我使用 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
修改的 chaine2) 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/