Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux中的C编程:对于在文件中查找子字符串出现次数的程序,无法获得正确的输出_C_Linux_Segmentation Fault_Dynamic Memory Allocation - Fatal编程技术网

Linux中的C编程:对于在文件中查找子字符串出现次数的程序,无法获得正确的输出

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

我正在编写一个程序,用于在写入缓冲区的文本文件(也从命令行读取)中查找命令行中输入子字符串的出现次数

当我在bash中运行代码时,我得到一个错误:Segmentation fault(内核转储)。 我仍在学习如何在这种环境下使用C编写代码,并对出现分段错误(滥用动态内存分配?)的原因有了一些想法,但我找不到它的问题。我所能得出的结论是,问题来自for循环(我标记了代码中潜在错误的位置)

编辑:我通过将
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
不关心内容,也不会为 字符串,so
l1=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])
aka
while(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);
}