从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 == strstrtol 之后,以使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中的复杂字符串中读取整数的主要内容,如果未能解决你的问题,请参考以下文章

从文件中读取 64 位整数字符串

读入字符并创建数组c ++

在c ++中输入n个空格分隔的整数

在C中将字符串的第一个字符读取为整数

从C中的txt文件中读取整数

如何从字符串变量中获取读取为整数的 CSV 整数