Лучший способ прочитать данные разбора из текстового файла в C? - PullRequest
1 голос
/ 29 марта 2012

Я работаю над заданием, которое связано с чтением данных из текстового файла и разбором этих данных в различных массивах.Например, часть моего текстового файла выглядит следующим образом:

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) 

Мне нужно разобрать данные в следующие массивы: идентификатор пользователя, терминал, 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.Тем не менее, массив событий пока не работает идеально.Поскольку массив событий представляет собой строку, содержащую пробелы, как я могу использовать sscanf, чтобы добавить остаток буфера в массив событий?

Ответы [ 4 ]

4 голосов
/ 29 марта 2012

Я думаю, реальная часть вопроса заключается в том, как обработать их только в 4 массивах. E.g.:

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

Маркировка этой строки с пробелами дает много строк. Но нас интересует только разбиение всей строки только на 4 строки, не более того.

Решение:

  1. Считайте строку, используя fgets().

  2. Токенизируйте его, используя strtok() или 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.
    
2 голосов
/ 29 марта 2012

Используйте fgets для чтения по одной строке за раз. Работайте в режиме линии, используя sscanf вызовы для хранения информации, поскольку данные не находятся в согласованной форме (например, «все еще зарегистрированы»). sscanf будет считывать и удалять любые пробелы между спецификаторами формата.

0 голосов
/ 30 марта 2012

Для чего это стоит, вот мое предложение. Сверните свой собственный токенайзер строк следующим образом:

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);
}
0 голосов
/ 29 марта 2012

Попробуйте:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...