我用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])数组,以便找到用户输入的单词,并找到文件中该单词前面和后面的两个单词
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修改
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)!!!!

你看的是表的条目i而不是j
附加说明:在这段时间内,你需要检查我是否达到了表中的条目数量,否则你就冒着风险把它写出来。
(编辑以解释为什么需要复制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的第二行的包含是正确的(因为它是文件的最后一行)。
strtok返回链的子字符串,每次返回非空指针时修改它以添加空字符,因此(我在空字符下面用“@”表示)
fgets读取第一行,chaine包含“12345678\n@”
strtok用空字符替换“12345678\n@”中的空格,并返回在tableau[0]中存储的链的地址(“1234@5678\n@”)
strtok用空字符替换“\n”,并返回在tableau[1]中存储的chaine+5(“5678@”)
strtok的下一次调用返回空指针
fgets读取下一行并将chaine修改为包含“12345678\n@”
strtok用空字符替换“1”后的空格,并返回存储在tableau[2]中的链地址(“1@23 045 678\n@”)
strtok用空字符替换“3”后的空格,并返回在tableau[3]中存储的chaine+2(“23@45 678\n@”)
strtok用空字符替换'5'后面的空格,并返回在tableau[4]中存储的chaine+5(“45@678\n@”)
strtok用空字符替换“\n”,并返回存储在tableau[5]中的chaine+8(“678@”)
strtok返回空指针
所以现在chaine包含“1@23@45@678@”,tableau中的指针是:
tableau[0]=chaine=“1@23@45@678@”,printf生成“1”,而不是预期的“1234”
tableau[1]=chaine+5:“45@678@”,print生成45,而不是预期的“5678”
tableau[2]=链:“1@23@45@678@”,printf生成“1”
tableau[3]=链+2:“23@45@678@”,printf生成“23”
tableau[4]=链子+5:“45@678@”,printf产生“45”
tableau[5]=链+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'

08-27 19:58