c - Reading integers with commas between them -
i assumed using strtok best because of formatting of input. i've run few problems when trying detect errors:
an example of line program read:
.data 123,456,89 .data 12, 34, 53 , 64
these ok.
my problem when input incorrect, example:
.data 200 4000 // no comma speration .data 1, ,3 // ,3 should error .data 4, // , should error .data 12.2 // .2 should error , on
my code (size buffer size = 30, valid_num goes through token see if chars numbers), idea first check validity of tokens , add them buffer, if numbers valid, add numbers data base:
while((sptr = strtok(null, ", \t\n")) != null){ //this after reading using strtok before. if(i < size && valid_num(sptr)){ //buffer not full , token contains numbers temp_num = atoi(sptr); if(temp_num >= min_val && temp_num <= max_val){ //number within required size buffer[i] = temp_num; /*fill buffer*/ i++; } else{ fprintf(stderr, "(%d) error: %d out of bounds. valid numbers between %d , %d\n", line_count, temp_num, min_val, max_val); } } else{ fprintf(stderr, "(%d) error: %s not valid number\n",line_count, sptr); } tok_count++; } if(i == tok_count){ //if tokens read correctly, add data database. dc += add_data(buffer, tok_count, dc, data_table); } else{ if(sptr != null){ fprintf(stderr, "(%d) error: %s not digit, .data can used integers\n", line_count, sptr); } }
should try same sscanf, though length of input unknown?
how can enforce pattern? number - comma - number ...
perhaps using few different strtok inside loop?
there many ways parse line.
op's temp_num = atoi(sptr);
not detect overflow 1) overflow atoi()
undefined , 2) there no error return value.
i believe below cope hostile input. not use strtok()
, strtol()
find non-numeric input.
making use of helper functions provides clarity of each step.
#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; (i = 0; < 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; // text return i; }
example usage
#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); }
Comments
Post a Comment