由于输入的格式化,我认为使用 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 ?
答案 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);
}