史前:我有一个问题,getchar()函数没有得到正确的处理,因为没有对任何给定输入的请求,程序只是继续进一步处理。
我在互联网上搜索了这个问题,发现如果scanf()函数在getchar()函数之前被实现到一个程序中,getchar()函数就不会以正确的方式运行,并且会像我的问题一样。
引用:
我敢打赌100美元,只有在调用getchar()之前加上scanf()时,您才会看到这个问题。
不要将scanf用于交互式程序。这主要有两个原因:
1)scanf无法从格式错误的输入中恢复。您必须每次都正确设置格式字符串,否则它只是丢弃了它无法匹配的任何输入,并返回一个指示失败的值。如果您正在解析一个固定格式的文件,而糟糕的格式无论如何都是不可恢复的,这可能是好的,但是这与您想要对用户输入进行的操作正好相反。使用fget()和sscanf()、fget()和strtok(),或者使用getchar()和putchar()编写自己的用户输入例程。
1.5)即使使用得当,scanf也不可避免地丢弃有时可能很重要的输入(空白)。
2)scanf有在输入流中留下换行符的坏习惯。如果你只使用scanf,这很好,因为scanf通常会跳过任何空白字符,急于找到它下一步想要的东西。但是如果你把scanf和fget/getchar混合在一起,试图弄清楚输入流中可能会或不会留下什么,很快就会变得一团糟。特别是如果您执行任何循环--输入流在第一次迭代时不同是很常见的,这会导致潜在的奇怪错误,甚至更奇怪的修复尝试。
tl; dr--scanf用于格式化输入。用户输入未格式化。//
以下是指向该线程的链接:https://bbs.archlinux.org/viewtopic.php?id=161294
scanf()与:
scanf("%x",integer_variable);
对我来说,作为一个新手,这是从键盘输入十六进制数字(或者更好地说是标准输入文件)并将其存储到int变量的唯一方法。
是否有其他方法从标准输入十六进制值并将其存储到整数变量中?
额外挑战:如果我能将负值(当然是通过负十六进制输入)写入一个有符号的int变量,那也太好了。
信息:我在Stackoverflow上读过很多关于C的线程,都是关于类似的问题,但没有一个能很好地回答我的明确问题。所以我已经发布了这个问题。
我在Linux Ubuntu下工作。
正如您发布的链接中所述,使用fgets
和sscanf
是处理此问题的最佳方法fgets
将读取整行文本,sscanf
将解析该行。
例如
char line[100];
fgets(line, sizeof(line), stdin);
int x;
int rval = sscanf(line, "%x", &x);
if (rval == 1) {
printf("read value %x\n", x);
} else {
printf("please enter a hexadecimal integer\n");
}
因为您只读取一个整数,所以也可以使用strtol
而不是sscanf
。这还具有检测是否输入了任何其他字符的优点:
char *ptr;
errno = 0;
long x = strtol(line, &ptr, 16);
if (errno) {
perror("parsing failed");
} else if (*ptr != '\n' && *ptr != 0) {
printf("extra characters entered: %s\n", ptr);
} else {
printf("read value %lx\n", x);
}
在scanf手册页中,您可以使用scanf将十六进制数从stdin读入(无符号)整数变量。
unsigned int v ;
if ( scanf("%x", &v) == 1 ) {
// do something with v.
}
根据手册页,%x
始终未签名。如果要支持负值,则必须添加显式逻辑。
关于百元赌注的报价是准确的。将scanf
与getchar
混合几乎总是一个坏主意;它几乎总是导致麻烦。但这并不是说它们不能一起使用。它们可以一起使用——但通常情况下,这太难了。有太多的琐碎细节和“明白了!”这是要跟踪的。麻烦太多了。
起初你说
scanf()与<代码>%d。。。对我来说,作为一个新手,这似乎是唯一可以从键盘输入十六进制数的方法
这里有一些混乱,因为当然%d
是十进制输入。但由于在你纠正这个问题时我已经写了这个答案,现在让我们继续小数点。(目前我还不考虑错误检查——也就是说,如果用户没有键入请求的数字,这些代码片段不会检查或执行任何优雅的操作。)无论如何,这里有几种读取整数的方法:
>
scanf(“%d”,
char buf[100];
fget(buf, sizeof(buf), stdin);
integer_variable=atoi(buf);
我认为这是不使用scanf
的最简单方法。但是现在大多数人不喜欢使用atoi,因为它没有做很多有用的错误检查。
char buf[100];
fget(buf, sizeof(buf), stdin);
integer_variable=strtol(buf, NULL,10);
这几乎和以前一样,但避免了有利于的首选strtol
。
char buf[100];
fget(buf, sizeof(buf), stdin);
sscanf(buf,"%d",
所有这些都将起作用;所有这些都将处理负数。不过,考虑错误条件是很重要的——我稍后会对此有更多要说的。
如果要输入十六进制数,技术类似:
scanf(“%x”,
char buf[100];
fget(buf, sizeof(buf), stdin);
integer_variable=strtol(buf, NULL,16);
char buf[100];
fget(buf, sizeof(buf), stdin);
sscanf(buf,"%x",
这些也都应该有效。不过,我不一定期望它们处理“负十六进制”,因为这是一个不寻常的要求。大多数情况下,十六进制表示法用于无符号整数。(事实上,严格来说,
%x
withscanf
和sscanf
必须与声明为无符号int
的整型变量
一起使用,而不是纯int
)
有时“用手”做这类事情是有用的或必要的。这里有一个代码片段,它正好读取两个十六进制数字。我将从使用
getchar
的版本开始:
int c1 = getchar();
if(c1 != EOF && isascii(c1) && isxdigit(c1)) {
int c2 = getchar();
if(c2 != EOF && isascii(c2) && isxdigit(c2)) {
if(isdigit(c1)) integer_variable = c1 - '0';
else if(isupper(c1)) integer_variable = 10 + c1 - 'A';
else if(islower(c1)) integer_variable = 10 + c1 - 'a';
integer_variable = integer_variable * 16;
if(isdigit(c2)) integer_variable += c2 - '0';
else if(isupper(c2)) integer_variable += 10 + c2 - 'A';
else if(islower(c2)) integer_variable += 10 + c1 - 'a';
}
}
正如你所看到的,这有点让人大吃一惊。对我来说,虽然我几乎从不使用scanf家族的成员,但这是我有时使用的地方,正是因为“用手”做这件事需要做很多工作。通过使用辅助函数或宏进行数字转换,可以大大简化:
int c1 = getchar();
if(c1 != EOF && isascii(c1) && isxdigit(c1)) {
int c2 = getchar();
if(c2 != EOF && isascii(c2) && isxdigit(c2)) {
integer_variable = Xctod(c1);
integer_variable = integer_variable * 16;
integer_variable += Xctod(c2);
}
}
或者你可以把那些内心的表达压缩成
integer_variable = 16 * Xctod(c1) + Xctod(c2);
这些功能在辅助功能方面起作用:
int Xctod(int c)
{
if(!isascii(c)) return 0;
else if(isdigit(c)) return c - '0';
else if(isupper(c)) return 10 + c - 'A';
else if(islower(c)) return 10 + c - 'a';
else return 0;
}
或者是宏观的(尽管这绝对是一种老派的东西):
#define Xctod(c) (isdigit(c) ? (c) - '0' : (c) - (isupper(c) ? 'A' : 'a') + 10)
我经常这样解析十六进制数字不是从
stdin
使用getchar()
,而是从字符串。我经常使用字符指针(char*p
)来遍历字符串,这意味着我最终得到的代码更像这样:
char c1 = *p++;
if(isascii(c1) && isxdigit(c1)) {
char c2 = *p++;
if(isascii(c2) && isxdigit(c2))
integer_variable = 16 * Xctod(c1) + Xctod(c2);
}
省略临时变量和错误检查并进一步归结为:
integer_variable = 16 * Xctod(*p++) + Xctod(*p++);
但不要这样做!除了缺少错误检查之外,这个表达式可能是未定义的,而且它肯定不会总是做您想要做的事情,因为您读取字符的顺序不再有任何保证。如果您知道
p
位于两个十六进制数字的第一个,那么您不希望将其折叠到超过
integer_variable = Xctod(*p++);
integer_variable = 16 * integer_variable + Xctod(*p++);
即使如此,这也只适用于函数版本的
Xctod
,而不适用于宏,因为宏会多次计算其参数。
最后,让我们谈谈错误处理。有相当多的可能性需要担心:
用户点击Return而不键入任何内容
用户在数字之前或之后键入空格
用户在数字后键入额外垃圾
用户键入非数字输入,而不是数字
代码到达文件末尾;根本没有要读取的字符
然后你如何处理这些取决于你使用的是什么输入技术。以下是基本规则:
A.如果您正在调用
scanf
、fscanf
或sscanf
,请始终检查返回值。如果它不是1(或者,在您有多个%
说明符的情况下,它不是您期望读取的值的数量),这意味着出错了。这通常会抓住问题4和5,并优雅地处理案例2。但它往往会悄悄忽略问题1和3。(特别地,scanf
和fscanf
对待额外的\n
就像领导空白一样。)
B.如果您正在调用
fgets
,请再次检查返回值。在EOF(问题5)中,您将得到NULL
。其他问题的处理取决于你如何处理你读到的那一行。
C.如果您正在呼叫
atoi
,它将优雅地处理问题2,但它将忽略问题3,并将悄悄地将问题4变成数字0(这就是为什么atoi
通常不再被推荐的原因)。
D.如果您正在调用
strtol
或任何其他“strto”函数,它们将优雅地处理问题2,如果您让它们返回“结束指针”,您可以检查并处理问题3和问题4。(注意,我在上面的两个strtol
示例中没有处理结束指针。)
最后,如果你在做一些下流肮脏的事情,比如我的“hardway”两位数十六进制转换器,你通常必须自己解决所有这些问题。如果要跳过前导空格,必须这样做(来自
用户用十六进制或二进制输入一个数字(必须以0x或0b为前缀,如果没有给出错误信息) 我不能用基数,我只是用整数。parseInt(s) 我不知道怎样才能使这个计划奏效。。请帮帮我,我还缺什么?
问题内容: 我是JavaScript和jQuery的新手,现在面临一个问题: 我需要将一些数据发布到PHP,并且其中一部分数据必须是div X的背景色十六进制。 jQuery具有css(“ background-color”)函数,通过它我可以将背景的RGB值转换为JavaScript变量。 CSS函数似乎返回了一个类似rgb(0,70,255)的字符串。 我找不到任何方法来获取背景颜色的十六进制
问题内容: 如上面的标题。我想从一个十六进制数字 我想转换为。 问题答案:
我有十六进制字符串,例如“0x103E”,我想将其转换为整数。意思是to我尝试了但它给出了数字格式异常。我如何实现这一点?
我有一个十六进制值字符串,由
问题内容: 如何在Python中将十六进制字符串转换为int? 我可能将其命名为或。 问题答案: 如果没有 0x前缀,则需要显式指定基数,否则无法分辨: 使用 0x前缀,Python可以自动区分十六进制和十进制。 (必须指定0为基数才能调用此前缀猜测行为;省略第二个参数意味着假定基数为10。)