Reputation: 69
I have two C programs.
First:
#include <stdio.h>
int main(int argc, char *argv[]){
float latitude;
float longitude;
char info[80];
int started = 0;
puts("data=[");
while ((scanf("%f,%f,%79[^\n]",&latitude,&longitude, info)) == 3){
if (started)
printf(",\n");
else
started = 1;
if ((latitude < -90) || (latitude > 90)){
fprintf(stderr,"Wrong latitude %f\n", latitude);
return 2;
}
if ((longitude < -180) || (longitude > 180)){
fprintf(stderr,"Wrong longitude %f\n", longitude);
return 2;
}
printf("{latitude: %f, longitude: %f, info: '%s'}", latitude, longitude, info);
}
puts("\n]");
return 0;
}
And second:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
char line[80];
FILE *in = fopen("spooky.csv","r");
FILE *file1 = fopen("ufos.csv","w");
FILE *file2 = fopen("disappearances.csv","w");
FILE *file3 = fopen("others.csv","w");
while(fscanf(in,"%79[^\n]\n",line)==1){
if (strstr(line, "UFO"))
fprintf(file1,"%s\n",line);
else if (strstr(line, "Disappearance"))
fprintf(file2, "%s\n", line);
else
fprintf(file3,"%s\n",line);
}
fclose(file1);
fclose(file2);
fclose(file3);
return 0;
}
I do not understand why the first code outputs all lines of the my file with instruction %79[^\n]
and the second code outputs all lines only with this instruction %79[^\n]\n
and output only one line of text if I write %79[^\n]
Please, explain me the differences between two codes and two instructions in them %79[^\n]
and %79[^\n]
Upvotes: 0
Views: 491
Reputation: 409166
It's not the format specifier itself that is causing the problem, but how it is used in conjunction with other format specifiers.
If you read e.g. this scanf
(and family) reference you will see that the "%["
format does not skip leading white-space, while most other formats (like for example "%f"
) do.
When you read the input in the first program, you don't need the scanf
function to read the ending newline (which is a white-space character) because the next call to scanf
will cause the "%f"
format specifier to skip that newline before it attempts to read a floating point value.
For the second program, if you have "%79[^\n]"
then fscanf
will read until but not including the first newline. Then in the next iteration of the loop the same format will attempt to read characters until there is a newline, but the very first character in the input is a newline so nothing will be actually read.
If you add the trailing newline (any white-space character would work) then the fscanf
function will skip the newline, so the next call to fscanf
will read the next line properly. You can accomplish the same thing by using a leading space in your format. I.e. instead of "%79[^\n]\n"
you could have
" %79[^\n]"
.
With that said, if you want to read lines, then use fgets
instead. That's what it does, without many of the problems that scanf
will have.
Upvotes: 2
Reputation: 133899
Any whitespace characters not in conversion specifications will discard any number of any consecutive whitespace characters in the input. Therefore your \n
will eat those whitespace characters in the latter.
Now, %f
will discard all preceding whitespace characters until it finds a non-whitespace character, and start the conversion from that one. %[^\n]
will not discard any characters - it starts conversion from the first character in the input.
Upvotes: 1