Can I call sscanf mutliple times on the same string? - c

I'm trying to read a line from a file, I grab a line line using fgets. I then try to use sscanf to parse it. Sometimes I'll call sscanf and find out it returns the wrong number of arguments. So then I'll try reparse the same line string. Sometimes it works, sometimes it doesn't (which is leading me to believe that the problem isn't sscanf but something else in my code). Here's an example of what I mean:
i = sscanf(line,"%d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d\n", &faceV1, &faceUV1, &faceN1, &faceV2, &faceUV2, &faceN2, &faceV3, &faceUV3, &faceN3,
&faceV4, &faceUV4, &faceN4);
if(i == 12) {
//We gotta quad...
printf("Model.c: Quads not supported\n");
} else if(sscanf(line,"%d/%d/%d %d/%d/%d %d/%d/%d\n", &faceV1, &faceUV1, &faceN1, &faceV2, &faceUV2, &faceN2, &faceV3, &faceUV3, &faceN3) == 9) {
//Doesn't do what I expect!
...
However if I get rid of i = sscanf... and the check for i == 12 and go straight to if(sscanf(line,"%d/%d/%d %d/%d/%d %d/%d/%d\n", &faceV1, &faceUV1, &faceN1, &faceV2, &faceUV2, &faceN2, &faceV3, &faceUV3, &faceN3) == 9) it will work as expected.
So back to the title of this question, can I call sccanf multiple times on the same string? Am I calling it wrong? Or should I look elsewhere in my code for the problem?

Short answer YES you can sscanf the same string multiple times.
Your problem is that having "\n" in your string does not do what you expect...
It matches ANY white-space character space, tab, \r, and not just \n.
So you need to check for the end-of-line after scanf'ing.

Related

Printing another program in c

In the original code I have a line:
input = scanf("%c%c%c%c%c", &input_key[0], &input_key[1], &input_key[2], &input_key[3], &input_key[4]);
since I have to print the program out I did:
printf(" input = scanf(\"%c%c%c%c%c\", &input_key[0], &input_key[1], &input_key[2], &input_key[3], &input_key[4]);\n");
however the output came out to:
input = scanf("dd≡Ç", &input_key[0], &input_key[1], &input_key[2], &input_key[3], &input_key[4]);
How to fix this?
% is a special character in printf that is replaced by an input argument. If you want to print the % literal, you should escape it through %%.
So your code should be:
printf(" input = scanf(\"%%c%%c%%c%%c%%c\", &input_key[0], &input_key[1], &input_key[2], &input_key[3], &input_key[4]);\n");

How to get blank input with scanf

I have created a console-based program that get commands from the user. I wanted to check if the user give a blank input (just hit enter), it gives a message to the user. I used wscanf_s to get input from users. I have written the following code:
else if (!wcscmp(g_c_Commands, L"console"))
{
wchar_t console_command[MAX_PATH] = { 0 };
wscanf_s(L"%s", console_command, MAX_PATH - 1);
if (!wcscmp(console_command, L"--local"))
{
CallPsExecuteWindow(arg_computer_name);
}
else if (!wcscmp(console_command, L"--ip"))
{
wchar_t remote_host[MAX_PATH] = { 0 };
wscanf_s(L"%s", remote_host, MAX_PATH - 1);
CallPsExecuteWindow(remote_host);
}
else
{
wprintf(L"\n\t");
WarningMessage(L"%s", L"[Wrong] Usage: console --local / --ip [ADDRESS].");
wprintf(L"\n\n");
}
}
Instead of "%s", you should use "%[^ \t\n]" after skipping blanks:
console_command[0] = L'\0';
wscanf_s(L"%*[ \t]"); // skip blanks if any
wscanf_s(L"%[^ \t\n]", console_command, (unsigned)MAX_PATH); // read word, stop on white space
The first wscanf_s will fail if no blanks are pending, but you can ignore the error.
The second wscanf_s will fail if there are no more words pending on the line, ie: if the pending byte is a newline, console_command is unmodified so it still contains an empty string.
Parsing this input as wide strings is a major pain, most platforms have standardized on UTF-8 encoding, it is a shame you must deal with such cumbersome APIs.
It is also very disturbing to have to pass a unsigned int value as the number of elements in the destination array when the C Standard specifies that this extra argument should be a size_t which has a different width on most 64-bit platforms including Windows.

detect if a line is match to a format - in C

I have a file and I need to check if its lines are in the following format:
name: name1,name2,name3,name4 ...
(some string, followed by ":", then a single space and after that strings separated by ",").
I tried doing it with the following code:
int result =0;
do
{
result =sscanf(rest,"%[^:]: %s%s", p1,p2,p3);
if(result==3)
{
printf("invalid!");
fclose(fpointer);
return -1;
}
}while (fgets(rest ,LINE , fpointer) != NULL);
this works good for lines like: name: name1, name2 (with space between name1, and name2).
but it fails with the following line:
name : name1,name2
I want to somehow tell sscanf not to avoid this white space before the ":".
could someone see how ?
Thanks for helping!
This works for me:
result = sscanf(rest,"%[^*:]: %[^,],%s", p1, p2, p3);
Notice the * is used to consume the space (if any).

Parameters inside the function

I have a work to do in which I have to keep a loop inside the function expecting the following parameters:
-"i" to insert
-"s" to search
-"q" to quit
How do I keep this loop? I've looked up some options and it seems to be possible using a while or a switch, but I am not sure which is the best way to read those chars (with a fscanf perhaps?). I am also not sure how to read the things after the parameter "i" as the input would be "i word 9", so after detecting the i to insert I have to read a string and an int.
Anyone has any idea how to do this? I am sorry is this seems simple, but I am new to programming.
edit: Here is what I have so far
while (loop) {
fscanf(stdin,"%c",&par);
if (strcmp(&par,"i")){
scanf("%s %d",palavra,p);
raiz = insere(raiz,&palavra,p);
}
else if (strcmp(&par,"b")){
scanf("%s",palavra);
busca(raiz,&palavra);
}
else if (strcmp(&par,"q"))
loop = 0;
}
edit 2: This is what I have now, I am having problems reading the string and integer when the parameter is i, somehow it crashes the function
while (1) {
c = getchar();
if (c == 'f')
break;
else if (c == 'i'){
fscanf(stdin,"%s",&palavra);
scanf("%d",&p);
raiz = insere(raiz,palavra,p);
}
else if (c == 'b') {
scanf("%s",palavra);
busca(raiz,palavra);
}
}
Thanks in advance!
The code you have doesn't look too bad compared to what I believe you want. You can replace the "while (loop)" with "while (1)" and then your exist code "loop = 0;" with "break;" which is a bit more standard way of doing things. Also "fscanf(stdin..." is the same as "scanf(..." ... scanf will read from stdin by default. You might want to check the docs for strcmp because it returns 0 for an exact match and I don't think that will do what you want in your 'if' statements. You should be able to use scanf to read in the values you want, is it giving you an error?
You are using 3 separated scans. That means you can't input this "i word 9", but input one command or parameter at the time separated by EOL(pressing enter).. i, enter, word, enter, 9, enter ... Then the function should actually get further in those "if"s. With those scans you also should consider printing information about expected inputs ("Choose action q/i/f")
And I would recommend using something to test those inputs.
if (scanf("%d", &p) == 0) {
printf("Wrong input");
break;
}

How to read data from a text file

How do I read input from my text file? The input file is several lines long, and each line is of the format city city distance where there are two cities and the distance between them.
I have tried several things to read the input, but unfortunately those did not work. I need
to parse the individual values on each line. (Each line consists of 2 city names and the distance between them.) Any help would be appreciated.
data = fopen(argv[1],"r");
while(!EOF){
while(1){
c=fgetc(data);
inname=(char**)malloc(sizeof(char*));
if(c==' ')
mode++;
else if(c=='\n'){mode=0;
break;}
else {
switch(mode%3){
case 0;
for(i=0;fgetc(data)!=' ';i++){
if(inname[count]!=NULL) {count++;inname=(char**)malloc(sizeof(char*));}
inname[count][i]=fgetc(data);}
break;
case 1;
if(inname[count]!=NULL){ count++;inname=(char**)malloc(sizeof(char*));}
for(i=0;fgetc(data)!=' ';i++){
inname[count][i]=fgetc(data);}
break;
/*case 2;for(i=0;fgetc(data)!='\n';i++){
dist[say]=atoi(str);}}}*/
}}}count++;}
`
I think you should look into fscanf for reading formatted input like this.
To read a line containing two strings and an int, you would have something like:
fscanf(data, "%s %s %d", &city1, &city2, &distance);
To read multiple lines until EOF, your code should be of the following form:
while(fscanf(data, "%s %s %d", &city1, &city2, &distance)!=EOF) {
/* rest of your logic here */
}

Resources