由于程序中的分段错误而导致的错误

时间:2020-03-01 11:39:59

标签: c

昨天,我在代码厨师中解决了一个名为At The Gates的问题。我用C语言编写了一些没有语法错误的代码,因为该代码的编译过程中警告和错误为零。

该代码在第一个测试用例上运行正常,但是在第二个测试中给出了分段错误错误。

当我调试它时,它表明分段错误是由于代码行造成的

if(a[N-1]=='H');

调试器输出:

程序收到信号SIGSEGV,分段错误。 main.c中main()中的0x00000000004006d4:15

请帮助我纠正和更正代码。

#include<stdio.h>
void main(){
    int T;

    scanf("%d",&T);
    while(T!=0){
        int N=0,K,count=0,i;
        scanf("%d%d",&N,&K);
        char a[200];
        for(i=0;i<N;i++){
            scanf("%c",&a[i]);
        }

        while(K--){
            if(a[N-1]=='H'){
                N--;
                for(i=0;i<N;i++){
                    if(a[i]=='H'){
                        a[i]=='T';
                    }
                    if(a[i]=='T'){
                        a[i]=='H';
                    }
                }
            }
            else{
                N--;
            }

        }

        for(i=0;i<N;i++){
            if(a[i]=='H'){
                count=count+1;
            }
        }
        printf("%d\n",count);
        T=T-1;
}

}

2 个答案:

答案 0 :(得分:1)

连同评论中提到的其他建议-

  1. 更改main签名以返回int
  2. 更新a[i]=='T';a[i]=='H';以删除if块内的double equals警告(用==替换=在逻辑上是不正确的,请参阅@CiaPan的答案下面)

您还必须更新scanf语句 -scanf("%c",&a[i]);scanf(" %c",&a[i]);(请注意%c之前的多余空格)

这应该可以解决细分错误问题。

有关详细信息,请参见thisthis-

%d自动吃掉空格和特殊字符,因为空格和特殊字符是字符,而不是数字!但是,%c必须将空格和特殊字符解释为输入,因为%c会读取字符。

说明-

在如下所示的程序中添加一些printf语句以检查收到的输入时,我们可以看到会发生什么情况-

        int N=0,K,count=0,i; // N initialized to 0, but not K
        printf("Before scan N=%d, K=%d\n", N, K);
        i=scanf("%d%d",&N,&K);
        char a[200];
        printf("After scan-\n N=%d, K=%d, Scanf return value=%d\n", N, K, i);
        for(i=0;i<N;i++){
            scanf("%c",&a[i]);
        }
        for(i=0;i<N;i++){
            printf("%d=>'%c', ",i, a[i]);
        }
        printf("\n");

有输入-

3
5 3
H T T H T
7 4
H H T T T H H
6 1
T H T H T T

整个程序的输出看起来像这样-

Before scan N=0, K=1362879360
After scan-
 N=5, K=3, Scanf return value=2   <------ 2 VALUES SUCCESSFULLY READ
0=>'
', 1=>'H', 2=>' ', 3=>'T', 4=>' ',
Program output - 1
Before scan N=0, K=-1
After scan-
 N=0, K=-1, Scanf return value=0 <------ 0 VALUES SUCCESSFULLY READ (problem)

exited, segmentation fault

正如@CiaPan在评论中所提到的,%c占用了数组中的每个字符,甚至空格和换行符,但部分输入行H T T H T留在了输入缓冲区中。由于在第一个循环中N和K为正且N大于K,因此第二个while循环终止。

在主循环的第二次迭代(测试用例)期间,N初始化为0,而K在第一次循环迭代中的值为-1。由于无法将来自输入缓冲区的剩余数据正确分配给N和K,因此它们会继续使用该值。

现在进入第二个while循环(测试用例),K开始为负,因此条件while(K--)在意外的长时间内保持正确(直到在整数边界处换行后K为零),并且N也保持递减。最终,对于较大的N负值,程序尝试访问不可访问的内存(使用a[N-1]),从而导致分段错误。

通过确保N和K正确初始化并在整个程序中具有预期值,可以避免此问题。 scanf中%c之前的空格将适当地消耗来自输入缓冲区的多余空格/换行符,以为数组提供正确的值,从而导致按预期从输入分配N,K个变量。可以通过检查return values of scanf函数来捕获此类输入问题。诸如K>0之类的其他检查/断言可有助于调试。

答案 1 :(得分:0)

这段代码肯定不会 做您想要的事情:

object.method1();
.method2();
.method3();
// etc

说明

                if(a[i]=='H'){
                    a[i]=='T';
                }
                if(a[i]=='T'){
                    a[i]=='H';
                }

只是比较将数组项 a[i]=='T'; 与常量a[i],但随后比较结果却没有任何作用– {{{ 1}}是否等于'T'不会以任何方式影响程序的进一步执行。

如果将比较运算符a[i]更改为赋值'T' ...

==

然后,该循环的每次执行将使=数组{em>充满。你知道为什么吗?