从c中的复杂字符串中读取整数
Posted
技术标签:
【中文标题】从c中的复杂字符串中读取整数【英文标题】:read only integers from complex string in c 【发布时间】:2014-02-20 00:07:00 【问题描述】:我试图只从字符串中读取整数。每次迭代时,空格和非整数字符基本上是随机的。理想情况下,我的代码将运行并仅打印(或以其他方式存储)整数。所以对于这个测试用例,它将是 6,1,0,16,2,3
等等。
char line [ 200 ] ="T06 1/ 0 16/ 2 3/15 41/40 17/36 0/11 0/11 0/11 1/14 1/ 7";
int num=0;
int count=0;
int i=0;
char *str = line;
while (sscanf(str, "%d%n", &num,&i))
printf ("number: %d\n",num);
str+=i;
count++;
显然它不起作用,我认为我需要一种方法让 sscanf 跳过任何不是 0-9 的内容。有什么帮助吗?
谢谢
【问题讨论】:
为什么不使用strtoul
?
我建议将其读取为%c
,然后检查您扫描的char
是否在 48 到 57 之间,它们是 ASCII 表中的整数
【参考方案1】:
改成
while (sscanf(str, "%*[^0-9]%d%n", &num, &i)==1)
printf ("number: %d\n",num);
str+=i;
count++;
【讨论】:
如果字符串以数字开头,则循环将失败:(【参考方案2】:用空格替换所有非数字字符,然后将它们全部替换为scanf
。您需要对负数进行调整,但我对此进行了测试,它为给定输入提供了您想要的输出。
char line [ 200 ] ="T06 1/ 0 16/ 2 3/15 41/40 17/36 0/11 0/11 0/11 1/14 1/ 7";
int num=0;
int count=0;
int i=0;
char *str = line;
for (int i = 0; i < strlen(line); i++)
if (!isdigit(line[i]))
line[i] = ' ';
while (sscanf(str, "%d%n", &num,&i) == 1)
printf ("number: %d\n",num);
str+=i;
count++;
【讨论】:
【参考方案3】:#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
enum oflow OFL_GOOD, OFL_OVER, OFL_UNDER ;
int getnums(const char *str, int nums[], enum oflow oflow[], int n)
int i;
for (i = 0; *str; )
char *junk;
long val;
str += strcspn(str, "0123456789+-");
if (!*str)
break;
errno = 0;
val = strtol(str, &junk, 10);
if (junk > str)
if (i < n)
if (((val == LONG_MIN) && errno == ERANGE) || (val < INT_MIN))
nums[i] = 0;
oflow[i++] = OFL_UNDER;
else if (((val == LONG_MAX) && errno == ERANGE) || (val > INT_MAX))
nums[i] = 0;
oflow[i++] = OFL_OVER;
else
oflow[i] = OFL_GOOD;
nums[i++] = val;
else
i++;
str = junk;
else
str++; /* no number was pulled out: skip one char and try again */
return i;
int main(int argc, char **argv)
int nums[256];
enum oflow oflow[256];
if (argc > 1)
int n = getnums(argv[1], nums, oflow, 256);
int i;
if (n > 256)
printf("array is too small: we need %d elements\n", n);
n = 256;
for (i = 0; i < n; i++)
if (oflow[i])
printf("nums[%d] = %sflow\n", i, oflow[i] == OFL_OVER ? "over" : "under");
else
printf("nums[%d] = %d\n", i, nums[i]);
return 0;
测试:
$ ./nums "" $ ./nums "0" 数字[0] = 0 $ ./nums "-" $ ./nums "+" $ ./nums "+1" 数字[0] = 1 $ ./nums "-1" 数字[0] = -1 $ ./nums "abc" $ ./nums "asd+asdf+1 -0+1-3234abc-10zzz-" 数字[0] = 1 数字[1] = 0 数字[2] = 1 数字[3] = -3234 数字[4] = -10 $ ./nums "+++-1+++" 数字[0] = -1 $ ./nums "++" $ ./nums "1+11111111111111111111111-111111111111111111111" 数字[0] = 1 nums[1] = 溢出 nums[2] = 下溢 $ ./nums "$(seq 1 300)" |头-5 数组太小:我们需要 300 个元素 数字[0] = 1 数字[1] = 2 数字[2] = 3 数字[3] = 4 $ ./nums "$(seq 1 300)" |尾-5 数字[251] = 252 数字[252] = 253 数字[253] = 254 数字[254] = 255 数字[255] = 256作业练习:在什么情况下junk == str
在strtol
之后,以使str++
案例执行?为什么我们需要这个逻辑?
【讨论】:
【参考方案4】:要过滤除数字以外的所有内容,请在循环中使用 strcspn()
和 sscanf()
:
int i;
while (sscanf(str += strcspn(str, "0123456789"), "%d%n", &num, &i) == 1)
printf("number: %d\n", num);
count++;
str += i;
【讨论】:
【参考方案5】:sscanf
使用起来确实很痛苦,如果你的输入每次都不一样,那就更糟了。您可以尝试正则表达式,或者您可以尝试手动解析整数,如下所示:
int i;
int num = 0;
int num_valid = 0;
int count = 0;
for(i = 0; line[i]; i++) // loop through every character
if(line[i] >= '0' && line[i] <= '9') // check to see if it's a digit
num *= 10; // scale up num
num += lin[i] - '0'; // convert ASCII to INT
num_valid = 1; // indicate that num contains a real number
else if(num_valid) // if the number is done
printf ("number: %d\n",num);
count++;
num = 0;
num_valid = 0;
【讨论】:
【参考方案6】:OP 差不多了!
为sscanf()
的字符串结尾和返回值添加测试。
char line[200] = "T06 1/ 0 16/ 2 3/15 41/40 17/36 0/11 0/11 0/11 1/14 1/ 7";
int num;
int count = 0;
char *str = line;
while (*str)
int i; // Place to save count of characters scanned.
if (1 == sscanf(str, "%d%n", &num, &i))
printf("number: %d\n", num);
count++;
str += i;
else
str++; // Go to the next character
【讨论】:
以上是关于从c中的复杂字符串中读取整数的主要内容,如果未能解决你的问题,请参考以下文章