Помогите с пользовательской функцией getline()
Может кто-нибудь объяснить мне, почему это не работает?
#include <stdio.h>
#include <stdlib.h>
char *getline(int lim)
{
char c;
int i;
char *line;
line = malloc(sizeof(char) * lim);
i = 0;
while((c = getchar()) != '\n' && c != EOF && i < lim-1)
{
*line = c;
line++;
i++;
}
*line = '\0';
printf("%s", line);
return line;
}
Я не беспокоюсь о возвращаемом значении прямо сейчас - только причина того, почему printf("%s", line)
не работает
Спасибо!
РЕДАКТИРОВАТЬ: исправлено line = malloc(sizeof(char) * lim);
но это все еще не работает.
Решение: адрес *line
увеличивается на протяжении всей функции. Когда он был передан printf()
, *line
указал на '\0', потому что там его адрес был увеличен. Использование временного указателя, в котором сохранен исходный адрес, выделенный malloc()
в *line
а затем передать этот указатель в printf()
, разрешено для функции ходить по указателю.
8 ответов
Потому что вы выделяете достаточно места только для одного символа в этой строке:
line = malloc(sizeof(char));
И это наполняется \0
до вашего printf
заявление.
Я предполагаю, что вы хотите изменить эту строку на:
/* Allocate enough room for 'lim' - 1 characters and a trailing \0 */
line = malloc(sizeof(char) * lim);
Или даже лучше:
char *line, *tmp;
tmp = line = malloc(sizeof(char) * lim);
А потом использовать tmp
во всей вашей математике указатель, таким образом line
все равно будет указывать на начало вашей строки.
И я знаю, что это в начале вашего развития, но вы хотите убедиться, что вы free()
память, которую вы malloc()
,
Вот рабочая версия вашей функции, включая мои предлагаемые изменения:
#include <stdio.h>
#include <stdlib.h>
char *getline(int lim)
{
char c;
int i;
char *line, *tmp;
tmp = line = malloc(sizeof(char) * lim);
i = 0;
/* NOTE: 'i' is completely redundant as you can use 'tmp',
* 'line,' and 'lim' to determine if you are going to
* overflow your buffer */
while((c = getchar()) != '\n' && c != EOF && i < lim-1)
{
*tmp = c;
tmp++;
i++;
}
*tmp = '\0';
printf("%s", line);
return line;
}
Похоже, вы печатаете строку нулевой длины.
*line = '\0';
printf("%s", line);
Я предполагаю, что вы хотите хранить то, что line
был изначально (как вернулся из malloc
) и распечатайте это.
Все уже рассмотрели эти вопросы, но вот все это вместе:
Изменить: немного улучшил код
#include <stdio.h>
#include <stdlib.h>
char *getline(int lim)
{
char *result = malloc(sizeof(char) * lim); // allocate result buffer
int i = 0;
char c;
char *line = result;
while((c = getchar()) != '\n' && c != EOF && i < lim-1)
{
*line = c;
line++;
i++;
}
*line = '\0';
printf("%s", result); // print the result
return result; // return the result buffer (remember to free() it later)
}
Обновлено - это была простая ошибка опечатки, но вы не должны были голосовать за меня
вместо
char *line= malloc(sizeof(char));
пытаться
int space= //number of how many characters you need on the line
char *line= malloc(sizeof(char)*space);
извини я имел ввиду
char *line= malloc( sizeof(char)*lim)
Вы, кажется, выделили достаточно места только для одного персонажа. Вместо этого вы имели в виду следующее:
line = malloc(lim * sizeof(char));
Кроме того, вы не хотите менять line
после прочтения каждого символа. Вместо этого используйте следующий блок для цикла while:
*(line + i) = c;
i++;
И, наконец, чтобы завершить строку нулем, используйте:
*(line + i) = '\0';
Вы делаете ошибку по двум пунктам (но вы можете сказать ту же ошибку или две, это до вас). Сначала ваш указатель должен быть увеличен как
*(строка +i) = с; По этой причине, когда вы устанавливаете нулевой символ в конце цикла, вы на самом деле говорите компилятору, чтобы он указывал только на эту позицию. Но указатель указывает только на пустую строку, а не на всю строку. Так как он постоянно перемещался на каждом этапе цикла. Поэтому, когда вы пытались напечатать, указателю нечего печатать. Таким образом, если вы измените свой оператор внутри цикла для указателя и назначите значение для экспресс-адреса, а не просто передвинете указатель, тогда ваша проблема будет решена.
Заметка. Если вы измените эту строку, то вам также нужно изменить свое нулевое терминаторное назначение следующим образом; *(строка + предел) = '\0';
Вы также перезаписываете память, которой не владеете. Вы неправильно используете один символ, устанавливаете *line на c, а затем увеличиваете строку и повторяете.
Вы должны понимать концепцию указателя и то, как он отличается от буфера. В вашем коде вы рассматриваете "строку" как указатель и буфер одновременно.