Есть несколько способов подойти к этой проблеме. Как показывают другие, если вы знаете, что ваш ввод не будет превышать определенный размер, вы можете объявить static buffer
достаточным для хранения ваших данных. Однако, если вы обнаружите, что в ситуации, когда вы не знаете, сколько данных вам нужно читать, вы можете перейти на dynamically allocating
свой буфер, который даст вам возможность расти (или realloc
) размер вашего буфера по мере необходимости. Ниже приводится такой подход. (вы можете перенаправить текстовый файл к нему в качестве теста).
Кроме того, было неясно, если вы хотите пропустить все пустые строки или если вы просто не хотите видеть ввод до EOF
. Во всяком случае, если вы хотите пропустить пустые строки, вы можете добавить простой тест внутри цикла чтения после назначения p = line;
.
/* skip blank lines */
if (*p == '\n' || *p == '\r')
continue;
В этом примере используется getline
вместо fgets
, который обеспечивает 2 преимущества для вас. (1)getline
выделит вам буфер строки, если вы инициализируете его до NULL
; и (2) возвращает фактическое количество прочитанных символов, исключая необходимость вызова strlen
. Дайте мне знать, если у вас есть вопросы:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *realloc_void_on (void *p, size_t o, size_t n, size_t psz);
int main (void) {
char *line = NULL; /* pointer to use with getline() */
char *p = NULL; /* pointer to parse getline return */
ssize_t nchr = 0; /* actual chars read per-line */
size_t n = 0; /* max chars to read (0 - no limit) */
char *buff = NULL; /* buffer to hold all lines read */
char *ep = NULL; /* end pointer for buff */
size_t cbuffsz = 0; /* current buffer size */
size_t nbuffsz = 0; /* new buffer size */
size_t offset = 0; /* offset to orient end pointer */
/* read each line from stdin */
while ((nchr = getline (&line, &n, stdin)) != -1)
{
p = line; /* assign line address to pointer */
/* set required new buff size, realloc, set end ptr, update cbuffsz */
nbuffsz += nchr + 1;
buff = realloc_void_on (buff, cbuffsz, nbuffsz, sizeof *buff);
ep = buff + offset;
cbuffsz = nbuffsz;
while (*p) { /* for each character in line */
*ep++ = *p; /* add char to buff, increment ep */
offset++; /* increment offset */
if (*p == '\t' || *p == ' ') { /* if space, or tab */
while (*p == '\t' || *p == ' ') /* read/discard following spaces */
p++;
}
else
p++; /* if not space, increment pointer */
}
}
/* output complete buffer */
#ifdef DEBUG
printf ("\nBuffer:\n-----\n%s-----\n\n", buff);
#else
printf ("%s\n", buff);
#endif
/* free allocated memory */
if (line) free (line);
if (buff) free (buff);
return 0;
}
/* reallocate memory for p of type size psz, from o to n.
* accepts any pointer p, with current allocation o,
* with the type size psz and reallocates memory to
* n, intializing the new memory to zero and returning
* a pointer to the newly allocated block of memory on
* success, exit otherwise.
*/
void *realloc_void_on (void *p, size_t o, size_t n, size_t psz)
{
void *tmp = realloc (p, n * psz);
#ifdef DEBUG
printf ("\n reallocating %zu to %zu\n", o, n);
#endif
if (!tmp) {
fprintf (stderr, "Error: pointer reallocation failure.\n");
exit (EXIT_FAILURE);
}
p = tmp;
memset (p + o, 0, (n - o) * psz); /* memset new ptrs 0 */
return p;
}
Сложение/компилирования
Without перераспределить отладочная информация:
gcc -Wall -Wextra -o buildbuf buildbuf.c
С перераспределить отладочная информация (в том числе gdb
отладочной информации):
gcc -Wall -Wextra -g -DDEBUG -o buildbuf buildbuf.c
Input
I am running.
Выход
I am running.
Логика у вас есть вид грязный, и я не имею в виду, что, как оскорбление. Когда вы учитесь, легко попасть в выражения 'while', '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' Возможно, подумайте о том, как вы могли бы реорганизовать свой цикл, когда получите персонажа и проверите его, пока не достигнете 'EOF'. – DigitalNinja
Пожалуйста, покажите мне, как. – runners3431
Я думаю, что ваша улучшенная версия лучше. Это более читаемо и использует меньше кода. – DigitalNinja