Equivalent Chapel functionality for C fgets function - io

What is some Chapel code that is equivalent to C's fgets function?
`fgets(buffer, sizeof(buffer), stdin)`
The above call to fgets reads data from stdin until a newline character is encountered. The Chapel readln function stops reading when whitespace is encountered. I want readln to read until a newline character is encountered. There is iostringformat.toend that appears to be the solution, but how do I get stdin to behave as if that is enabled?

Use readline instead of readln. See https://chapel-lang.org/docs/modules/standard/IO.html#IO.channel.readline
Try this program for example:
config const fname = "test.txt";
var r = openreader(fname);
var line:string;
while r.readline(line) {
write("I just read: ", line);
}

Related

What encoding does nodejs use for arguments in child_process.spawn and child_process.execFile?

In NodeJS, child_process.execFile and .spawn take this parameter:
args <string[]> List of string arguments.
How does NodeJS encode the strings you pass in this array?
Context: I'm writing a nodejs app which adds metadata (often including non-ascii characters) to an mp3.
I know that ffmpeg expects utf8-encoded arguments. If my nodejs app invokes child_process.execFile("ffmpeg",["-metadata","title="+myString], {encoding:"utf8") then how will nodejs encode myString in the arguments?
I know that id3v2 expects latin1-encoded arguments. If my nodejs app invokes child_process.execFile("id3v2",["--titl",myString], {encoding:"latin1") then how will nodejs encode myString in the arguments?
I see that execFile and spawn both take an "encoding" argument. But the nodejs docs say "The encoding option can be used to specify the character encoding used to decode the stdout and stderr output." The docs say nothing about the encoding of args.
Answer: NodeJS always encodes the args as UTF-8.
I wrote a simplistic C++ app which shows the raw truth of the bytes that are passed into its argv:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("argc=%u\n", argc);
for (int i = 0; i < argc; i++)
{
printf("%u:\"", i);
for (char *c = argv[i]; *c != 0; c++)
{
if (*c >= 32 && *c < 127)
printf("%c", *c);
else
{
unsigned char d = *(unsigned char *)c;
unsigned int e = d;
printf("\\x%02X", e);
}
}
printf("\"\n");
}
return 0;
}
Within my NodeJS app, I got some strings that I assuredly knew what they came from:
const a = Buffer.from([65]).toString("utf8");
const pound = Buffer.from([0xc2, 0xa3]).toString("utf8");
const skull = Buffer.from([0xe2, 0x98, 0xa0]).toString("utf8");
const pound2 = Buffer.from([0xa3]).toString("latin1");
The argument of toString indicates that the raw bytes in the buffer should be understood as if the buffer is in UTF-8 (or latin1 in the last case). The result is that I have four strings whose contents I unambiguously know is correct.
(I understand that Javascript VMs typically store their strings as UTF16? The fact that pound and pound2 behave the same in my experiments proves that the provenance of the strings doesn't matter.)
Finally I invoked execFile with these strings:
child_process.execFileAsync("argcheck",[a,pound,pound2,skull],{encoding:"utf8"});
child_process.execFileAsync("argcheck",[a,pound,pound2,skull],{encoding:"latin1"});
In both cases, the raw bytes that nodejs passed into argv were UTF-8 encodings of the strings a,pound,pound2,skull.
So how can we pass latin1 arguments from nodejs?
The above explanation shows it's IMPOSSIBLE for nodejs to pass in any latin1 character in the range 127..255 to child_process.spawn/execFile. But there's an escape hatch involving child_process.exec:
Example: this string "A £ ☠"
stored internally in Javascript's UTF16 as "\u0041 \u00A3 \u2620"
encoded in UTF-8 as "\x41 \xC2\xA3 \xE2\x98\xA0"
encoded in latin1 as "\x41 \xA3 ?" (the skull-and-crossbones is inexpressible in latin1)
Unicode chars 0-127 are same as latin1, and encode into utf-8 the same as latin1
Unicode chars 128-255 are same as latin1, but encode differently
Unicode chars 256+ don't exist in latin1/.
// this would encode them as utf8, which is wrong:
execFile("id3v2", ["--comment", "A £ ☠", "x.mp3"]);
// instead we'll use shell printf to bypass nodejs's wrongful encoding:
exec("id3v2 --comment \"`printf "A \xA3 ?"`\" x.mp3");
Here's a handy way to turn a string like "A £ ☠" into one like "A \xA3 ?", ready to pass into child_process.exec:
const comment2 = [...comment]
.map(c =>
c <= "\u007F" ? c : c <= "\u00FF"
? `\\x${("000" + c.charCodeAt(0).toString(16)).substr(-2)}` : "?")
)
.join("");
const cmd = `id3v2 --comment \"\`printf \"${comment2}\"\`\" \"${fn}\"`;
child_process.exec(cmd, (e, stdout, stderr) => { ... });

I used cin to get a string input as shown below in the code and it works fine. Is it alright?

#include<iostream>
#include<stdio>
using namespace std;
int main()
{ int n;
char s[15];
cin>>n;
cin>>s;
cout<<n*2<<"\n";
cout<<s;
return 0;
}
I tried with gets and fgets function but they don't work just after cin..
I'm kind of confused on what you are asking here, but I have noticed something here that can be fixed.
Yes the code you have compiles and it works. However, it could be improved.
When prompted to input something to your char array, you'll notice that it will not accept whitespaces. So if I input, Jon Smith, the output will only be Jon and the rest of the string input is cut off. To fix this, you will need to make a call the the getline() function.
The documentation of getline() states:
Extracts characters from is and stores them into str until the delimitation character delim is found (or the newline character, '\n'..)
This will allow you to get whitespaces from the input and put the entire input back into a string.
If you add this function call to your code where the second input prompt lies and you were to run the code, you would notice that you will only get prompted once and then the program would finish running before the second prompt appears to be executed. This is because getline() does not ignore leading whitespace characters and it stops reading any further because the cin>> before it is seen as a newline character.
To make getline() work with cin>>, you must use cin.ignore() before the call to getline(). Below is some code that I wrote to make this adjustment:
// Example program
#include <iostream>
#include <string>
using namespace std;
int main()
{
int n;
string s; //using string allows us to use getline()
cout<<"Enter a number: "; //Let user know they are being prompt for number
cin>>n;
cin.ignore(); //ignore the leading newline
cout<<"Enter a string: "; //let user know being prompt for string
getline (cin,s);
cout<<n*2<<"\n";
cout<<s;
return 0;
}
Again, the code you have works and compiles. I'm not sure if my solution is the answer you are hoping to get but I hope that you are able to find this useful! Cheers!

strlen not counting newlines?

I embedded lua into my project and came across a strange (for me) behavior of strlen and lua interpreting. I was trying to load a string, containing lua code, with luaL_loadbuffer and it consistently threw error of "unexpected symbol" on whatever was the last line of the lua code, except if the whole chunk was written in one line. so for example:
function start()
print("start")
end
would always results error: unexpected symbol on 3rd line, but
function start() print("start") end
loads successfully.
I figured out that loading the same chunk with luaL_loadstring, gives no errors, and saw that it uses strlen to determine the length of the specified string (I used std::string::size) and also that using strlen to provide the length of the string to the luaL_loadbuffer also results in successful loading.
Now the question was: what may be the difference between strlen and std::string::size, and at my most surprise the answer is that strlen is not counting new lines ('\n'). That is:
const char* str = "this is a string\nthis is a newline";
std::string str2(str);
str2.size(); // gives 34
strlen(str); // gives 33
The difference between the size, and the value returned by strlen was always the number of new line characters.
My questions are:
Does strlen really not counting newlines or I am missing something?
How do newlines affect the interpretation of the lua code internally?
I am using vs 2015 and lua 5.3.0
EDIT:
My first example was not exact, and did not produce the detailed effect for me neither, but I was able to recreate the problem from the original code:
std::fstream _Stream("test.lua", std::ios::ate | std::ios::in);
std::string _Source;
if(_Stream.is_open()) {
_Source.resize(_Stream.tellg());
_Stream.seekg(0, std::ios::beg);
_Stream.read(&_Source[0], _Source.size());
_Stream.close();
}
std::cout << "std::string::size() = " << _Source.size() << std::endl;
std::cout << "strlen() = " << strlen(_Source.c_str()) << std::endl;
The content of test.lua is "function start()\n\tprint("start")\nend\n\nstart()"
The difference is the number of newlines:
http://i.stack.imgur.com/y0QOW.png
Window's line endings (CR+LF) are two characters making the file size larger than the number of characters in the string so the resize operation uses the file size and not the length of the null-terminated string. strlen reports the length of the null-terminated string and counts \n as a single character. You can make the size match the length of the C string by resizing the string to match afterwards:
_Source.resize(strlen(_Source.c_str()) + 1);

How to transmit ASCII by WriteFile function

I am writing following codes to transmit ASCII(62), ASCII(42),ASCII(62),ASCII(112) through serial port.
DWORD written;
WriteFile(serialHandle,">>p",strlen(">>p"),&written,NULL);
But right now I want to transmit ASCII(4).ASCII(0) also, but I don't know how to write them into char type.
If I write: WriteFile(serialHandle, 4,1, &written, NULL); the VC++ system will give me an error message.
Would you please help me to re-write WriteFile function to meet my requirement?
You do not have to use " quotes with WriteFile. Seems like you should learn to use arrays.
char buf[2];
buf[0] = 4;
buf[1] = 0;
WriteFile(serialHandle, buf, 2, &written, NULL);

CreateProcess does not return extected value

I want to send the double quote character to my CreateProcess function. How can I do the correct way? I want to send all of this characters: "%h"
CreateProcess(L"C:\\identify -format ",L"\"%h\" trustedsnapshot.png",0,0,TRUE,NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW,0,0,&sInfo,&pInfo);
note: "identify" is an Imagemagick program.
Here is the full code:
int ExecuteExternalFile()
{
SECURITY_ATTRIBUTES secattr;
ZeroMemory(&secattr,sizeof(secattr));
secattr.nLength = sizeof(secattr);
secattr.bInheritHandle = TRUE;
HANDLE rPipe, wPipe;
//Create pipes to write and read data
CreatePipe(&rPipe,&wPipe,&secattr,0);
STARTUPINFO sInfo;
ZeroMemory(&sInfo,sizeof(sInfo));
PROCESS_INFORMATION pInfo;
ZeroMemory(&pInfo,sizeof(pInfo));
sInfo.cb=sizeof(sInfo);
sInfo.dwFlags=STARTF_USESTDHANDLES;
sInfo.hStdInput=NULL;
sInfo.hStdOutput=wPipe;
sInfo.hStdError=wPipe;
CreateProcess(L"C:\\identify",L" -format \"%h\" trustedsnapshot.png",0,0,TRUE,NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW,0,0,&sInfo,&pInfo);
CloseHandle(wPipe);
char buf[100];
DWORD reDword;
CString m_csOutput,csTemp;
BOOL res;
do
{
res=::ReadFile(rPipe,buf,100,&reDword,0);
csTemp=buf;
m_csOutput+=csTemp.Left(reDword);
}while(res);
//return m_csOutput;
float fvar;
//fvar = atof((const char *)(LPCTSTR)(m_csOutput)); ori
//fvar=atof((LPCTSTR)m_csOutput);
fvar = _tstof(m_csOutput);
const size_t len = 256;
wchar_t buffer[len] = {};
_snwprintf(buffer, len - 1, L"%d", fvar);
MessageBox(NULL, buffer, L"test print createprocess value", MB_OK);
return fvar;
}
I need this function to return the integer value from the CreateProcess.
The way you wrote it should work OK, or do you have any problems with it?
Your problem is not the quotes. There are two problems with the way you pass parameters to CreateProcess. The first is that the command line passed in the second argument should include the name of the command (that is, it should include the value for "argv[0]"), the second is that the redirection (> testt.txt) is not handled by the CreateProcess API,. Unless c:\identify expects such arguemnts, you should not include this in the command line.

Resources