2017-03-28 5 views
0

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

그래서 ... 잘못된 입력을 구문 분석 할 싶어 시도? 왜? 성취하고자하는 것은 무엇입니까? – ForceBru

+0

'strpbrk'을 사용하여 분할 문자가 무엇인지 알 수 있고 aqccordingly 행동한다면 더 잘 작동할까요? –

+0

하나를 구문 분석하고 오류를 던지거나 모두 함께 구문 분석하지 마십시오 – Immanuel

답변

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