Почему функция не видит символ «NULL»

#c

#c

Вопрос:

Я пытаюсь создать программу, которая будет выделять память для чтения нового символа до тех пор, пока не будет прочитан символ null, но, похоже, это не работает

Printf в строке, которая прокомментирована (после условия цикла while), показывает мне, на какое значение указывает c i, я только что проверил, и даже если он показывает мне символ NULL (он просто печатает ‘- —‘, я предполагаю, что это символ NULL?), цикл продолжается.

 char *read(char *c) {

    int i=0;

    c=(char*)malloc(1);
    scanf("%c", c i); 

    while (*(c i)) {
        //printf("-- %c --", *(c i));

        i  ;
        c=(char*)realloc(c,i 1);
        scanf("%c", c i);
    }

    return c;
}
  

Комментарии:

1. Что вы подразумеваете под нулевым символом ?

2. » Я предполагаю, что это символ NULL? «. Почему вы предполагаете и угадываете вслепую? Вы можете просто распечатать порядковое значение символа, используя спецификатор формата %d вместо %c. Тогда вы увидите , какой символ у вас там есть, независимо от того, доступен ли сам символ для печати или нет…

3. Почему вы игнорируете возвращаемое значение scanf() ? Как вы можете определить, когда произошла ошибка или была предпринята попытка чтения после окончания ввода, если вы этого не делаете?

4. Кроме того, getchar() и друзья — лучший выбор, если вы читаете символ за раз. scanf() для этого слишком много.

5. Еще один момент, о котором больше никто не упоминает. malloc() без free в той же функции не является хорошим шаблоном, поэтому делайте это только тогда, когда это необходимо. Это приводит к утечкам памяти. Существуют лучшие шаблоны для достижения такого же поведения, однако за счет циклов. Например, вызывающий вызывает функцию, чтобы узнать, сколько выделить. Вызывающий выделяет буфер и выполняет обратный вызов с выделенным буфером. Тогда существует ЧЕТКИЙ КОНТРАКТ о том, кто будет освобождать память.

Ответ №1:

Ваша реализация не останавливается, потому что она никогда не считывает NULL символ. Когда вы нажимаете клавишу типа RETURN / ENTER, консоль генерирует последовательность перевода строки (которая является « n » в некоторых операционных системах, таких как Linux, или « rn » в некоторых других, таких как Windows).

С учетом сказанного, вы могли бы затем изменить свое while условие, чтобы проверить, является ли прочитанный символ 'n' или 'r' завершить чтение, вместо того, чтобы проверять, был ли он NULL . Однако это решение остановило бы чтение, как только пользователь нажмет клавишу возврата.

Комментарии:

1. Вау, это сработало, о, мой глобус, большое спасибо, эта штука доставила мне головную боль. Я предположил, что нулевой символ добавляется автоматически при нажатии enter, но если он сгенерировал только новую строку, вы знаете, как добавить нулевой символ в конце строки? Или вы не можете сделать это в консоли?

2. Это определенно можно сделать: вам просто нужно realloc() снова добавить один новый символ в вашу строку и присвоить этому символу значение NULL , делая это сразу после вашего while (...) {...} цикла.

3. Я имел в виду, можете ли вы добавить нулевой символ из консоли после того, как вы ввели то, что хотели прочитать, но если новая строка генерируется автоматически, я думаю, это было бы довольно бессмысленно, поскольку вы можете просто добавить его после завершения цикла while, как вы сказали.

4. Насколько я понимаю, NULL никогда не генерируется при операции чтения с использованием scanf() спецификатора со %c для чтения со стандартного устройства ввода («клавиатуры»). Это потому, что %c спецификатор считывает символ и NULL работает не как символ, а как своего рода «заполнитель» для представления «нет символа». Резюме: %c никогда не преобразует ни один пользовательский ввод (с клавиатуры) в null.

5. Для длинного ответа о том, что считается новой строкой, en.wikipedia.org/wiki/Newline . Кроме того, нужно уметь корректно обрабатывать EOF перед новой строкой.