验证CSV格式

时间:2012-04-27 05:34:10

标签: c

我正在编写一个验证CSV文件的程序。格式的限制是:

  • 一行不能以逗号结尾,必须以数字结尾;
  • 一行不能以逗号开头,必须是数字;
  • 一行可以为空;
  • 只允许一位数字作为数字(即没有数字低于0或大于9);
  • 两个逗号不能相邻,它们必须用数字分隔。

编辑:

我根据反馈对代码进行了一些更改。有人可以解释一下while循环实际上在做什么吗?为什么交换机不工作?我现在得到所有输入的1。我可以在交换机中使用isdigit吗?

#include <ctype.h>
#include <stdio.h> 

int main()
{

int c;

    while ((c = getchar()) != EOF )
    {      
        switch(c)
    {
        case'0':
            printf("1");
            break;
        case'1':
            printf("1");
            break;
        case'2':
            printf("1");
            break;
        case'3':
            printf("1");
            break;
        case'4':
            printf("1");
            break;
        case'5':
            printf("1");
            break;
        case'6':
            printf("1");
            break;
        case'7':
            printf("1");
            break;
        case'8':
            printf("1");
            break;
        case'9':
            printf("1");
            break;
        case',' :
            printf("1");
            break;
        case'\n' :
            printf("1");
            break;
        default :
            printf("0");
            break;
    }
}
}

7 个答案:

答案 0 :(得分:2)

enter image description here

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

int main(void){
    int ch;
    while(EOF!=(ch=getchar())){
        if(ch == ' '){
            while(' '==(ch=getchar()));
            goto CR;
        }
        if(isdigit(ch)){
            while(','==(ch=getchar()))
                if(isdigit(getchar()))
                    continue;
                else
                    goto NG;
            goto CR;
        }
CR:     if(ch != '\n')
            goto NG;
    }
    printf("OK");
    return EXIT_SUCCESS;
NG:
    printf("NG");
    return EXIT_FAILURE;
}

#if 0
    while(EOF!=(ch=getchar())){
        if(ch == ' '){
            while(' '==(ch=getchar()));
        } else if(isdigit(ch)){
            while(','==(ch=getchar()))
                if(!isdigit(getchar()))
                    break;//ch==','
        }
        if(ch != '\n')
            goto NG;
    }
#endif

答案 1 :(得分:0)

您的代码永远不会到达switch语句。

简而言之,递归就是:

