从C中的文本文件中读取解析数据的最佳方法?

我正在进行一项任务,处理从文本文件中读取数据,并将该数据解析为各种数组。 例如,我的文本文件的一部分如下所示:

arbrick pts/26 141.219.210.189 Thu Mar 29 11:23 - 11:24 (00:00) rjmcnama pts/27 141.219.205.107 Thu Mar 29 11:02 still logged in ajhoekst pts/26 99.156.215.40 Thu Mar 29 10:59 - 11:08 (00:08) eacarter pts/31 141.219.162.145 Thu Mar 29 10:50 - 10:51 (00:00) kmcolema pts/31 141.219.214.128 Thu Mar 29 09:44 - 09:47 (00:03) 

我需要将数据解析为以下数组:用户ID,终端,IP地址和事件时间。 考虑到列之间没有一致的空白区,我该怎么做?

编辑:我尝试使用Thiruvalluvar提供的建议,但我无法让它工作。 但是,我确实切换到了sscanf,而且几乎 ……

 while(!feof(myfile)) { fgets(buffer, 256, myfile); sscanf(buffer, "%s %s %s %s", user_id[i], terminal_id[i], ip_addr[i], events[i]); } /*End while not EOF*/ 

工作的是user_id,terminal_id和ip_addr数组。 但是,事件数组尚未完美运行。 由于events数组是一个包含空格的字符串,我如何使用sscanf将剩余的缓冲区添加到events数组中?

我认为,问题的真正部分是如何仅在4个arrays中使用它们。 例如:

 arbrick pts/26 141.219.210.189 Thu Mar 29 11:23 - 11:24 (00:00) 

用空格对这一行进行标记是为了给出很多字符串。 但我们只对将整行分成4行而不是更多的兴趣感兴趣。

解:

  1. 使用fgets()读取该行。

  2. 使用空格作为分隔符,使用strtok()strtok_r() (用于线程安全)对其进行strtok_r()

  3. 将前3个字符串读入数组:user_id,terminal_id和ip_address

  4. 将其余字符串存储(并附加)到数组events

     int i = 0; int line_index = 0; char *p; while(...) //loop to read the file { fgets(line); p = strtok(line, " "); i=0; while(p!=NULL) { if(i==0) strcpy(user_id[line_index], p); if(i==1) strcpy(terminal_id[line_index], p); if(i==2) strcpy(ip_addr[line_index], p); else strcat(events[line_index], p); //anything else goes into array events i++; } line_index++; } //end of file-reading loop. 

使用fgets读取一行。 使用sscanf调用在线上操作以存储信息,因为数据不是一致的forms(例如,“仍然登录”)。 sscanf将读取并丢弃格式说明符之间的任何空格。

试试这个:

 #include  #include  #include  char** split (char* string, const char* delim) { char* p; int i = 0; char** array; array = malloc(strlen(string) * sizeof (char*)); p = strtok (string, delim); while (p != NULL) { array[i] = malloc(sizeof(char) ); array[i++] = p; p = strtok(NULL, delim); } return array; } void parseLine(char *line, char *user, char term[], char ip[], char event[]) { char *copy = line; char **array = split(copy, " "); strcpy(user, *array++); strcpy(term, *array++); strcpy(ip, *array++); array++;array++;array++; strcpy(event, *array++); if (strcmp(*array, "-")) { strcat(event, " still logged in"); } else { array++; strcat(event, " - "); strcat(event, *array++); } } int main(void) { char line[2048]; char user[64], term[64], ip[64], event[64]; while (fgets(line, 2048, stdin) != NULL) { parseLine(line, user, term, ip, event); printf("[%s][%s][%s][%s]\n", user, term, ip, event); /* use an array to save them ... */ } return 0; } 

然后: ./a.out < file.txt

对于它的价值,这是我的建议。 滚动您自己的字符串标记符,如下所示:

 static char *string_tok(char **stringp, const char *delim) { char *tok = *stringp + strspn(*stringp, delim); char *end = tok + strcspn(tok, delim); if (*end) { *end++ = '\0'; end += strspn(end, delim); } *stringp = end; return tok; } 

然后只需按顺序为每个令牌调用它。 在第三次调用string_tok ,缓冲区buf保存一个指向字符串剩余部分(事件)开始的指针。 请注意,buf必须是可写的。

 static void parse(char * buf) { char * user_id = string_tok(&buf, " \t"); char * term = string_tok(&buf, " \t"); char * ip = string_tok(&buf, " \t"); printf("user_id: %s\n", user_id); printf("terminal: %s\n", term); printf("ip addr: %s\n", ip); printf("events: %s\n\n", buf); }