从stdin读取字符串

我试图用这种格式从stdin读取一行:

Boston "New York" "San Francisco" Memphis (请注意,其中包含空格的字符串位于括号之间。另请注意,每个城市名称都以空格分隔。)我试图一次用scanf读取一个, fgets整行然后标记,但结果不好。 我假装将所有内容存储在多维字符数组中供以后使用。

关于如何解决这个问题的任何建议? 先感谢您!

您可以阅读整行,并轻松自己解析。 如果你来的第一个非空白字符不是“,那么读到下一个空格。如果是,则读到下一个”,假设你不需要担心转义引号。

这是一个简单的实现:

 #include  #include  #include  #include  #define MAX_BUFFER 100 #define MAX_STRINGS 10 int main(void) { char buffer[MAX_BUFFER]; if ( !fgets(buffer, MAX_BUFFER, stdin) ) { fprintf(stderr, "Couldn't get input.\n"); return EXIT_FAILURE; } else { /* Remove trailing newline, if present */ size_t length = strlen(buffer); if ( length && buffer[length - 1] == '\n' ) { buffer[length - 1] = '\0'; } } char *my_strings[MAX_STRINGS + 1] = {NULL}; int read_strings = 0; char *buf_ptr = buffer; while ( *buf_ptr && read_strings < MAX_STRINGS ) { char temp_buf[MAX_BUFFER] = {0}; char *temp_ptr = temp_buf; /* Skip leading whitespace */ while ( *buf_ptr && isspace(*buf_ptr) ) { ++buf_ptr; } if ( *buf_ptr ) { if ( *buf_ptr == '"' ) { /* If starts with '"', read to next '"'... */ ++buf_ptr; /* Skip first " */ while ( *buf_ptr && *buf_ptr != '"' ) { *temp_ptr++ = *buf_ptr++; } if ( *buf_ptr ) { ++buf_ptr; /* Skip second " */ } } else { /* ...otherwise, read to next whitespace */ while ( *buf_ptr && !isspace(*buf_ptr) ) { *temp_ptr++ = *buf_ptr++; } } /* Copy substring into string array */ my_strings[read_strings] = malloc(strlen(temp_buf) + 1); if ( !my_strings[read_strings] ) { fprintf(stderr, "Couldn't allocate memory.\n"); return EXIT_FAILURE; } strcpy(my_strings[read_strings++], temp_buf); } } for ( size_t i = 0; my_strings[i]; ++i ) { printf("String %zu: %s\n", i + 1, my_strings[i]); free(my_strings[i]); } return 0; } 

样本输出:

 paul@MacBook:~/Documents/src/scratch$ ./ql Boston "New York" "San Francisco" Memphis String 1: Boston String 2: New York String 3: San Francisco String 4: Memphis paul@MacBook:~/Documents/src/scratch$ ./ql a quoted "word" and "some quoted words" and an "unclosed quoted string String 1: a String 2: quoted String 3: word String 4: and String 5: some quoted words String 6: and String 7: an String 8: unclosed quoted string paul@MacBook:~/Documents/src/scratch$ 

这是一个简单的实现:

 #include  #include  #include  int main(){ char line[128] = "Boston \"New York\" \"San Francisco\" Memphis\n"; //fgets(line, sizeof(line), stdin);//Boston "New York" "San Francisco" Memphis char array[10][32]; char *p; int i, n, len; n = 0; for(p = line ; *p ; p += len){ while(isspace(*p))//skip white space ++p; if(!*p)break; if(*p=='"'){ sscanf(p, "\"%31[^\"]\"%n", array[n++], &len); } else { sscanf(p, "%31s%n", array[n++], &len); } } for(i=0;i 

您可以将其分解为两个不同的问题:

  1. 如果您看到" ,读取字符直到下一个" ,则将引号之间的字符串复制到多维数组的下一个可用索引

  2. 读取char直到看到空格字符,然后将最后一个空格和当前空间之间的字符串(单词)复制到多维数组的下一个可用索引。

这假设您的输入格式正确,每个引号都有相应的对。 即它没有"Memphis或类似的东西。

为什么不在每个城市名称之后将null分配给字节?

这将需要一个简单的算法只传递一次char数组。 同时,您可以在指针数组中添加指向每个城市名称开头的指针。 所以你得到了多维char数组。

唯一的问题 – 删除引号。 原算法的小细化将解决这个问题。