c - 通过充满单词的数组(从文件中检索)来操作文件中的单词

标签 c

我使用 fgets 浏览了文件。 我将 fgets 返回的句子标记为 strtok 以检索单词 我将单词保存在 char*

数组中
while (fgets(chaine, TAILLE_MAX, fichier) != NULL) {
    chainetoken = strtok(chaine, " ");
    while (chainetoken != NULL) {              
        tableau[i] = chainetoken;
        chainetoken = strtok (NULL, " ");
        i++;
    }// it works wel
}
printf("%d \n", i);

现在,我想遍历包含文件单词的 char* (tableau[i]) 数组,以便找到由用户并在文件中找到它前后的 2 个词

printf("words to find?\n");
scanf("%s", mot_recherche);

for (j = 0; j < i; j++) {
    printf ("tableau %d.mot %s \n", i, tableau[i]); //tableau[0]=last word of the file
    if (strcmp(mot_recherche, tableau[i]) == 0)
        printf("this word exist \n");
} //doesn't work,it save only the last word of the array(of the file)!!!!

最佳答案

你犯了三个错误

1) 在

while (fgets(chaine, TAILLE_MAX, fichier) != NULL) 
{
   chainetoken=strtok(chaine," ");
   while (chainetoken != NULL)
   {              
      tableau[i]= chainetoken;
      chainetoken = strtok (NULL," ");
      i++;
    }// it works wel
}

你需要保存strtok结果的副本(strdup),否则你总是保存一个指向内部的指针由每个 fgets

修改的 chaine

2) strtok 的分隔符必须是 "\n",否则 '\n' 是 strtok 返回结果的一部分

3) 在

for (j=0; j<i; j++)
{
  printf ("tableau %d.mot %s \n",i,tableau[i]);//tableau[0]=last word of the file
  if (strcmp(mot_recherche,tableau[i])==0)
    printf("this word exist \n");
}//doesn't work,it save only the last word of the array(of the file)!!!!

您查看 tableau 的条目 i 而不是 j

补充说明:在 while 中,您需要检查 i 是否达到了 tableau 中的条目数,否则您将冒险编写


(编辑以解释为什么需要复制 strtok 的结果)

让那个程序像你一样使用strtok(没有重复):

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

int main()
{
  FILE * fichier = fopen("in", "r");

  if (fichier != NULL)
  {
#define TAILLE_MAX 32
    char chaine[TAILLE_MAX];
    char * chainetoken;
    char * tableau[16];
    int i = 0, j;

    while ((fgets(chaine, TAILLE_MAX, fichier) != NULL)  &&
           (i != sizeof(tableau)/sizeof(tableau[0])))
    {
      chainetoken=strtok(chaine," \n");
      while (chainetoken != NULL)
      {              
        tableau[i]= chainetoken;
        chainetoken = strtok (NULL," \n");
        i++;
      }
    }
    fclose(fichier);

    for (j = 0; j != i; ++j)
      printf("'%s'\n", tableau[j]);
  }

编译和执行:

/tmp % gcc -pedantic -Wextra f.c
/tmp % cat in
1234 5678
1 23 45 678
/tmp % ./a.out
'1'
'45'
'1'
'23'
'45'
'678'

预期的结果是看到1234 5678 1 23 45 678但事实并非如此,只有in第二行的contains是正确的(因为它是文件的最后一行)。

strtok 返回 chaines 的子字符串,每次返回非空指针时修改它以添加空字符,所以(我在空字符下方用 ' @')

  • fgets 读取第一行,chaine_包含"1234 5678\n@"
  • strtok 将“1234 5678\n@”中的空格替换为空字符并返回 chaine ("1234@5678\n@") 的地址内存在tableau[0]
  • strtok 用空字符替换 '\n' 并返回 chaine + 5 ("5678@") 被存储在 tableau[1]
  • strtok 的下一次调用返回空指针
  • fgets 读取下一行并修改 chaine 以包含“1 23 45 678\n@”
  • strtok 将 '1' 后的空格替换为 null char 并返回存储在 chaine ("1@23 045 678\n@") 中的地址画面[2]
  • strtok 将 '3' 之后的空格替换为空字符并返回 chaine + 2 ("23@45 678\n@") 被存储在 画面[3]
  • strtok 将 '5' 之后的空格替换为空字符并返回 chaine + 5 ("45@678\n@") 被存储在 画面[4]
  • strtok 用空字符替换 '\n' 并返回 chaine + 8 ("678@") 被存储在 tableau[5]
  • strtok 返回空指针

所以现在 chaine 包含“1@23@45@678@”,tableau 中的指针是:

  • tableau[0] = chaine = "1@23@45@678@",printf 产生'1'而不是预期的'1234'
  • tableau[1] = chaine + 5:“45@678@”,打印结果为 45 而不是预期的“5678”
  • tableau[2] = chaine:“1@23@45@678@”,printf 产生“1”
  • tableau[3] = chaine+2 : "23@45@678@", printf 产生 '23'
  • tableau[4] = chaine+5:“45@678@”,printf 生成“45”
  • tableau[5] = chaine+8 : "678@", printf 产生 '678'

这就是为什么需要复制 strtok 的结果的原因:

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

int main()
{
  FILE * fichier = fopen("in", "r");

  if (fichier != NULL)
  {
#define TAILLE_MAX 32
    char chaine[TAILLE_MAX];
    char * chainetoken;
    char * tableau[16];
    int i = 0, j;

    while ((fgets(chaine, TAILLE_MAX, fichier) != NULL)  &&
       (i != sizeof(tableau)/sizeof(tableau[0])))
    {
      chainetoken=strtok(chaine," \n");
      while (chainetoken != NULL)
      {              
        tableau[i]= strdup(chainetoken);
        chainetoken = strtok (NULL," \n");
        i++;
      }
    }
    fclose(fichier);

    for (j = 0; j != i; ++j) {
      printf("'%s'\n", tableau[j]);
      free(tableau[j]); /* to avoid memory leak */
    }
  }
}

编译和执行:

/tmp % gcc -pedantic -Wextra f.c
/tmp % cat in
1234 5678
1 23 45 678
/tmp % ./a.out
'1234'
'5678'
'1'
'23'
'45'
'678'

关于c - 通过充满单词的数组(从文件中检索)来操作文件中的单词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55092551/

相关文章:

C:排序方法分析

c - linux子recvfrom没有正常工作

c - 关于循环缓冲区中简洁索引处理的建议

c - 激活记录长度

c++ - 可以将非常量字符数组传递给常量字符数组吗?

c - 如何在 C 中的头文件中初始化结构的结构?

c - C.fgets中的简单网络服务器导致无限循环读取浏览器请求

c - 错误 sliceShiftLeft() 函数

c - 以下 C 程序的输出是什么?

c++ - 使用 LibTar 提取文件