C语言 水平和垂直输入阅读

hrirmatl  于 2022-12-22  发布在  其他
关注(0)|答案(1)|浏览(134)

我正试图弄清楚如何以多种方式读取输入。输入可以是这样的。

N:{-4,2,1}
E:{1,1,9}
W:{-2,5,3}
S:{7,1}

或者像这样

E:{9,1,1}N:{1,2,-4}W:{3,5,-2}S:{7,1}

我在我的代码中添加了单词END的检查。它应该是在EOF上工作的,但是在我的Windows机器上它不工作。所以输入END来表示输入的结束。到目前为止,我设法让它们都单独工作...但是我需要它们同时工作。

char *skip_whitespace(char *str)
{
    //skip any leading whitespace characters
    while (*str == ' ' || *str == '\t')
        str++;
    return str;
}
void read_tokens(int *north, int *west, int *east, int *south, int *north_size, int *west_size, int *east_size, int *south_size)
{
    //buffer for reading in input
    char buffer[MAX_TOKENS];
    //read in the input line by line
    while (fgets(buffer, MAX_TOKENS, stdin) != NULL)
    {
        //remove the newline character from the end of the line
        buffer[strcspn(buffer, "\n")] = 0;
        //check for the "END" string to end the input
        if (strcmp(buffer, "END") == 0)
            break;

        //split the line at the curly brace character
        char *direction_token = strtok(buffer, "{");
        char *tokens = strtok(NULL, "}");

        //get the direction
        char direction = direction_token[0];
        //skip any leading or trailing whitespace characters
        tokens = skip_whitespace(tokens);

        //split the tokens at each comma
        char *token = strtok(tokens, ",");

        //determine the direction and store the tokens in the appropriate array
        if (direction == 'N')
        {
            while (token != NULL)
            {
                //skip any leading or trailing whitespace characters
                token = skip_whitespace(token);
                //store the token in the array
                north[*north_size] = atoi(token);
                (*north_size)++;
                //find the next token
                token = strtok(NULL, ",");
            }
        }
        else if (direction == 'W')
        {
            while (token != NULL)
            {
                //skip any leading or trailing whitespace characters
                token = skip_whitespace(token);
                //store the token in the array
                west[*west_size] = atoi(token);
                (*west_size)++;
                //find the next token
                token = strtok(NULL, ",");
            }
        }
        else if (direction == 'E')
        {
            while (token != NULL)
            {
                //skip any leading or trailing whitespace characters
                token = skip_whitespace(token);
                //store the token in the array
                east[*east_size] = atoi(token);
                (*east_size)++;
                //find the next token
                token = strtok(NULL, ",");
            }
        }
        else if (direction == 'S')
        {
            while (token != NULL)
            {
                //skip any leading or trailing whitespace characters
                token = skip_whitespace(token);
                //store the token in the array
                south[*south_size] = atoi(token);
                (*south_size)++;
                //find the next token
                token = strtok(NULL, ",");
            }
        }
        else
        {
            //invalid direction = error
            printf("Nespravny vstup.\n");
        }
    }
}

这是主要的函数。对任何感兴趣的人来说都是调用和打印。

int main(void)
{
    //field for token values
    int north[MAX_TOKENS], west[MAX_TOKENS], east[MAX_TOKENS], south[MAX_TOKENS];
    //sizes of token value fields
    int north_size = 0, west_size = 0, east_size = 0, south_size = 0;
    printf("Input:\n");
    //fetch token values ​​from input
    read_tokens(north, west, east, south, &north_size, &west_size, &east_size, &south_size);


    printf("N: { ");
    for (int i = 0; i < north_size; i++)
        printf("%d, ", north[i]);
    printf("}\n");

    printf("W: { ");
    for (int i = 0; i < west_size; i++)
        printf("%d, ", west[i]);
    printf("}\n");

    printf("E: { ");
    for (int i = 0; i < east_size; i++)
        printf("%d, ", east[i]);
    printf("}\n");

    printf("S: { ");
    for (int i = 0; i < south_size; i++)
        printf("%d, ", south[i]);
    printf("}\n");
}
gpfsuwkq

gpfsuwkq1#

你有一个输入格式,允许在标记之间使用可选的空格,包括换行符。你的两个例子的不同之处仅仅在于一个使用了这个选项,而另一个没有。用最基本的术语来说,解决方案是让你的解析器也忽略标记之间的(所有)空格。这样的解析器可以处理两种形式的输入,也可以处理其他变体。
然而,我确实认为fgets()在这里更多的是一种负担而不是一种帮助。您的输入基本上不是面向行的,并且使用fgets()时,您需要(但目前还不需要)注意和处理将一个长行拆分为两个或更多个读取的情况。我建议直接从流中对输入进行标记化,而不是首先将其读入中间缓冲区。
我知道scanf()很不受欢迎,但它可能很好地满足了您的需求。它已经知道如何跳过空格、识别整数和匹配特定字符。也许可以这样做:

while (1) {
    char direction;
    char delim;
    int result;

    // scan first part:
    result = scanf(" %c : %c", &direction, &delim);
    if (result == EOF) {
        // end of file
    } else if (result != 2 || !is_valid_direction(direction) || delim != '{') {
        // invalid input ...

        // ... or maybe (part of) an "END" keyword if you decide to
        // go ahead with that
    }

    // ... handle direction code ...

    do {
        // scan number
        int num;
        result = scanf("%d %c", &num, &delim);
        if (result != 2 || (delim != ',' && delim != '}')) {
            // invalid input ...
            // unless empty number lists are allowed: N:{}
        }

        // store number ...

    } while (delim == ',');
}

如果你想避免scanf(),那么你可以通过getchar()fgetc()一次阅读一个字符来做基本相同的事情,或者,是的,如果你足够小心的话,也可以用fgets()
当然,这只是示意图,并不是所需解析器的完整实现

相关问题