You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言数据类型识别程序Bug咨询:输入"20x"被误判为整数

C语言输入类型识别程序的误判问题与解决

原程序代码

// C program to find data type
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX_INPUT 100

int main()
{
    // To read input
    char value[MAX_INPUT] = "";

    // To store numeric value of input if a 
    // number (float or integer)
    double temp;

    // To store integral value of input
    int n;

    // To store string value of input
    char str[MAX_INPUT] = "";

    // Precision for integer checking
    double val = 1e-12;

    fgets(value, 100, stdin); // Read input

    // Check for integers.
    if (sscanf(value, "%lf", &temp) == 1) 
    {
        n = (int)temp; // typecast to int.
        if (fabs(temp - n) / temp > val) 
            printf("The input is a floating point\n");        
        else 
            printf("The input is an integer\n");        
    }

    // Check for string 
    else if (sscanf(value, "%s", str) == 1)     
        printf("The input is a string\n");
      
    else // No match.    
        printf("input not recognized\n");    
}

问题描述

输入像"20x"这类带有非数字后缀的字符串时,程序会错误判定为整数。

问题原因

sscanf使用%lf格式读取时,只会从输入开头读取连续的数字字符,遇到非数字字符就停止解析,不会验证整个输入字符串是否完全匹配数字格式。比如"20x",sscanf会读取20作为有效double值,返回匹配成功的计数1,触发整数/浮点数的判断分支,忽略了后面的x。

解决办法

要确保整个输入字符串都被解析为数字,需要验证解析完成后是否没有剩余未处理的有效字符(除了换行符,因为fgets会把换行符也读入)。这里提供两种可行方案:

方案1:使用strtod函数

strtod可以将字符串转换为double,同时返回一个指针,指向转换结束后第一个未被处理的字符。我们可以检查这个指针指向的内容是否是字符串结束符,以此确认整个输入都是数字。

修改后的代码:

// C program to find data type
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_INPUT 100

int main()
{
    char value[MAX_INPUT] = "";
    double temp;
    int n;
    double val = 1e-12;
    char *end_ptr;

    fgets(value, MAX_INPUT, stdin);
    // 去掉fgets读取的换行符(如果存在)
    size_t len = strlen(value);
    if (len > 0 && value[len-1] == '\n') {
        value[len-1] = '\0';
    }

    temp = strtod(value, &end_ptr);
    // 检查是否转换成功,且所有字符都被处理
    if (end_ptr != value && *end_ptr == '\0') 
    {
        n = (int)temp;
        // 避免temp为0时除以0的错误
        if (temp != 0 && fabs(temp - n) / fabs(temp) > val)
            printf("The input is a floating point\n");        
        else 
            printf("The input is an integer\n");        
    }
    else
    {
        printf("The input is a string\n");
    }

    return 0;
}

方案2:使用sscanf配合%n记录读取位置

%n可以记录sscanf已经读取的字符数,我们可以通过这个数值检查是否读取到了字符串的末尾(忽略换行符)。

修改后的核心代码片段:

// ... 其他代码不变
int chars_read;
// 读取数字同时记录读取的字符数
if (sscanf(value, "%lf%n", &temp, &chars_read) == 1) 
{
    // 跳过可能的空白字符,检查是否到了换行或结束
    while (value[chars_read] == ' ' || value[chars_read] == '\t') chars_read++;
    if (value[chars_read] == '\n' || value[chars_read] == '\0')
    {
        n = (int)temp;
        // 处理temp为0的情况,避免除以0
        if (temp != 0 && fabs(temp - n) / temp > val) 
            printf("The input is a floating point\n");        
        else
            printf("The input is an integer\n");        
    }
    else
    {
        printf("The input is a string\n");
    }
}
else if (sscanf(value, "%s", str) == 1)     
    printf("The input is a string\n");
else    
    printf("input not recognized\n");

补充说明

原程序还有一个潜在问题:当temp为0时,fabs(temp - n)/temp会触发除以0的错误,上述修改后的代码已经修复了这个问题。

内容的提问来源于stack exchange,提问作者party

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 03:05:29