我用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'