2015-04-27 3 views
1

У меня проблемы с чтением из гнезда. Код, который я использую, ниже, иногда он работает отлично, но в других случаях он просто печатает некоторые нечитаемые символы или некоторые случайные читаемые ... есть ли лучший способ?Чтение из гнезда в C дает странный вывод

char* answer = (char*) malloc(1024); 
    int answerLength = 0; 
    char prevChar = 0; 
    char newChar = 0; 
    while (answerLength < 1024 && read(sock, &newChar, 1) > 0) { 

      if (newChar == '\n' && prevChar == '\r') { 
        break; 
      } 
      printf("%d\n", answerLength); 
      answer[ answerLength ] = newChar; 
      answerLength++; 

      prevChar = newChar; 
    } 
    printf("%s\n", answer); 
+0

в C, не отбрасывать возвращаемое значение из malloc() (и семейства функций). «Магические» номера, такие как «1024», должны быть #defined, чтобы значительно облегчить бремя отладки и последующего обслуживания. #define name (go style style says: all caps) должно указывать на то, что 1024 означает – user3629249

+0

относительно этой строки: 'if (newChar ==' \ n '&& prevChar ==' \ r ') {' OS/компилятор будет обрабатывать разницу между окончаниями строк ОС (в некоторых ОС используется только линейная передача, в некоторых ОС используется только возврат каретки, а в некоторых ОС используется строка с несколькими символами). Компилятор будет обрабатывать детали, поэтому код должен использовать только '\ n' – user3629249

+0

предлагают использовать calloc(), а не malloc, поэтому выделенная память «уже» инициализируется ко всем '' \ 0 ', поэтому не стоит беспокоиться о добавлении нулевого терминатора во входную строку. BTW: когда answerLength 1023, следует остановить , не добавляйте еще один символ, так как добавление символа приведет к тому, что буфер ответа будет иметь место для завершения строки NUL char – user3629249

ответ

1

Ваш массив символов не может быть завершен до нуля. Это означает, что printf может печатать больше, чем то, что находится в вашем массиве, поскольку он ищет нулевое завершение, чтобы остановить вывод символов.

Вы также не инициализируете выделенную память перед ее использованием, что является плохой практикой, поскольку память может содержать случайный мусор.

Чтобы получить код, чтобы работать лучше и, надеюсь исправить вашу проблему, вы должны сделать следующее:

char* answer = malloc(1024 + 1); /* add extra byte for null terminator */ 
/* other variables the same */ 

memset(answer, '\0', 1024 + 1); /* initialise memory before use */ 
while (answerLength < 1024 && read(sock, &newChar, 1) > 0) { 
    /* loop is the same */ 
} 
printf("%s\n", answer); 

Существует также аргумент в printf, который будет сказать ему, чтобы напечатать определенное количество символов. Вроде бы так:

printf("%.*s\n", answerLength, answer); 
+0

Пожалуйста, удалите бросок из 'malloc()' , прочитайте [это] (http://stackoverflow.com/a/605858/1983495) –

+0

@iharob Спасибо :) хороший совет. – Serdalis

3

Строки в C должен быть нулевым символом, который означает, что они должны иметь символ \0 в качестве последнего символа.

Поскольку вы не гарантируете, что это произойдет в любом месте вашего кода, answer может быть дополнен мусором памяти рядом с данными, которые вы читаете.

Чтобы убедиться, что это не произойдет, используйте:

answer[answerLength] = '\0'; 
printf("%s\n", answer); 

Кроме того, вы можете просто read() все это прямо в answer, вам не нужен этот бессмысленный цикл:

int len; 
while (len = read(sock, &answer[answerLength], 1024 - answerLength)) 
    answerLength += len; 
answer[answerLength] = '\0'; 
printf("%s\n", answer); 
+0

Согласен. Важно помнить, что память, возвращаемая из malloc, будет заполнена неопределенным содержимым, она не будет обнулена если код явно не нули, t поскольку код не заканчивается вручную, «printf» может печатать любое количество мусора в конце, зависящее только от того, что было в этой памяти ранее. – antiduh

+1

Или не используйте 'printf()', а функцию, которая принимает длину как аргумент, ключевая проблема заключается в том, что 'printf()' необходимо определить, где заканчивается строка, так как она не находит '' \ 0 ' ', он продолжает читать через мусор ... –

+0

@iharob:' printf() '* can * принимает длину в качестве аргумента:' printf (%.* s \ n ", answerLength, answer)' – caf

2

Данные, которые вы читаете, не заканчиваются символом '\0', поэтому вы не можете рассматривать это как строку.

Смежные вопросы