C 标准缓冲问题
我已经写了这个代码C 标准缓冲问题,c,stdout,C,Stdout,我已经写了这个代码 #include<stdio.h> #include<assert.h> #include<stdlib.h> char *list[20],*story[100]; FILE*listfile; FILE*infile; FILE*outfile; int check(char*string) { int i=0; while(list[i]!=NULL) { if(strcmp(string,list[
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
char *list[20],*story[100];
FILE*listfile;
FILE*infile;
FILE*outfile;
int check(char*string)
{
int i=0;
while(list[i]!=NULL)
{
if(strcmp(string,list[i])==0){return 1;};
i++;
};
return 0;
};
void print_d(int d){ printf(" debug %d ",d);};
int main(int argc,char**argv){
assert(argc==4);
printf("hello \n");
//assigning the file pointers in their respective modes
printf("%s %s %s ",argv[1],argv[2],argv[3]);
listfile=fopen(argv[1],"r");
print_d(12);
infile=fopen(argv[2],"r");
outfile=fopen(argv[3],"w");
print_d(0);
int i=0; /* the infamous 'i' */
while(1)
{
if(feof(listfile)!=0)
{ break;};
list[i]=malloc(sizeof(char [15]));
fscanf(listfile,"%s[^\n]",list[i]);
i++;
}
i=0;
print_d(1);
while(1)
{
if(feof(infile)!=0)
{ break;};
story[i]=malloc(sizeof(char [25]));
fscanf(infile,"%s",story[i]);
i++;
}
fclose(infile);
fclose(listfile);
i=0;
print_d(2);
while(1)
{
if(check(story[i])==1)
{ fprintf(outfile,"%s","censored");}
else
{
fprintf(outfile,"%s",story[i]);
};
};
print_d(3);
fclose(outfile);
i=0;
while(list[i]!=NULL)
{ free(list[i]);};
return 0;
}
#包括
#包括
#包括
字符*列表[20],*故事[100];
文件*列表文件;
文件*填充;
文件*输出文件;
整数检查(字符*字符串)
{
int i=0;
while(列表[i]!=NULL)
{
if(strcmp(string,list[i])==0{return 1;};
i++;
};
返回0;
};
无效打印d(int d){printf(“调试%d”,d);};
int main(int argc,字符**argv){
断言(argc==4);
printf(“hello\n”);
//以各自的模式分配文件指针
printf(“%s%s%s”,argv[1],argv[2],argv[3]);
listfile=fopen(argv[1],“r”);
打印(12);
infle=fopen(argv[2],“r”);
outfile=fopen(argv[3],“w”);
打印d(0);
int i=0;/*臭名昭著的“i”*/
而(1)
{
如果(feof(listfile)!=0)
{break;};
list[i]=malloc(sizeof(char[15]);
fscanf(列表文件“%s[^\n]”,列表[i]);
i++;
}
i=0;
打印d(1);
而(1)
{
如果(feof(infle)!=0)
{break;};
故事[i]=malloc(sizeof(char[25]);
fscanf(填充,“%s”,故事[i]);
i++;
}
fclose(infle);
fclose(列表文件);
i=0;
打印(2);
而(1)
{
如果(检查(故事[i])==1)
{fprintf(输出文件,“%s”,“已审查”);}
其他的
{
fprintf(输出文件,“%s”,故事[i]);
};
};
打印(3);
fclose(输出文件);
i=0;
while(列表[i]!=NULL)
{free(list[i]);};
返回0;
}
随后出现了以下问题
[1] 输出是一个hello,后跟一个seg故障
这就是事情变得有趣的地方
如果我修改
printf(“%s%s%s”,argv[1],argv[2],argv[3])
到
printf(“%s%s%s\n”,argv[1],argv[2],argv[3])
输出是一个“hello”,后跟三个文件名,然后是一个segfault
在用户danfuzz指出我应该将print_d debug改为print to stderr(我做到了)…调试打印现在可以正常工作了。所以我想一个更好的问题是,为什么会发生这种情况,以及防止这种情况发生的步骤
对于经验丰富的程序员来说,这似乎是一个微不足道的问题,但是请注意,早期版本(上面代码中的版本)在seg故障之前没有打印出任何消息,这导致我得出结论,在事件/文件打开的命令行部分发生了一些事情。与其在论坛上猜测或询问,不如运行一个调试器。如果在linux上工作,gdb将直接带您找到分段错误的位置 假设您的应用程序名为“foo”: 当它崩溃时:
# bt
不要在论坛上猜测或询问,只需运行调试器即可。如果在linux上工作,gdb将直接带您找到分段错误的位置 假设您的应用程序名为“foo”: 当它崩溃时:
# bt
一些观察结果
您应该阅读关于fflush(stdout)
,因为它将帮助您处理调试语句
void print_d(int d)
{
printf(" debug %d ",d); fflush(stdout);
};
您分配给字符指针数组、list[20]
和story[100]
,但是您有循环(由臭名昭著的“i”索引),可以很容易地从列表或故事的末尾走出来
如果试图打开文件名为argv[2]
和argv[3]
的文件,一行为读,另一行为写,请将这些行更改为以下内容:
printf("%s %s %s ",argv[1],argv[2],argv[3]); fflush(stdout);
if( !(listfile=fopen(argv[1],"r")) )
{
printf("cannot open %s\n",argv[1]); fflush(stdout);
return(1);
}
print_d(1);
if( !(infile=fopen(argv[2],"r")) )
{
printf("cannot open %s\n",argv[2]); fflush(stdout);
return(2);
}
print_d(2);
if( !(outfh=fopen(argv[3],"w+")) ) //notice the "w+" to create missing file
{
printf("cannot open %s\n",argv[3]); fflush(stdout);
return(3);
}
print_d(3);
现在文件已正确打开,请将调试打印参数更改为递增的数字顺序,这样您就可以按顺序发现(;)循环工作的计数器
int check(char*string)
{
int i;
for(i=0; list[i]!=NULL; i++)
{
if(strcmp(string,list[i])==0){return 1;};
};
return 0;
};
更改循环以成功读取两个文件
for(i=0; i<20; ++i)
{
if(feof(listfh)!=0) { break; };
list[i]=malloc(sizeof(char [15]));
fscanf(listfh,"%s[^\n]",list[i]);
}
fclose(listfh);
debug(4);
您还需要确保只释放分配的行
for(i=0; list[i] && list<20; i++)
{
free(list[i]);
}
对于(i=0;list[i]&&list一些观察结果
您应该阅读关于fflush(stdout)
,因为它将帮助您处理调试语句
void print_d(int d)
{
printf(" debug %d ",d); fflush(stdout);
};
您分配给字符指针数组、list[20]
和story[100]
,但是您有循环(由臭名昭著的“i”索引),可以很容易地从列表或故事的末尾走出来
如果试图打开文件名为argv[2]
和argv[3]
的文件,一行为读,另一行为写,请将这些行更改为以下内容:
printf("%s %s %s ",argv[1],argv[2],argv[3]); fflush(stdout);
if( !(listfile=fopen(argv[1],"r")) )
{
printf("cannot open %s\n",argv[1]); fflush(stdout);
return(1);
}
print_d(1);
if( !(infile=fopen(argv[2],"r")) )
{
printf("cannot open %s\n",argv[2]); fflush(stdout);
return(2);
}
print_d(2);
if( !(outfh=fopen(argv[3],"w+")) ) //notice the "w+" to create missing file
{
printf("cannot open %s\n",argv[3]); fflush(stdout);
return(3);
}
print_d(3);
现在文件已正确打开,请将调试打印参数更改为递增的数字顺序,这样您就可以按顺序发现(;)
循环工作的计数器
int check(char*string)
{
int i;
for(i=0; list[i]!=NULL; i++)
{
if(strcmp(string,list[i])==0){return 1;};
};
return 0;
};
更改循环以成功读取两个文件
for(i=0; i<20; ++i)
{
if(feof(listfh)!=0) { break; };
list[i]=malloc(sizeof(char [15]));
fscanf(listfh,"%s[^\n]",list[i]);
}
fclose(listfh);
debug(4);
您还需要确保只释放分配的行
for(i=0; list[i] && list<20; i++)
{
free(list[i]);
}
for(i=0;list[i]&&list您应该始终检查fopen()的返回值是否为0。@CharlieBurns您认为在打开文件时可能发生了什么事情……这可能是第一次。但是可以。关于if(strcmp(string,list[i])==0{return 1;};
,请删除最后一个;
(不确定它会影响什么,只是一个混淆因素。@Ryker不好的做法?你可能想让print\u d
print换行,也可能去stderr而不是stdout。似乎stdout的默认缓冲对你来说很混淆。你应该始终检查fopen()的返回值。)要查看是否为0。@CharlieBurns您认为在打开文件时可能发生了什么事情……这可能是第一次。但是可以。关于if(strcmp(string,list[i])==0){return 1;};
,请删除最后一个;
(不确定它会影响什么,只是一个混乱的因素。@Ryker坏习惯?你可能想让print\u d
打印一个换行符,也可能去stderr而不是stdout。似乎stdout的默认缓冲让你很困惑。我对segfault以外的东西更感兴趣,gdb会给你更多。放一个断点,检查变量,找出你的问题。这比打印或猜测你的建议是正确的要容易得多,但是告诉我好先生,你的“评论”不应该在“评论”部分而不是在“回答”部分吗?也许你是对的。但是gdb是调试的正确答案。现在你的答案是transfo