gpt4 book ai didi

c - linux 上的段错误-在 windows 上工作

转载 作者:太空宇宙 更新时间:2023-11-04 01:16:08 25 4
gpt4 key购买 nike

这个程序的目标是扫描一个由数字和它们之间的空格填充的字符串,并将每个数字插入到一个数组中。然后将数组中的每个数字发送到 checkPowerOfTwo确定发送的数字是否为 2 的幂并打印计算结果的函数。

当我在 Windows 上运行该程序时,一切正常。在 Linux 上运行会导致段错误。

我正在 Linux 服务器上编译我的代码:gcc -std=c99 -Wall -pedantic-errors -Werror -DNDEBUG main.c -o mtm_tot .它编译成功,没有错误或警告。当我尝试运行测试仪时出现问题:./mtm_tot< test1.in > tmpout .在此行上按 enterSegmentation fault上升。

test1.in contains : 8

5 9 -1 4 20 256 -32 17 32

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int checkPowerOfTwo(int x);
int main()
{
int exp,size,sum=0,*numbers;
char term,*str=NULL,*token;

printf("Enter size of input:\n");
if(scanf("%d%c", &size, &term) != 2 || term != '\n'){
printf("Invalid Size\n");
return 0;
} if(size<=0){
printf("Invalid size\n");
return 0;
} else{
numbers=(int*)malloc(size * sizeof(int));
str=(char*)malloc(sizeof(int)*(size+1) + (size-1)*sizeof(char));
if(numbers==NULL||str==NULL){
printf("Out of memory\n");
return 0;
} //else{
//printf("Memory allocated\n");
//}
printf("Enter numbers:");
fgets (str, sizeof(int)*(size+1) + (size-1), stdin);
//printf("%s",str);
token=strtok(str," ");
while(token!=NULL){
for(int i=0;i<size;i++){
//printf("token is %s\n",token);
//numbers[i]=token;
sscanf(token,"%d",&numbers[i]);
//printf("Inserting %s to the array\n ",numbers[i]);
token=strtok(NULL," ");
}
}
}

for(int j =0;j<size;j++)
{
//sscanf(numbers[j],"%d",&x);
//printf("the number im sending is : %d ",x);
exp=checkPowerOfTwo(numbers[j]);
if (exp>=0){
printf("The number %d is a power of 2: %d=2^%d\n",numbers[j],numbers[j],exp);
sum+=exp;
}
}
printf("Total exponent sum is %d",sum);
free(numbers);
free(str);
}

int checkPowerOfTwo(int x)
{
int exponent=0;
//sscanf(n,"%d",&x);
//printf("checking number %d\n",x);
if (x==0){
return -1;
} if (x==1){
return 0;
}
while( x != 1)
{
if(x % 2 != 0){
return -1;
}
x /= 2;
exponent++;
}
return exponent;
}

最佳答案

用输入文件test1.in如问题中所示,您指定大小为 8 并提供 9 个数字。

你的代码

        while(token!=NULL){
for(int i=0;i<size;i++){
//printf("token is %s\n",token);
//numbers[i]=token;
sscanf(token,"%d",&numbers[i]);
//printf("Inserting %s to the array\n ",numbers[i]);
token=strtok(NULL," ");
}
}

将进入外层while在内部 for 的第一次运行中循环并处理 8 个数字环形。由于您输入了 9 个数字,token不会是NULL并且外循环将重复并再次运行内循环。这将部分覆盖数组中的数字。在第一个循环中处理第 9 个数字后,token将变为 NULL在第二个周期 sscanf将尝试使用 NULL可能导致段错误的指针。

您应该将计数器和 NULL 的支票结合起来在循环条件下。我还建议检查 sscanf 的返回值因为值 != 1将指示无效输入。

        for(int i=0; (i<size) && (token!=NULL); i++) {
if(sscanf(token,"%d",&numbers[i]) != 1) {
/* invalid input */
break;
}
token=strtok(NULL," ");
}

当然,循环后面的代码必须处理循环以 i < size 结束的情况。如果没有足够的值。

编辑:下面的补充说明

注意:scanf 的错误检查不完整。它将返回 0如果它无法转换整数,但它也会返回 1如果它转换了一个整数并且后面有任何东西,例如对于 123abc它将转换 123并返回 1 .要检查数字后面可能有什么,您可以添加 %c转换,如果返回值为 2检查转换后的字符。 ('\n''\r' 在这里可能没问题。)

我更愿意使用 strtol在循环中解析 str 中的数字.

顺便说一句:分配 str 的大小计算是错的。 sizeof intint 的内部二进制表示的大小在许多系统上该值为 4(4 字节 = 32 位)。它与数字的字符串表示需要多少个字符无关。有效号码 -2147483648需要 11 个字符。

(您可以使用缓冲区 str,如果您将剩余数据移动到开头并在传递一个数字后追加新数据,那么它对于整行来说太小但足够大以容纳超过一个有效数字,直到您阅读终止换行符。)

关于c - linux 上的段错误-在 windows 上工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58629090/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com