首页 > 解决方案 > 由于程序中的分段错误而导致的错误

问题描述

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

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

当我调试它时,它显示分段错误是由于代码行

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

调试器输出:

程序收到信号 SIGSEGV,分段错误。0x00000000004006d4 在 main ( ) at main.c: 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;
}

}

标签: c

解决方案


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

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

您还必须更新scanf语句 -scanf("%c",&a[i]);scanf(" %c",&a[i]);(注意前面开头的额外空格%c

这应该解决分段错误问题。

有关详细信息,请参阅-

%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 变量按预期从输入中分配。可以通过检查 scanf函数的返回值来捕获此类输入问题。其他检查/断言之类K>0的可能有助于调试目的。


推荐阅读