Linux中的C编程:对于在文件中查找子字符串出现次数的程序,无法获得正确的输出
我正在编写一个程序,用于在写入缓冲区的文本文件(也从命令行读取)中查找命令行中输入子字符串的出现次数 当我在bash中运行代码时,我得到一个错误:Segmentation fault(内核转储)。 我仍在学习如何在这种环境下使用C编写代码,并对出现分段错误(滥用动态内存分配?)的原因有了一些想法,但我找不到它的问题。我所能得出的结论是,问题来自for循环(我标记了代码中潜在错误的位置) 编辑:我通过将Linux中的C编程:对于在文件中查找子字符串出现次数的程序,无法获得正确的输出,c,linux,segmentation-fault,dynamic-memory-allocation,C,Linux,Segmentation Fault,Dynamic Memory Allocation,我正在编写一个程序,用于在写入缓冲区的文本文件(也从命令行读取)中查找命令行中输入子字符串的出现次数 当我在bash中运行代码时,我得到一个错误:Segmentation fault(内核转储)。 我仍在学习如何在这种环境下使用C编写代码,并对出现分段错误(滥用动态内存分配?)的原因有了一些想法,但我找不到它的问题。我所能得出的结论是,问题来自for循环(我标记了代码中潜在错误的位置) 编辑:我通过将argv[j]更改为argv[I]来修复分段错误,但是当我现在运行代码时,count1始终返回0
argv[j]
更改为argv[I]
来修复分段错误,但是当我现在运行代码时,count1始终返回0,即使子字符串在文本文件中多次出现,并且我不确定是什么错误,即使我已经多次查看了代码
$ more foo.txt
aabbccc
$ ./main foo.txt a
0
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv[]){
文件*fp;
长时间lsize;
char*buf;
int count=0,count1=0;
int i,j,k,l1,l2;
if(argc<3){printf(“错误:参数不足。\n”);返回(1);};
fp=fopen(argv[1],“r”);
如果(!fp){
perror(argv[1]);
出口(1);
}
//获取文件大小
fseek(fp,0L,SEEK_END);
lsize=ftell(fp);
倒带(fp);
//为整个内容分配内存
buf=calloc(1,lsize+1);
如果(!buf){
fclose(fp);
fputs(“内存分配失败。\n”,stderr);
出口(1);
}
//将文件复制到缓冲区中
如果(1!=fread(buf,lsize,1,fp)){
fclose(fp);
免费(buf);
fputs(“整个读取失败。\n”,stderr);
出口(1);
}
l1=strlen(buf);
//错误就在这里的某个地方
对于(i=2;i
fread(buf,lsize,1,fp)
将读取1块lsize
字节,但是fread
不关心内容,也不会为
字符串,sol1=strlen(buf)代码>产生未定义的行为,其余的
因此,可以忽略结果(并且您的计数也有错误)。
请注意,文件的结尾通常没有以0结尾的字节,
这甚至适用于包含文本的文件,它们通常以
新线
您必须自己设置0字节:
if (1 != fread(buf, lsize, 1, fp)) {
fclose(fp);
free(buf);
fputs("Entire read fails.\n", stderr);
exit(1);
}
buf[lsize] = '0';
您可以使用strstrstr
获取子字符串的位置,如下所示:
for(i = 2; i < argc; ++i)
{
char *content = buf;
int count = 0;
while((content = strstr(content, argv[i])))
{
count++;
content++; // point to the next char in the substring
}
printf("The substring '%s' appears %d time(s)\n", argv[i], count);
}
是错误的,您是在比较指针,而不是内容。您必须使用strcmp
比较字符串。在这种情况下,您必须使用strncmp
,因为
仅希望匹配子字符串:
while(strncmp(&buf[j], argv[k], strlen(argv[k])) == 0)
{
// substring matched
}
但这也是错误的,因为您也在增加k
,这将
给你下一个论据,在最后你可能会读到超出
argv
如果子字符串长于参数数量。基于你的
代码,则必须比较字符:
while(buf[j] == argv[i][k])
{
j++;
k++;
}
仅当子字符串匹配时,才必须递增计数器,如
这:
l1=strlen(buf);
对于(i=2;i这不是你的问题,但是while(j
比for(j=0;j
while(&buf[j]==argv[k])
akawhile(false)
调试是作为一名初级程序员需要学习的一项重要技能。阅读一些开始的提示。好的,非常感谢。考虑到我仍在学习如何正确编码,这是非常有用的。
while(strncmp(&buf[j], argv[k], strlen(argv[k])) == 0)
{
// substring matched
}
while(buf[j] == argv[i][k])
{
j++;
k++;
}
l1 = strlen(buf);
for (i = 2; i < argc; i++) {
int count = 0;
int k = 0; // running index for inspecting argv[i]
for (j = 0; j < l1; ++j) {
while(buf[j + k] == argv[i][k])
k++;
// if all characters of argv[i]
// matched, argv[i][k] will be the
// 0-terminating byte
if(argv[i][k] == 0)
count++;
// reset running index for argv[i]
// go to next char if buf
k = 0;
}
printf("The substring '%s' appears %d time(s)\n", argv[i], count);
}