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
相关产品推荐
相关产品推荐

