Я пытаюсь решить проблему, и в процессе я ввожу строки с помощью getline следующим образом (часть моей основной функции)
size_t n1=0,n2=0;
char *a=0, *b=0;
getline(&a,&n1,stdin);
getline(&b,&n2,stdin);
но независимо от того, какой ввод я даю, значение n1 и n2 всегда сохраняется как 120 . Как я могу решить эту проблему, чтобы сохранить точный размер строки, которую я ввожу
чтение документация — хорошее начало.
@G.M. спасибо, что указали, что я действительно пропустил запись здесь, но в моем исходном коде *lineptr инициализируется значением null, но все же размер n1 и n2 равен 120
В: Если вам нужен "точный размер строки, которую я ввожу"... тогда почему бы просто не прочитать возвращаемое значение getline()???
@ paulsm4, насколько меня учили, n1 должен хранить точное количество строк, которые я даю в качестве входных данных, но независимо от того, какую строку я даю, я получаю те же 120, что и размер строк
Вы не можете изменить значение по умолчанию, которое выделяет getline()
. Если вам нужен буфер точного размера, используйте strdup()
на входе. Или заранее выделить меньший размер, и сказать getline()
какой это: size_t n1 = 32; char *a0 = malloc(n1);
. Но getline()
выбирает разумное значение по умолчанию, которое обычно позволяет избежать перераспределения при чтении входных данных — длина большинства строк не превышает 120 (или 128, или 256, или любое другое значение по умолчанию, которое использует getline()
).
@JonathanLeffler спасибо, у меня есть сомнения, что я использовал эту нотацию несколько раз раньше, но у меня никогда не было такой ошибки, раньше она сохраняла точную длину строки, которую я ввел в качестве входных данных, но почему сейчас это не удается
Это не ошибка; это ожидаемое поведение getline()
. Возможно, вы использовали другую реализацию getline()
? Возможно, вы читали строки, постоянно превышающие минимальный размер буфера. Вы должны создать MCVE, воспроизводящее старое поведение, и объяснить, чем отличается ваш текущий код. Спецификация для getline()
гарантирует, что для хранения текущих данных достаточно места, что означает, что может быть выделено больше места, чем минимально необходимое. Это уменьшает количество перераспределений памяти.
@JonathanLeffler Я думаю, что не могу прикрепить скриншот, но когда размер строки огромен, все равно его выделяемый размер составляет 120
Скриншоты имеют ограниченную ценность. Если вам это нужно, найдите мой адрес электронной почты в моем профиле и отправьте мне информацию. Включите URL-адрес вопроса. И включите необходимую информацию в виде обычного текста, если это вообще возможно — скопируйте и вставьте вывод, а не снимок экрана. Включите код, конечно.
В: «Насколько меня учили, n1 должен хранить точное количество строк, которые я даю в качестве входных данных». О: Как вы, надеюсь, теперь понимаете, это НЕПРАВИЛЬНО. «n» — это размер вашего буфера (или индикатор того, что система должна использовать функцию malloc() для буфера), НЕТ «размер строки». Вот для чего нужно возвращаемое значение.
How can I overcome this problem to store the exact size of string I input
Во-первых, вы должны перестать относиться к этому как к проблеме и относиться к этому как к нормальному поведению getline
. Вы должны адаптироваться к getline
, а не ожидать, что он приспособится к вам.
getline
выделяет разумное количество места для работы. Выделение меньшего объема пространства может потребовать getline
более частого перераспределения пространства, поскольку постоянный ввод требует все больших и больших выделений. Это приведет к пустой трате ресурсов, включая энергию и время.
n1
или n2
, переданные getline
посредством второго параметра, устанавливаются на размер выделенного пространства, а не на длину прочитанного ввода, и вы не можете изменить это, если не считать изменения реализации getline
. getline
не помещает длину ввода в n1
или n2
.
Чтобы получить длину прочитанного ввода, сохраните возвращаемое значение getline
:
size_t l1 = getline(&a, &n1, stdin);
size_t l2 = getline(&b, &n2, stdin);
Если выделенное пространство вызывает серьезную озабоченность, используйте realloc
, чтобы сообщить программе управления памятью, что избыточное пространство не требуется:
char *temp = realloc(a, n1 = l1+1);
if (!temp) a = temp;
temp = realloc(b, n2 = l2+1);
if (!temp) b = temp;
Некоторые реализации realloc
, скорее всего, будут игнорировать попытки уменьшить выделенное пространство, особенно когда выделенный размер невелик.
использование возвращаемого значения строки get сработало, спасибо. Но у меня никогда не возникало таких ошибок, даже если я использую те же обозначения, почему сейчас?
@user Вы можете назвать это ошибкой, но это не так. Если вы проверите неправильные переменные, вы можете получить неожиданные результаты. Ожидание конкретного результата для n1
не подтверждается спецификацией. Единственное, чего можно ожидать, это «достаточно большой». Любая реализация может решить вести себя по-другому, а также изменяться между версиями.
От документация
If *lineptr is not null, the behavior is undefined if *lineptr is not a pointer that can be passed to free or if *n is less than the size of the allocated memory pointed to by *lineptr
.lineptr
в вашем случае будетa
илиb
. Вам нужно их инициализировать, иначе у вас будет неопределенное поведение.