关于堆栈:简单的 C 代码错误

Simple C Code Error

有谁知道为什么我在运行这段代码时会出现段错误? Valgrind 告诉我,我在第 13 行 if( !isdigit(x) ) 上有"大小为 4 的未初始化值",并且在同一行上有一个无效的读取大小 2 - 地址不是堆栈\\'d,malloc\\'d ,或免费的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>

int main()
{
    int x;

    printf("Please enter a number:");
    scanf("%d", &x);

    if( !isdigit(x) )
    {
        printf("You entered %d\
"
, x);
    }
    else
    {
        printf("You did not enter a valid number!\
"
);
    }

    return 0;
}


我用 g 编译了你的代码,导致没有段错误。

输入值:

5、-1、27、43545gbb 和 gggg

产生的结果:

5、-1、27、43545 和 1729208414


我认为问题在于如果 scanf 失败,x 将未初始化。
最好在字符数组中输入数据。否则,您的代码没有意义,因为您无法在 int 类型的对象中输入非数字。此外,如果您输入一个数字,使用函数 isdigit 的结果可能会出乎意料。


尝试以下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int x = 0;
    char a;

    printf("Please enter a number:");

    while(scanf("%d%c",&x,&a) != 2 || a != '\
'
)
    {
        printf("Please enter an integer only :");
        do
        {
            scanf("%c",&a);
        }while(a != '\
'
);
    }

    printf("You entered %d\
"
, x);
    return 0;
}

代码向您展示了如何使用 scanf 的复杂方法。有关更多信息:scanf 的工作并检查输入是否为 int

根据 c 文档:isdigit

原型:

1
int isdigit( int ch );

参数:

1
ch  -   character to classify

目的:

Checks if the given character is a numeric character (0123456789).
The behavior is undefined if the value of ch is not representable as unsigned char and is not equal to EOF.

返回值:

Non-zero value (true) if the character is a numeric character, 0 (false) otherwise.


为什么第 13 行出现问题?第 13 行是 if( !isdigit(x) )
在第 8 行创建 x 时,您没有初始化它,
因此,如果输入了一个不可接受的值,并在第 11 行由 scanf() 处理,则它将在到达 isdigit() 函数时继续未初始化。

问题在于 isdigit() 期望输入必须是整数值介于 0 和 255 之间的字符。任何其他值都会导致未定义的行为。段错误是未定义行为的可能结果之一。

还有其他方法可以实现这一点,例如:
这是一个使用 char 数组(字符串)的示例。请注意注释以解释为什么要完成某些事情。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int main()
{
    //int x;
    char x[2];  //Good for only one digit

    printf("Please enter an integer with up to 10 digits:");
    //scanf("%d", &x);
    scanf("%1s", x); //Edited to allow maximum field width of 1.

   // if( !isdigit(x) )        
    if( isdigit(x[0]) ) //note the"!" was removed for logic to work
    {
        printf("You entered %d\
"
, atoi(x)); //note use of atoi() to convert string to int.
    }
    else
    {
        printf("You did not enter a valid number!\
"
);
    }

    return 0;
}