int valid() /* This is the function definition. */
{
    int c;

    while((c = getchar()) != EOF) {
        if(!valid(c)) {  /* While not EOF you keep calling valid() 
                            You also pass 'c' - which you can't get
                            as your function _definition_ does not have 
                            any arguments. */
           return 0;     /* You never get here as valid() always, when EOF, 
                            return 1 */
        }
    }
    return 1; /* When EOF you never go _inside_ the while loop, 
                 you return 1, 
                 and back track of stack begins. */

    switch(c) { ... /* You never get here. */
}

导致valid()始终返回1

另请注意:

int valid();        /* This _declaration_ has no arguments thus indicating the 
                       _definition_ of the function can have any number of 
                       arguments. */

int valid(void);    /* This would explicitly say that the _definition_ does not
                       take any arguments. */

int valid(int);
int valid(int foo); /* These would explicitly say the _definition takes
                       one int, and one int only. */

作为电话的一个例子:

file.csv:
  0,2
  1,2

调用堆栈步骤:

Down            Up
01 main()       20 valid() return 1 so puts("1")
02 valid()      19 ... return 1
03 valid('0')   18 ... return 1
04 valid(',')   17 ... return 1
05 valid('2')   16 ... return 1
06 valid('\n')  15 ... return 1
07 valid('1')   14 Step  8 returns 1, so return 1
08 valid(',')   13 Step  9 returns 1, so return 1
09 valid('2')   12 Step 10 returns 1, so return 1
10 Now at EOF,  11 Never inside while as EOF, return 1.
 v              ^  Start popping calls from stack.
 |              |
 +--------------+

答案 2 :(得分:0)

我不知道你的程序正在遵循什么逻辑,但这里有奇怪的递归

int valid()
{
    int c;

    while((c = getchar()) !=EOF) {
        if (!valid(c)) {

您正在将int传递给valid()理想情况不接受任何内容。

我认为此代码会进入无限旋转

即使您删除了递归调用,也会遇到普通的return 1。我认为你也需要把它关掉

答案 3 :(得分:0)

查找isdigit()。这将取代你的switch语句中的一大块,并使其更短,以便更容易扫描。

此外,您可能希望一次读取一行(gets()/ fgets())而不是一次读取一个字符,然后对一行进行测试。

答案 4 :(得分:0)

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define bool int
#define false 0
#define true !false

// Rule:(SPACE* | [0-9](,[0-9])*)CR
bool isValid(char *str){
    if(*str == '\n')
        return true;
    if(*str == ' '){
        while(*++str == ' ');
        if(*str == '\n')
            return true;
        else
            return false;
    }
    if(isdigit(*str++)){
        do{
            if(*str == '\n')
                return true;
        }while(*str++ == ',' && isdigit(*str++));
        return false;
    }
    return false;
}

#define BUFF_SIZE 128

int main(void){
#ifdef DEBUG
    printf("\nEnd with comma:\n");
    printf(isValid("1,2,3,\n") ? "OK" : "NG");
    printf("\nStart with comma:\n");
    printf(isValid(",1,2,3\n") ? "OK" : "NG");
    printf("\nCR only:\n");
    printf(isValid("\n") ? "OK" : "NG");
    printf("\nSPACE and CR only:\n");
    printf(isValid("     \n") ? "OK" : "NG");
    printf("\nBelow zero:\n");
    printf(isValid("-1\n") ? "OK" : "NG");
    printf("\nGreater than nine:\n");
    printf(isValid("10\n") ? "OK" : "NG");
    printf("\nInclude two comma:\n");
    printf(isValid("3,4,,5\n") ? "OK" : "NG");
    printf("\nNormal pattern I:\n");
    printf(isValid("9\n") ? "OK" : "NG");
    printf("\nNormal pattern II:\n");
    printf(isValid("3,4,5\n") ? "OK" : "NG");
#else
    char line[BUFF_SIZE];
redo:
    fgets(line, BUFF_SIZE, stdin);
    if(NULL==strchr(line, '\n')){
        fprintf(stderr,"You have exceeded the number of characters that can be entered.\n");
        fflush(stdin);
        goto redo;
    }
    if(isValid(line))
        printf("OK\n");
    else
        printf("NG\n");
#endif
    return 0;
}

答案 5 :(得分:0)

重写版本

#include <stdio.h>
#include <ctype.h>

#define bool int
#define false 0
#define true !false

// Rule:(SPACE* | [0-9](,[0-9])*)CR
bool isValid(FILE *fp){
    int ch;
    while(EOF!=(ch=fgetc(fp))){
        if(ch == '\n')
            continue;
        if(ch == ' '){
            while((ch=fgetc(fp)) == ' ');
            if(ch == '\n')
                continue;
            else
                return false;
        }
        if(isdigit(ch)){
            do{
                if((ch=fgetc(fp)) == '\n')
                    goto cont; //continue
            }while(ch == ',' && isdigit(fgetc(fp)));
            return false;
        }
        return false;
        cont:;
    }
    return true;
}

int main(void){
    FILE *file;
#ifdef DEBUG
    file = fopen("testdata.csv","r");
#else
    file = stdin;
#endif
    if(isValid(file))
        printf("OK");
    else
        printf("NG");
    fclose(file);
    return 0;
}

答案 6 :(得分:0)

#include <stdio.h>
#include <stdlib.h>

typedef enum STATUS {
    START,SPC,NUM,COMMA,CR
} Status;

int main(void){
    int ch;
    Status pre_stat, stat;
    pre_stat=stat=START;

    while(EOF!=(ch=getchar())){
        switch(ch){
        case '\n':
            stat = CR;
            if(pre_stat == START || pre_stat == SPC || pre_stat == NUM){
                //pre_stat = stat;
                pre_stat = START;//line end move to line start, reset status
            } else
                goto NG;
            break;
        case ' ':
            stat = SPC;
            if(pre_stat == START || pre_stat == SPC){
                pre_stat = stat;
            } else
                goto NG;
            break;
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
            stat = NUM;
            if(pre_stat == START || pre_stat == COMMA){
                pre_stat = stat;
            } else
                goto NG;
            break;
        case ',':
            stat = COMMA;
            if(pre_stat == NUM){
                pre_stat = stat;
            } else
                goto NG;
            break;
        default:
            goto NG;
        }
    }
    printf("OK");
    return EXIT_SUCCESS;
NG:
    printf("NG");
    return EXIT_FAILURE;
}