%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 会遇到的许多问题。