只读c中复杂字符串的整数

时间:2014-02-20 00:07:00

标签: c

我试图只读取字符串中的整数。每次迭代时,空格和非整数字符基本上是随机的。理想情况下,我的代码将遍历此代码并仅打印(或以其他方式存储)整数。所以对于这个测试用例,它将是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的东西。有什么帮助吗?

由于

6 个答案:

答案 0 :(得分:2)

更改为

while (sscanf(str, "%*[^0-9]%d%n", &num, &i)==1){
    printf ("number: %d\n",num);
    str+=i;
    count++;
}

答案 1 :(得分:1)

#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"
nums[0] = 0
$ ./nums "-"
$ ./nums "+"
$ ./nums "+1"
nums[0] = 1
$ ./nums "-1"
nums[0] = -1
$ ./nums "abc"
$ ./nums "asd+asdf+1  -0+1-3234abc-10zzz-"
nums[0] = 1
nums[1] = 0
nums[2] = 1
nums[3] = -3234
nums[4] = -10
$ ./nums "+++-1+++"
nums[0] = -1
$ ./nums "++"
$ ./nums "1+11111111111111111111111-111111111111111111111"
nums[0] = 1
nums[1] = overflow
nums[2] = underflow
$ ./nums "$(seq 1 300)" | head -5
array is too small: we need 300 elements
nums[0] = 1
nums[1] = 2
nums[2] = 3
nums[3] = 4
$ ./nums "$(seq 1 300)" | tail -5
nums[251] = 252
nums[252] = 253
nums[253] = 254
nums[254] = 255
nums[255] = 256

家庭作业练习:在junk == str之后strtol的情况是什么,以便str++案例执行?为什么我们需要这种逻辑?

答案 2 :(得分:1)

用空格替换所有非数字字符,然后只用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 :(得分:0)

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;
    }
}

答案 4 :(得分:0)

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;
int i;
char *str = line;   

while (*str) {
  if (1 == sscanf(str, "%d%n", &num, &i)){
    printf ("number: %d\n", num);
    str += i;
    count++;
  }
  else str++;
}

答案 5 :(得分:0)

要过滤除数字以外的所有内容,请在循环中使用 strcspn()sscanf()

int i;
while (sscanf(str += strcspn(str, "0123456789"), "%d%n", &num, &i) == 1) {
    printf("number: %d\n", num);
    count++;
    str += i;
}