我写了一个程序,可以进行十六进制到十进制的转换。我剩下的只是检查char
是否在a
-f
或A
-F
之间,也许是0
-{{1 }}。如果不在它们之间,则会打印9
。
我的代码:
"Illegal input"
我需要的输出:
Enter the number of digits in the Hexadecimal number: 2 Enter the Hexadecimal number: QQ Illegal input
答案 0 :(得分:2)
代码有几个问题。
对于初学者来说,功能scanf_s
应包括格式说明符c
的缓冲区大小作为参数。
要输出unsigned long
类型的对象,必须使用格式说明符ul
。
在这些if语句中,您不检查有效的alpha十六进制数字的上限。
if (currentDigit >= 'a') {
currentDigitInt = (currentDigit - 'a') + 10;
}
else if (currentDigit >= 'A') {
currentDigitInt = (currentDigit - 'A') + 10;
}
要检查输入的符号是否为有效的十六进制数字,应编写一个单独的函数。
这里是一个演示程序,显示了如何完成此操作。
//Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23506 for x64
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int hex_digit( char c )
{
const char *alpha = "ABCDEF";
unsigned char c1 = toupper( ( unsigned char )c );
const char *p;
int result = -1;
if ( '0' <= c1 && c1 <= '9' )
{
result = c1 - '0';
}
else if ( c1 != '\0' && ( p = strchr( alpha, c1 ) ) != NULL )
{
result = *p - alpha[0] + 10;
}
return result;
}
int main(void)
{
const unsigned long HEX_BASE = 16;
unsigned int n;
printf( "Enter the number of digits in the Hexadecimal number: " );
scanf_s("%u", &n);
unsigned long sum = 0;
if ( n )
{
printf( "Enter the Hexadecimal number: " );
unsigned int i = 0;
for ( ; i < n; i++ )
{
char c;
scanf_s( " %c", &c, 1 );
int digit = hex_digit( c );
if ( digit < 0 ) break;
else sum = sum * HEX_BASE + digit;
}
if ( i == n )
{
printf("The decimal number is: %ul\n", sum);
}
else
{
puts( "Illegal input" );
}
}
return 0;
}
其输出可能如下所示
Enter the number of digits in the Hexadecimal number: 8
Enter the Hexadecimal number: ffFFffFF
The decimal number is: 4294967295l
如果需要,可以在程序中添加一个检查,以确保输入的十六进制数字的指定数量不大于2 * sizeof( unsigned long )
。
答案 1 :(得分:0)
a
(A
)到f
(F
)在C中不必连续。
如果您希望程序在C的所有实现上运行(klingon太空飞船,DS9K,火星漫游者,...,...),则可以尝试这样的操作
if ((currentdigit == 0) || (strchr("0123456789abcdefABCDEF", currentdigit) == NULL)) /* invalid */;
答案 2 :(得分:0)
您的代码中存在多个问题:
您可以使用&&
运算符测试字符范围。例如:
if (currentDigit >= 'a' && currentDigit <= 'f')
您将这些测试合并为一系列if
/ else
,并在没有一个匹配的情况下抱怨。
还要注意sum
的表达式也不正确。 sum += currentDigitInt * pow(16, i);
应该是
sum = sum * 16 + currentDigitInt;
printf
的{{1}}格式是unsigned long
,而不是%lu
。
您应该测试%u
的返回值以正确检测文件的潜在结尾。
scanf_s
期望为转换说明符scanf_s
增加2个参数,并且可能并非在所有系统上都可用。
也请注意,您不需要输入十六进制数字,只需在输入的字符第二次是换行符时从循环中中断即可。
这是更正的版本:
%c
注意:
#include <stdio.h>
int main() {
int currentDigit;
unsigned long int sum;
int invalid = 0;
printf("Enter the Hexadecimal number: ");
sum = 0;
while ((currentDigit = getchar()) ! EOF && currentDigit != '\n') {
int currentDigitInt;
if (currentDigit >= 'a' && currentDigit <= 'f') {
currentDigitInt = (currentDigit - 'a') + 10;
} else
if (currentDigit >= 'A' && currentDigit <= 'F') {
currentDigitInt = (currentDigit - 'A') + 10;
} else
if (currentDigit >= '0' && currentDigit <= '9') {
currentDigitInt = currentDigit - '0';
} else {
invalid = 1;
continue; // keep scanning the input until end of line
}
sum = sum * 16 + currentDigitInt;
}
if (invalid) {
printf("Invalid input\n");
} else {
printf("The decimal number is: %lu\n", sum);
}
return 0;
}
至0
是连续的,但纯粹主义者会争辩9
至a
和f
至{{1 }}可能不连续执行字符集。虽然正确,但由于这些考虑而使新手程序员望而却步,反而会适得其反,而且因为这些字符范围在ASCII和EBCDIC中都是连续的(EBCDIC中的间距介于A
和F
之间以及{{ 1}}和i
)。答案 3 :(得分:-1)
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int isaTof(int c)
{
c = toupper(c);
if(c >= 'A' && c <= 'F') return 1;
return 0;
}
int isin(int c, const char *allowedchars)
{
return strchr(allowedchars, c) != NULL;
}
int isHEXNumber(const char *number)
{
const char allowedchars[] = "abcdefABCDEF0123456789";
while(*number)
{
if(!isin(*number++, allowedchars)) return 0;
}
return 1;
}
或nitpickers版本
int isHEXNumber(const char *number)
{
const char allowedchars[] = "abcdefABCDEF0123456789";
if(!number || |*number) return 0;
while(*number)
{
if(!isin(*number++, allowedchars)) return 0;
}
return 1;
}
int main()
{
const char allowedchars[] = "abcdefABCDEF0123456789";
printf("%s\n", isin('d', allowedchars) ? "Yes" : "No");
return 0;
}