我正试图找出如何读取输入的多种方式。输入可以像这样:
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到信号输入的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");
}
您的输入格式允许在令牌之间使用可选的空白,包括换行符。你的两个例子的不同之处在于一个使用了那个选项,而另一个没有。用最基本的术语来说,解决方案就是让解析器也忽略(所有)记号之间的空白。这样的解析器处理两种形式的输入,以及其他变体。
然而,我确实认为,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()
也一样,只要你足够小心。