2014-11-10 4 views
0

Я пытаюсь использовать функцию getdelim, чтобы прочитать содержимое всего текстового файла в строке.Недопустимый аргумент, полученный от getdelim

Вот код, я использую:

ssize_t bytesRead = getdelim(&buffer, 0, '\0', fp); 

Это не удается, однако, с strerror(errno) говоря: «Ошибка: Недопустимый аргумент»

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

буфер NULL инициализирован, а поэтому он не кажется, что
FP также не сообщать об ошибках и файл открывается совершенно

EDIT: Моя реализация основана на ответ от этого StackOverflow вопроса Easiest way to get file's contents in C

+2

Вы знаете, что вы передаете NULL (как 0) для второго параметра. [Проверьте документацию] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/getdelim.html), потому что я не верю, что это разрешено. Функция ожидает 'size_t *'; значение * указывает на * может быть '0', но сам указатель не может быть так. И 'buffer' содержит адрес динамического буфера, выделенный из семейства' malloc', он также должен быть 'NULL' на входе. – WhozCraig

+0

Я пробовал, но это все равно дало то же самое.Он игнорирует значение размера, если первый аргумент равен NULL. – Arcana

+0

Он игнорирует значение ** на ** адрес размера; он не игнорирует сам адрес. Он по-прежнему будет использовать адрес для хранения размера вывода. Фактически вы используете нулевой символ (0-октет) в качестве разделителя? действительно? – WhozCraig

ответ

2

Kervate, включите предупреждения компилятора (-Wall для gcc) и прислушайтесь к ним. Они полезны; почему бы не принять всю помощь, которую вы можете получить?

Как указано WhozCraig и n.m. в комментариях к исходному вопросу, getdelim() man page показывает правильное использование.

Если вы хотите читать записи с разделителями характером NUL, вы могли бы использовать

FILE *input; /* Or, say, stdin */ 
char *buffer = NULL; 
size_t size = 0; 
ssize_t length; 

while (1) { 
    length = getdelim(&buffer, &size, '\0', input); 
    if (length == (ssize_t)-1) 
     break; 

    /* buffer has length chars, including the trailing '\0' */ 
} 

free(buffer); 
buffer = NULL; 
size = 0; 

if (ferror(input) || !feof(input)) { 
    /* Error reading input, or some other reason 
    * that caused an early break out of the loop. */ 
} 

Если вы хотите прочитать содержимое файла в единый массив символов, то getdelim() неправильная функция.

Вместо этого используйте realloc() для динамического выделения и роста буфера, добавляя к нему с помощью fread(). Чтобы вы начали - это еще не все! - рассмотрим следующий код:

FILE *input; /* Handle to the file to read, assumed already open */ 
char *buffer = NULL; 
size_t size = 0; 
size_t used = 0; 
size_t more; 

while (1) { 

    /* Grow buffer when less than 500 bytes of space. */ 
    if (used + 500 >= size) { 
     size_t new_size = used + 30000; /* Allocate 30000 bytes more. */ 
     char *new_buffer; 

     new_buffer = realloc(buffer, new_size); 
     if (!new_buffer) { 
      free(buffer); /* Old buffer still exists; release it. */ 
      buffer = NULL; 
      size = 0; 
      used = 0; 
      fprintf(stderr, "Not enough memory to read file.\n"); 
      exit(EXIT_FAILURE); 
     } 

     buffer = new_buffer; 
     size = new_size; 
    } 

    /* Try reading more data, as much as fits in buffer. */ 
    more = fread(buffer + used, 1, size - used, input); 
    if (more == 0) 
     break; /* Could be end of file, could be error */ 

    used += more; 
} 

Обратите внимание, что buffer в этом последнем фрагменте не является строкой. Не существует завершающего символа NUL, поэтому это всего лишь массив символов. Фактически, если файл содержит двоичные данные, массив может содержать много NUL (\0, нулевые байты). Предполагая, что ошибки не было, и весь файл был прочитан (вам нужно проверить это, см. Предыдущий пример), buffer содержит used chars, читаемый из файла, с достаточным пространством, выделенным для size. Если used > 0, то size > used. Если used == 0, то size может быть или не быть равным нулю.

Если вы хотите повернуть buffer в строку, вам нужно решить, что делать с возможными встроенными байтами \0. Я рекомендую либо преобразовать, например, пробелов или вкладок или переместить данные, чтобы пропустить их вообще, - и добавьте завершающий строку \0 в конец, чтобы сделать его допустимой строкой.

+0

Это сработало, спасибо вам большое! Моя проблема с моей переменной size_t заключалась в том, что я определил ее как size_t * len, а не size_t len ​​... Интересно, однако, что я компилировал с -Wall и не приводил никаких ошибок или предупреждений только для использования литерала 0. Следовательно почему я был так смущен. – Arcana