[英]Reading strings from stdin
我試圖用這種格式從stdin讀取一行:
Boston "New York" "San Francisco" Memphis
(請注意,其中有空格的字符串在括號之間。另請注意,每個城市名稱都用空格分隔。)我試圖用scanf一次讀取一個, fgets整行,然后標記,但結果不好。 我假裝將所有內容存儲在多維字符數組中供以后使用。
關於如何解決這個問題的任何建議? 先感謝您!
你可以閱讀整行,並輕松地自己解析。 如果您遇到的第一個非空白字符不是“,則讀取直到下一個空格。如果是,則讀取直到下一個”,假設您不需要擔心轉義引號。
這是一個簡單的實現:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#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 <stdio.h>
#include <string.h>
#include <ctype.h>
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<n;++i){
printf("%s\n", array[i]);
}
return 0;
}
您可以將其分解為兩個不同的問題:
如果您看到"
,讀取字符直到下一個"
,則將引號之間的字符串復制到多維數組的下一個可用索引
讀取char直到看到空格字符,然后將最后一個空格和當前空間之間的字符串(字)復制到多維數組的下一個可用索引。
這是假設您的輸入格式正確,每個引號都有相應的對。 即它沒有"Memphis
或類似的東西。
為什么不在每個城市名稱之后將null分配給字節?
這將需要一個簡單的算法只傳遞一次char數組。 同時,您可以在指針數組中添加指向每個城市名稱開頭的指針。 所以你得到了多維char數組。
唯一的問題 - 刪除引號。 原算法的小細化將解決這個問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.