Вы используете неопределенную константу SIZE вместо аргумента s
для своей функции, чтобы контролировать максимальную длину ваших строк. Так как s
является целым числом со знаком, вы должны проверить его на здравомыслие (это должно быть положительное (ненулевое) число, возможно, не больше, чем 1 МБ; возможно, вы хотите установить больший нижний предел, чем 1; возможно, вы по умолчанию 80, если звонящий облажается, или, возможно, вы вернетесь с ошибкой).
Вы используете char c;
для сохранения значения, считанного с fgetc()
; к сожалению, это означает, что ваш тест EOF ненадежен. Либо вы преждевременно остановитесь, когда кто-то поставит 'ÿ' (y-umlaut, hex 0xFF в ISO 8859-1, 8859-15, либо U + 00FF в ISO 10646 - Unicode), либо вы вообще не остановитесь, в зависимости от является ли тип char
подписанным или неподписанным. Всегда помните: getchar()
и родственники возвращают int
!
Переменная l
вызывает путаницу с константой 1
; как правило, избегайте этого.
Ваше условие основного цикла было бы лучше, если бы вы проверили результат fgetc()
напрямую.
int c;
while ((c = fgetc(fp)) != EOF && c != '\n')
{
...
}
На самом деле, вы читаете часть текста в цикле и не проверяете его должным образом. Затем вы можете использовать ungetc()
, чтобы вставить сначала прочитанный символ обратно во входной поток; это делает обработку ввода более равномерной. В качестве альтернативы вы можете настроить все так, чтобы все работало правильно, если первый вызов fgetc()
находится в элементе управления цикла и возвращает EOF.
Как указал Томми , вы должны захватить вывод realloc()
; нет никакой гарантии, что он вернет свой входной указатель в качестве результата. Вам также следует узнать, что вы не сохраняете результат realloc()
в переменную, указанную в качестве первого аргумента. Вы сразу же теряете память, если это происходит, и перераспределение не удается (потому что вы потеряли указатель на старую память - она просто обнуляется). Итак, чтобы быть в безопасности, вы используете:
char **new_array = realloc(l, (lcounter+1) * sizeof(*new_array));
if (new_array == 0)
...handle out of memory...
else
l = new_array;
Пара моментов здесь. Вы выделили (lcounter+2)
значения, но я думаю, что вы когда-либо используете только одно из них (если только нет конечного нулевого указателя, чтобы отметить конец массива). Вы указали sizeof(char **)
, но на самом деле вы хотите массив char *
значений. К счастью, все (объектные) указатели имеют одинаковый размер - стандарт C гарантирует это; только POSIX гарантирует, что указатели на функции имеют тот же размер, что и указатели на объекты (стандарт С не делает этого). Итак, sizeof(char **) == sizeof(char *)
и вы в безопасности, но вы не спрашиваете о том, что хотели.
Следствием дискуссии о realloc()
, возможно, неуспешном является malloc()
, тоже может не получиться. Вы должны по ошибке проверить выделение памяти - или использовать набор функций обложки для стандартной библиотеки, которые возвращаются, только если возвращаемый указатель не равен нулю. Если вы не проверите его, ваша программа в конечном итоге завершится сбоем из-за сбоя выделения памяти - даже на машине с 24 ГБ основной памяти (хотя для этого может потребоваться некоторое время).
В коде много повторений. Вы должны смотреть, чтобы избежать этого. Это означает использование подфункции, возможно, для управления распределением памяти.
Если вы исправите это, у вас будет шанс получить работающую функцию. Вам также следует написать код для освобождения выделенной памяти, которую вы возвращаете, чтобы пользователям не приходилось придумывать способ сделать это от вашего имени. Всегда волнуйтесь о том, кто собирается освободить выделенную память и как она будет освобождена.
Это в основном говорит, что все типы указателей объектов могут быть преобразованы в пустые указатели и обратно без потери информации, что означает, что все они должны быть одинакового размера. Обратите внимание, что категория «указатели объектов» не включает «указатели функций».