c - 由于程序中的分段错误而导致的错误
问题描述
昨天我在代码厨师中解决了一个名为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;
}
}
解决方案
连同评论中提到的其他建议,例如-
- 更改
main
签名以返回int
- 更新
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
的可能有助于调试目的。
推荐阅读
- android - 在没有运行时权限的情况下获取 IMEI 号码
- hadoop - dfs.blocksize 和 BlockCapacity 的值不同
- ios - 异常'-[GIDSignIn setPresentingViewController:] 无法识别的选择器发送到实例 0x280e898c0'
- sql - 在计数中使用星号和表别名 T-SQL
- python - 导入时无法通过在windows中双击打开python文件
- excel - 从VBA中的地址中提取第一列号
- c++ - 赋值运算符是否调用复制构造函数?
- java - Javafx中的倒计时与最大化
- azure - WSO2 与 Azure AD 集成 - 访问 https://outlook.office365.com/api/v2.0/me 时出现 403
- tensorflow - Training multiple models defined from the same class in Tensorflow 2.0 fails when using @tf.function