从输入中获取数字的最佳方法?
我想从包含文本和数字的输入文件中逐个字符循环。 我以为我可以循环……
char count; while( c != ' ' && c != '\n' && c != '\t' ) { count += c; c = fgetc(fp); }
说从文本文件中获取“11”然后使用atoi转换为int但我意识到我只是添加了ASCII数字。 我对C很新,从我理解的字符串只是char数组 – 这是否意味着我必须将“1”和“1”放入char数组中? 但是那时我不得不担心数组大小并将其转换为数字?
虽然它看起来像是自然的解决方案,但我通常建议不要在潜在的格式错误的输入上使用fscanf()
。
该function有几个问题,其中包括:
- 无法从错误(缺少
ftell()
/fseek()
)中优雅地恢复,因为您不知道它在何处停止解析输入。 - 它导致使用未初始化值的难易程度(如果格式与输入不匹配,并且您没有正确检查返回代码)。
- 一些极端情况,其中
fscanf()
在输入上窒息,其中atoi()
/strtol()
没有( “0xz” …)。
所有这些都将fscanf()
降级为仅读取格式良好的输入,即您自己的程序之前以已知格式编写的内容。
对于可能不是预期格式的任何类型的输入, 我建议一次读取一行( fgets()
),并在内存中解析它 ,例如使用strtol()
:
#include #include #include #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
为resp。LONG_MIN
如果找到的数字超出了long
范围(在这种情况下,errno == ERANGE
也是如此)。
我不知道你的确切要求,所以如果你没有找到一个数字,或者如何处理文本,我就无法给出一个很好的例子。 但是,由于你在内存中得到了行(或者,更长行的第一个LINE_BUFFER_SIZE
字符……),你可以使用所有字符串函数 。 strpbrk( line, "0123456789" )
可用于扫描下一个数字,或strpbrk( line, "+-0123456789" )
如果你的输入可能有+-
…
大多数人会使用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
跳过空白。 如果它找到一个数字就会成功,如果找到别的东西就会失败。