Символы барахла, выведенные после анализа из STDIN в C - PullRequest
1 голос
/ 09 января 2012

Я получаю нежелательный символ, который будет выведен в самом конце текста, который я прочитал:

hum 1345342342 ~Users/Documents ecabd459 //line that was read in from stdin
event action: hum_?
event timestamp: 1345342342
event path: ~Users/Documents
event hash: ecabd459

В конце значения действия события есть '_?'символ мусора, который также выводится.Это можно исправить, установив в последней позиции переменной нулевой терминатор (event.action[3] = '\0'), что все хорошо, но я озадачен тем фактом, что другой массив символов event.hash не демонстрирует такого типа поведения.Я создаю / печатаю их идентичным образом, но хэш не ведет себя одинаково.

Примечание: Я подумывал, может быть, это связано с тем, что за значением хеша строго следует символ новой строки (от которого я, кстати, избавляюсь), поэтому я протестировал свою программу с помощью reупорядоченный ввод безрезультатно (то есть добавлен дополнительный пробел и слово после позиции хеш-значения в строке).

Соответствующий код приведен ниже:

struct Event{
    char action[4];
    long timestamp;
    char* path;
    char hash[9];
};   

// parse line and return an Event struct
struct Event parseLineIntoEvent(char* line) {
    struct Event event;
    char* lineSegment;

    int i = 0;
    lineSegment = strtok(line, " ");
    while (lineSegment != NULL) {
        if (i > 3) {
            printf("WARNING: input format error!\n");
            break;
        }
        if (i == 0)
            strncpy(event.action, lineSegment, sizeof(event.action)-1);
        else if(i == 1)
            event.timestamp = atoi(lineSegment);
        else if(i == 2) {
            event.path = malloc(sizeof(lineSegment));
            strcpy(event.path, lineSegment);
        } else if(i == 3)
            strncpy(event.hash, lineSegment, sizeof(event.hash)-1);
        lineSegment = strtok(NULL, " ");
        i++;
    } // while
    return event;
} // parseLineIntoEvent()

int main (int argc, const char * argv[]) {
//...
    printf("%s\n",line); //prints original line that was read in from stdin
    struct Event event = parseLineIntoEvent(line);
    printf("event action: %s\n", event.action);
    printf("event timestamp: %lu\n", event.timestamp);
    printf("event path: %s\n", event.path);
    printf("event hash: %s\n", event.hash);
    free(event.path);
    free(line);
//...
    return 0;
}

РЕДАКТИРОВАТЬ: Я прочитал в строке с этой функцией, которая избавляет от символа новой строки:

// read in line from stdin, eliminating newline character if present
char* getLineFromStdin() {
    char *text;
    int textSize = 50*sizeof(char);
    text = malloc(textSize);

    if ( fgets(text, textSize, stdin) != NULL ) {
        char *newline = strchr(text, '\n'); // search for newline character
        if ( newline != NULL ) {
            *newline = '\0'; // overwrite trailing newline
        }
    }
    return text;
}

Заранее спасибо!

Ответы [ 4 ]

3 голосов
/ 09 января 2012

Это ошибка:

event.path = malloc(sizeof(lineSegment));

вернет sizeof(char*), когда вам потребуется длина плюс единица для завершающего символа NULL:

event.path = malloc(sizeof(char) * (strlen(lineSegment) + 1));

Чтобы избежать необходимости вставлять терминаторы нулевых строк в action и hash, вы можете инициализировать event:

struct Event event = { 0 };
2 голосов
/ 09 января 2012

Со страницы руководства Linux :

The strncpy() function is similar, except that at most n bytes of src are copied.
Warning: If there is no null byte among the first n bytes of src, the string
placed in dest will not be null-terminated.

При выполнении strncpy необходимо убедиться, что строка назначения правильно завершена.

Изменить настройкуполя event.action:

if (i == 0)
{
    strncpy(event.action, lineSegment, sizeof(event.action)-1);
    event.action[sizeof(event.action)-1] = '\0';
}
1 голос
/ 09 января 2012

но я озадачен тем фактом, что другой массив символов char.hash не демонстрирует такой тип поведения

Тебе не повезло. хэш [8], возможно, получил '\ 0' по чистой (плохой) удаче.

Попробуйте установить что-нибудь "случайное" перед циклом strtok

    int i = 0;
    event.hash[8] = '_';             /* forcing good-luck */
    lineSegment = strtok(line, " ");
    while (lineSegment != NULL) {
0 голосов
/ 09 января 2012

Это потому, что строка "num" берет только три элемента из массива символов из 4 элементов Event.action, а четвертый элемент останется неустановленным.Поскольку для элемента массива Event.action ничего не установлено, оно будет указывать на случайную ячейку памяти, в которой хранится некоторое случайное значение.Когда вы печатаете этот массив символов, он будет печатать все элементы вместо тех, которые указывают на действительные данные.Это приводит к появлению символа мусора.

...