fscanf() 如何进入下一行?

fscanf() how to go in the next line?

所以我在一个文件中有一大堆文本,我需要识别 $ 符号之间的一些单词并将它们称为数字,然后在另一个文件中打印修改后的文本以及数字对应的内容。 行也没有定义,列最多 80 个字符。

例如:

I $like$ cats.  
I [1] cats.  
[1] --> like

我就是这么做的:

    #include <stdio.h>
    #include <stdlib.h>

    #define N 80
    #define MAX 9999
    int main()
    {
        FILE *fp;
        int i=0,count=0;
        char matr[MAX][N];

        if((fp = fopen("text.txt","r")) == NULL){
            printf("Error.");
            exit(EXIT_FAILURE);
        }

        while((fscanf(fp,"%s",matr[i])) != EOF){
            printf("%s ",matr[i]);
            if(matr[i] == '[=11=]')
                printf("\n");

            //I was thinking maybe to find two $ but Idk how to replace the entire word     
            /*                                 
            if(matr[i] == '$')
                count++;
            if(count == 2){
                ...code...
            }
            */
            i++;
        }



        fclose(fp);
        return 0;
   }

我的问题是 fscanf 无法识别 '[=12=]',所以当我打印数组时它不会进入下一行。我也不知道如何替换 $word$有一个数字。

使用 fread() 将文件内容读取到 char[] 缓冲区。然后遍历这个缓冲区,每当你找到一个 $ 你执行一个 strncmp 来检测用哪个值替换它(记住,在单词的末尾有第二个 $)。要用数字替换 $word$,您需要缩小或扩展单词位置的缓冲区 - 这取决于 ascii 格式数字的字符串大小(在 google 上查找解决方案,通常你应该能够使用 memmove)。然后你可以将数字写入洞穴,这是由于扩展缓冲区而产生的(也只是覆盖 $word$ )。 然后将缓冲区写入文件,覆盖其之前的所有内容。

在 select 情况下,

fscanf() 是否识别“\0”,但这不是这里的问题。

代码需要检测'\n'fscanf(fp,"%s"... 不会那样做。 "%s" 指示的第一件事是消耗(而不是保存)任何领先的白色-space,包括 '\n'。使用 fgets().

读取一行文本

一次简单地读取 1 行。然后沿着缓冲区前进寻找单词。
以下使用 "%n" 跟踪缓冲区扫描停止的距离。

// more room for \n [=10=]
#define BUF_SIZE (N + 1 + 1) 
char buffer[BUF_SIZE];

while (fgets(buffer, sizeof buffer, stdin) != NULL) {
  char *p = buffer;
  char word[sizeof buffer];
  int n;
  while (sscanf(p, "%s%n", word, &n) == 1) {
    // do something with word
    if (strcmp(word, "$zero$") == 0) fputs("0", stdout);
    else if (strcmp(word, "$one$") == 0) fputs("1", stdout);
    else fputs(word, stdout);
    fputc(' ', stdout);
    p += n;
  }
  fputc('\n', stdout);
}

fscanf("%s") 不仅会一次读取一个以空格分隔的字符串,还会吃掉这些字符串之间的所有空格,包括行终止符。如果你想在输出中重现输入空白,正如你的例子所建议的那样,那么你需要一种不同的方法。

Also lines are not defined and columns should be max 80 characters.

我认为这意味着 number 行是事先不知道的,可以假设没有一行包含超过 80 个字符(不算任何行终止符)。

当你说

My problem is that fscanf doesn't recognize '[=25=]' so it doesn't go in the next line when I print the array

我猜你说的是这段代码:

        char matr[MAX][N];
            /* ... */
            if(matr[i] == '[=10=]')

鉴于 matr 的声明,给定的条件将 总是 评估为 false,而不管任何其他考虑。 fscanf() 根本不考虑。 matr[i] 的类型是 char[N],类型为 charN 个元素的数组。计算结果为指向数组第一个元素的指针,该指针永远不会是 NULL。看起来您正在尝试确定何时编写换行符,但与此方法类似的任何方法都无法做到这一点。

我建议您首先采纳@Barmar 的建议,通过 fgets() 逐行阅读。可能看起来像这样:

char line[N+2]; /* N + 2 leaves space for both newline and string terminator */

if (fgets(line, sizeof(line), fp) != NULL) {
    /* one line read; handle it ... */
} else {
    /* handle end-of-file or I/O error */
}

然后对于你阅读的每一行,用你喜欢的任何方式解析出 "$word$" 标记,并输出所需的结果(除了 $ 分隔的标记之外的所有内容;括号替换编号对于每个令牌)。当然,您需要记住替换标记以供以后输出。记得制作 副本 ,因为缓冲区将在每次读取时被覆盖(如果按照我上面的建议完成)。