Как читать ввод неизвестной длины с помощью fgets
Как я должен читать длинный ввод с помощью fgets()
, Я не совсем понял.
Я написал
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char buffer[10];
char *input;
while (fgets(buffer,10,stdin)){
input = malloc(strlen(buffer)*sizeof(char));
strcpy(input,buffer);
}
printf("%s [%d]",input, (int)strlen(input));
free(input);
return 0;
}
2 ответов
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char buffer[10];
char *input = 0;
size_t cur_len = 0;
while (fgets(buffer, sizeof(buffer), stdin) != 0)
{
size_t buf_len = strlen(buffer);
char *extra = realloc(input, buf_len + cur_len + 1);
if (extra == 0)
break;
input = extra;
strcpy(input + cur_len, buffer);
cur_len += buf_len;
}
printf("%s [%d]", input, (int)strlen(input));
free(input);
return 0;
}
речь идет о минимальном наборе изменений,которые дадут вам полную строку ввода. Это увеличивает пространство до 9 байт за раз; это не лучший способ сделать это, но есть дополнительная бухгалтерия, которая делает это лучшими способами (удвоение выделенного пространства и ведение записи о том, сколько выделено против того, сколько используется). Обратите внимание, что cur_len
запишите длину строки в пространстве, на которое указывает input
исключая терминал null. Также обратите внимание, что использование из extra
во избежание утечка памяти на отказе выделить.
на strcpy()
операция может быть законно заменить на memmove(input + cur_len, buffer, buf_len + 1)
(и в этом контексте, вы могли бы использовать memcpy()
вместо memmove()
, но это не всегда работает, а memmove()
всегда работает, поэтому более надежно использовать memmove()
).
С длина-удвоение - в cur_max
переменная записывает, сколько места выделено, и cur_len
записывает, сколько места используется.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char buffer[10];
char *input = 0;
size_t cur_len = 0;
size_t cur_max = 0;
while (fgets(buffer, sizeof(buffer), stdin) != 0)
{
size_t buf_len = strlen(buffer);
if (cur_len + buf_len + 1 > cur_max)
{
size_t new_len = cur_max * 2 + 1;
if (buf_len + 1 > new_len)
new_len = buf_len + 1;
char *extra = realloc(input, new_len);
if (extra == 0)
break;
input = extra;
cur_max = new_len;
}
strcpy(input + cur_len, buffer);
cur_len += buf_len;
}
printf("%s [%d]", input, (int)strlen(input));
free(input);
return 0;
}
лучший подход-использовать механизм ввода, который будет выделять для вас, такие как getline
(или даже scanf
). (Примечание: scanf
не выделяет во всех компиляторах. В gcc/Linux
, но не Windows/Codeblocks/gcc
)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *input;
scanf ("%m[^\n]%*c", &input);
printf("\n %s [%d]\n\n",input, (int)strlen(input));
free(input);
return 0;
}
выход:
$ ./bin/scanfinput
This is my longer string.
This is my longer string. [25]
пример getline
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *input = NULL; /* input buffer, NULL forces getline to allocate */
size_t n = 0; /* maximum characters to read (0 - no limit */
ssize_t nchr = 0; /* number of characters actually read */
if ((nchr = getline (&input, &n, stdin)) != -1)
input[--nchr] = 0; /* strip newline */
printf ("\n %s [%zd]\n\n", input, nchr);
free(input);
return 0;
}