fscanf写入字符串数组错误

fscanf写入字符串数组错误,c,scanf,C,Scanf,我正在使用fscanf逐字读取一个文件,并将它们写入char**数组 如果要打印当前索引,它可以正常工作,但在完全写入完成后,打印数组会导致错误的输出 char **stop_words = (char**)malloc(1000*sizeof(char*)); FILE *fp; fp = fopen("englishstopwords.txt", "r"); int i = 0; while(!feof(fp)) { fscanf(fp,&

我正在使用fscanf逐字读取一个文件,并将它们写入char**数组

如果要打印当前索引,它可以正常工作,但在完全写入完成后,打印数组会导致错误的输出

char **stop_words = (char**)malloc(1000*sizeof(char*));

FILE *fp;
fp = fopen("englishstopwords.txt", "r");

int i = 0;
while(!feof(fp)) {
    fscanf(fp,"%s\n", &stop_words[i]);
    // printf("%s\n", &stop_words[i]); //this works fine
    i++;
}
// for (int i = 0; i < 1000; i++) { //this works buggy
    // printf("%s\n", &stop_words[i]);
// }
fclose(fp); 
char**stop_words=(char**)malloc(1000*sizeof(char*);
文件*fp;
fp=fopen(“englishstopwords.txt”,“r”);
int i=0;
而(!feof(fp)){
fscanf(fp、%s\n、&stop_单词[i]);
//printf(“%s\n”,&stop_words[i]);//这很好用
i++;
}
//对于(inti=0;i<1000;i++){//这是一个很好的解决方案
//printf(“%s\n”和停止字[i]);
// }
fclose(fp);
断开的打印看起来像这样:
即时重要指数

工作打印如下所示:
立即
重要性
重要信息
索引

它们之间有什么区别?

问题出在哪里 您的内存分配根本上是错误的

char**stop_words=(char**)malloc(1000*sizeof(char*)仅分配能够存储1000个指针的内存块

stop_words[0]
stop_words[999]
的内容未定义,它们都是
malloc()
返回后的垃圾值

有时写
停止单词[i]
看起来不错,但幸运的是,垃圾是指向映射内存的指针(尽管仍然很糟糕,您可能因此而导致内存损坏)

解决方法就是分配另一块内存来包含文件中的数据


错误的目标缓冲区 这部分

fscanf(fp,"%s\n", &stop_words[i]);
写入分配给
malloc()
的指针数组。表达式的类型
&stop_words[i]
本身与
%s
不匹配,您应该真正激活警告标志,并且一个好的编译器应该在默认情况下警告您这一点

潜在缓冲区溢出 您读取行的方法是危险的,因为使用
%s
fscanf
不关心缓冲区有多大,因此您的程序容易发生缓冲区溢出

解决方法是,您可以使用
fgets
并指定缓冲区的大小

如果一行为缓冲区分配的内存多于,则可以
realloc()
。要检测此情况,可以查看返回的最后一个字符。如果它是换行符,则它是行的结尾,否则它可能是文件的结尾或字符数超过缓冲区大小的行(因此您可以决定realloc)


解决这个问题
EnglishTopWords.txt(用于测试的示例文件)
i
我
我的
我自己
我们
我们的
测试长线12312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312312323123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123123
我们的
我们自己

测试c

#包括
#包括
#包括
#包括
#定义最大字数(1000u)
#定义初始分配(128u)
内部主(空)
{
字号,总字数;
文件*fp;
char**stop_words=malloc(MAX_words*sizeof(*stop_words));
/*TODO:Handle`stop\u words==NULL`*/
fp=fopen(“englishstopwords.txt”,“r”);
/*TODO:句柄'fp==NULL`*/
i=0;
while(true){
尺寸长度=0;
char*ret,*buf=malloc(INIT_ALLOC*sizeof(*buf));
/*TODO:句柄'buf==NULL`*/
ret=buf;
关于fgets:
ret=fgets(ret,初始分配,fp);
if(ret==NULL){
/*我们已经到了文件的末尾*/
如果(len==0){
/*
*扔掉缓冲区,这是未使用的
*/
免费(buf);
}否则{
/*最后一行缓冲区*/
停止字[i++]=buf;
}
打破
}
len=strlen(buf);
如果(buf[len-1]!='\n'){
/*
*
*我们没有看到LF,这是指这条线
*具有超过'INIT_ALLOC'个字符或
*它可能是EOF。
*
*/
ret=realloc(buf,(len+1+INIT_ALLOC)*sizeof(*buf));
/*TODO:句柄'ret==NULL`*/
buf=ret;
/*
*将指针向右移动(字符串末尾)。
*因为这一行还没有完全读过。
*
*我们把下一个'fgets'缓冲区放在这个结尾
*绳子。
*/
ret+=len;
转到re_fgets;
}
/*TODO:在Windows平台上修剪CR*/
/*修剪左前*/
buf[len-1]='\0';
停止字[i++]=buf;
如果(i>=最大字数){
/*
*TODO:如果你愿意,你可以做realloc(停止单词…)
*我想。
*/
打破
}
}
fclose(fp);
总数=i;
对于(i=0;i

编译并运行
ammarfaizi2@integral:/tmp$cat englishstopwords.txt
我
我
我的
迈塞尔