用它们之间的逗号读取整数

时间:2017-03-28 13:41:59

标签: c strtok

由于输入的格式化,我认为使用 strtok 会是最好的。 但是在尝试检测错误时我遇到了一些问题:

程序读取的一行示例:

 .data 123,456,89 
 .data     12,   34,   53   ,   64

这些都没关系。

我的问题是输入不正确时,例如:

 .data 200 4000 // no comma speration
 .data 1, ,3 // ,3 should be an error
 .data 4, // the extra , should be an error
 .data 12.2 // the .2 should be an error
 and so on

我的代码(SIZE用于缓冲区大小= 30,valid_num通过令牌查看所有字符是否都是数字),我们的想法是首先检查令牌的有效性并将它们添加到缓冲区(如果所有数字都是是有效的,将数字添加到我的数据库:

 while((sptr = strtok(NULL, ", \t\n")) != NULL){ //this is after reading using strtok before.
    if(i < SIZE && valid_num(sptr)){ //buffer is not full and the token contains only numbers
        temp_num = atoi(sptr);
        if(temp_num >= MIN_VAL && temp_num <= MAX_VAL){ //number is within the required size
            buffer[i] = temp_num; /*fill buffer*/
            i++;
        }
        else{
            fprintf(stderr, "(%d) Error: %d is out of bounds. Valid numbers are between %d and %d\n", line_count, temp_num, MIN_VAL, MAX_VAL);
        }
    }
    else{
        fprintf(stderr, "(%d) Error: %s is not a valid number\n",line_count, sptr);
    }
    tok_count++;
}

if(i == tok_count){ //if all tokens were read correctly, add the data to database.
    DC += add_data(buffer, tok_count, DC, data_Table);
}
else{
    if(sptr != NULL){
    fprintf(stderr, "(%d) Error: %s is not a digit, .data can only be used for integers\n", line_count, sptr);
    }

}

我是否应尝试使用 sscanf 进行相同操作,即使输入的长度未知?

如何执行某种模式?号码 - 逗号 - 号码......

也许在循环中使用了一些不同的 strtok

1 个答案:

答案 0 :(得分:0)

许多方法来解析该行。

OP temp_num = atoi(sptr);未检测到溢出,因为1)atoi()溢出未定义且2)没有错误返回值。

我相信下面的内容将会应对所有恶意投入。它不使用strtok(),而是strtol()来查找非数字输入。

利用帮助函数可以明确每个步骤。

#include <ctype.h>
#include <errno.h>
#include <stdlib.h>

void consume_whitespace(char **input) {
  while (isspace((unsigned char ) **input))
    (*input)++;
}

int parse_int(char **input, int *dest) {
  char *endptr;
  errno = 0;
  long y = strtol(*input, &endptr, 10);
  if (*input == endptr) return -1; // no conversion
  if (errno) return -1;  // overflow
  #if LONG_MIN < INT_MIN || LONG_MAX > INT_MAX
    if (y < INT_MIN || y > INT_MAX) return -1;  // overflow
  #endif
  *input = endptr;
  *dest = (int) y;
  return 0;
}

int parse_data_line(char *input, const char *prefix, int *dest, int n) {
  size_t prefix_length = strlen(prefix);
  if (memcmp(input, prefix, prefix_length)) return -1;
  input += prefix_length;

  int i;
  for (i = 0; i < n; i++) {
    consume_whitespace(&input);
    if (*input == '\0') break;
    if (i > 0 && *input++ != ',') return -1;
    if (parse_int(&input, &dest[i])) return -1;
  }
  consume_whitespace(&input);
  if (*input) return -1;  // extra text
  return i;
}

使用示例

#define SIZE 30
int main() {
  int numbers[SIZE];
  char *input = foo();
  int count = parse_data_line(input, ".data", numbers, SIZE);
  if (count < 0) puts("Fail");
  else bar(numbers, count);
}