%79[^\n] 和 %79[^\n]\n 的区别
Difference between %79[^\n] and %79[^\n]\n
我有两个 C 程序。
第一个:
#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;
}
第二个:
#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;
}
我不明白为什么第一个代码用指令 %79[^\n]
输出我的文件的所有行,而第二个代码只用这个指令输出所有行 %79[^\n]\n
并且只输出一行文本如果我写 %79[^\n]
请解释一下两个代码和其中两个指令的区别%79[^\n]
和%79[^\n]
不在转换规范中的任何 空白字符将丢弃输入中的任意数量的任何连续空白字符。因此,您的 \n
将吃掉后者中的那些空白字符。
现在,%f
将 丢弃所有前面的空白字符,直到找到一个非空白字符,并从该字符开始转换。 %[^\n]
不会丢弃任何字符 - 它从输入中的第一个字符开始转换。
导致问题的不是格式说明符本身,而是它如何与 其他 格式说明符一起使用。
如果您阅读例如this scanf
(and family) reference 你会看到 "%["
格式不会跳过前导白色-space,而大多数其他格式(例如 "%f"
) 做.
当您在第一个程序中读取输入时,您不需要 scanf
函数来读取结束换行符(这是一个白色-space 字符),因为下一次调用scanf
将导致 "%f"
格式说明符在尝试读取浮点值之前跳过该换行符。
对于第二个程序,如果你有 "%79[^\n]"
那么 fscanf
将读取到但不包括第一个换行符。然后在循环的下一次迭代中,相同的格式将尝试读取字符,直到出现换行符,但输入中的第一个字符 是 换行符,因此实际上不会读取任何内容。
如果添加尾随换行符(任何白色-space 字符都可以),那么 fscanf
函数将跳过换行符,因此下一次调用 fscanf
将读取下一行正确。您可以通过在格式中使用 leading space 来完成同样的事情。 IE。而不是 "%79[^\n]\n"
你可以
" %79[^\n]"
.
话虽如此,如果您想阅读行,请改用 fgets
。这就是它所做的,没有 scanf
会遇到的许多问题。
我有两个 C 程序。
第一个:
#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;
}
第二个:
#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;
}
我不明白为什么第一个代码用指令 %79[^\n]
输出我的文件的所有行,而第二个代码只用这个指令输出所有行 %79[^\n]\n
并且只输出一行文本如果我写 %79[^\n]
请解释一下两个代码和其中两个指令的区别%79[^\n]
和%79[^\n]
不在转换规范中的任何 空白字符将丢弃输入中的任意数量的任何连续空白字符。因此,您的 \n
将吃掉后者中的那些空白字符。
现在,%f
将 丢弃所有前面的空白字符,直到找到一个非空白字符,并从该字符开始转换。 %[^\n]
不会丢弃任何字符 - 它从输入中的第一个字符开始转换。
导致问题的不是格式说明符本身,而是它如何与 其他 格式说明符一起使用。
如果您阅读例如this scanf
(and family) reference 你会看到 "%["
格式不会跳过前导白色-space,而大多数其他格式(例如 "%f"
) 做.
当您在第一个程序中读取输入时,您不需要 scanf
函数来读取结束换行符(这是一个白色-space 字符),因为下一次调用scanf
将导致 "%f"
格式说明符在尝试读取浮点值之前跳过该换行符。
对于第二个程序,如果你有 "%79[^\n]"
那么 fscanf
将读取到但不包括第一个换行符。然后在循环的下一次迭代中,相同的格式将尝试读取字符,直到出现换行符,但输入中的第一个字符 是 换行符,因此实际上不会读取任何内容。
如果添加尾随换行符(任何白色-space 字符都可以),那么 fscanf
函数将跳过换行符,因此下一次调用 fscanf
将读取下一行正确。您可以通过在格式中使用 leading space 来完成同样的事情。 IE。而不是 "%79[^\n]\n"
你可以
" %79[^\n]"
.
话虽如此,如果您想阅读行,请改用 fgets
。这就是它所做的,没有 scanf
会遇到的许多问题。