从输入中获取数字的最佳方法?
Posted
技术标签:
【中文标题】从输入中获取数字的最佳方法?【英文标题】:Best way to get numbers from input? 【发布时间】:2016-05-12 08:09:43 【问题描述】:我想从包含文本和数字的输入文件中逐个字符循环。
我以为我可以循环播放
char count;
while( c != ' ' && c != '\n' && c != '\t' )
count += c;
c = fgetc(fp);
要说从文本文件中获取“11”,然后使用atoi()
转换为 int,但后来我意识到我只是添加 ASCII 数字。
我对 C 很陌生,据我所知,字符串只是 char 数组 - 这是否意味着我必须将“1”和“1”放入 char 数组中?
但是我不得不担心数组大小并将其转换为数字?
【问题讨论】:
C 规范规定,无论编码如何,数字都必须是连续的。这意味着你可以做例如'1' - '0'
获取整数值1
。从那里很容易创建整数值,无论用于输入的基数如何。无需存储在字符串中以供以后与atoi
一起使用。如果您不想即时构建数字并使用atoi
,此评论也会为您提供提示。
快速修复是做count += c - '0';
Lundin,当我进行更改时,它会将“11”转换为 2
【参考方案1】:
大多数人会使用fscanf
:
int number, items_scanned;
items_scanned = fscanf(fp, "%d", &number);
if (items_scanned == 0)
/* Scanning for a number failed */
printf("Scan failed!\n");
printf("Found number: %d\n", number);
fscanf
跳过空格。如果它找到一个数字就会成功,如果它找到别的东西就会失败。
【讨论】:
谢谢克拉斯。我必须实际遍历文件以查找其他文本和数字,同时跟踪它们,所以我需要上面的某种行位置? 您可以使用ftell
来查找文件中的当前位置。您还应该考虑@DevSolar 的答案,这可能更适合您的问题。【参考方案2】:
虽然它看起来是自然的解决方案,但我通常建议不要对可能格式错误的输入使用 fscanf()
。
函数存在几个问题,其中:
无法从错误中正常恢复(缺少ftell()
/ fseek()
),因为您不知道究竟在哪里停止解析输入。
很容易导致使用未初始化的值(如果格式与输入不匹配,并且您没有正确检查返回码)。
一些极端情况,fscanf()
会阻塞输入,而 atoi()
/ strtol()
不会 ("0xz"...)。
所有这些都将fscanf()
降级为仅读取格式良好的输入,即您自己的程序之前以已知格式编写的内容。
对于可能符合预期格式的任何类型的输入,我建议一次读取一行 (fgets()
),并在内存中解析它,例如strtol()
:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define LINE_BUFFER_SIZE 256;
// ...
char line[ LINE_BUFFER_SIZE ];
fgets( line, LINE_BUFFER_SIZE, fp );
char * scanptr;
errno = 0;
long number = strtol( line, &scanptr, 0 );
if ( scanptr == line )
// not a number...
scanptr
现在指向数字解析结束的位置。
number
包含解析的数字,如果行不以数字开头,则为 0,而 LONG_MAX
则分别为。 LONG_MIN
如果找到的号码超出了long
范围(在这种情况下errno == ERANGE
也是如此)。
我不知道您的确切要求,因此我无法举例说明如果您找不到数字该怎么办,或者如何处理文本。但是,由于您在内存中获得了该行(或较长行的第一个 LINE_BUFFER_SIZE
字符......),因此您可以随意使用 string functions 的整个范围。 strpbrk( line, "0123456789" )
可用于扫描下一个数字,或者 strpbrk( line, "+-0123456789" )
如果您的输入中可能包含 +-
...
【讨论】:
尽管这个问题的变化不时出现,并且类似的答案讨论了*scanf()
和strto*()
,但对于学习者来说,这仍然是最好的答案之一。
@chux:谢谢。连同“什么是 Unicode,以及我如何在 C/C++ 中使用它”一起,这是我一直在考虑为其编写常见问题解答条目但从未有时间去做的其中之一。似乎我每隔一周回答一次。 ;-)
如果您开始着手并想要(预)审查,请与我联系。
感谢 DevSolar。我只是因为不熟悉 C 而试图掌握你写的东西。我需要遍历一个文件并找到我稍后将使用的数字和单词。 Fgetc 似乎是最自然的,因为我可以从上次发现的地方继续。我应该可以使用 scanptr 吗?我的一部分正在考虑切换到 C++,这样我就可以使用字符串了,但如果我这样做了,我会觉得我要退出了
@cpd1:选择 C++ 并不是“放弃”。它是一种更强大的语言,可以让许多事情变得更容易——但也有其自身的缺陷。一般来说,虽然在学习语言的同时使用一些“玩具”应用程序是一件好事,但尝试同时学习语言和解决“真正的”问题。您想首先获得对一种语言及其提供的工具的“感觉”,这样您就可以为任何给定的问题选择正确的工具。否则,你总是会玩盲人的虚张声势,变得沮丧。以上是关于从输入中获取数字的最佳方法?的主要内容,如果未能解决你的问题,请参考以下文章
jQuery:限制文本框仅输入“数字”的最佳方法是啥? (允许小数点)