Как использовать scanf, чтобы принять значение по умолчанию, просто нажав клавишу Enter? - PullRequest
4 голосов
/ 22 февраля 2010

Мне было интересно, может ли кто-нибудь помочь мне с этим:

printf("Enter path for mount drive (/mnt/Projects) \n");
scanf("%s", &cMountDrivePath);  

Можно ли позволить пользователю просто нажать Enter и принять значение по умолчанию (в данном случае: / mnt / Projects )? В настоящее время, если пользователь нажимает Enter, курсор просто переходит на следующую строку, и ввод по-прежнему требуется.

У меня складывается впечатление scanf не позволяет этого, и в каком случае что мне использовать?

Спасибо!

Ответы [ 7 ]

4 голосов
/ 22 февраля 2010

Нет, scanf() не может быть настроен на прием значения по умолчанию. Чтобы сделать вещи еще веселее, scanf() не может принять пустую строку в качестве допустимого ввода; спецификатор преобразования "% s" указывает scanf() игнорировать начальные пробелы, поэтому он не вернется, пока вы не наберете что-то, что не является пробелом, и затем не нажмете Enter или Return.

Чтобы принять пустой ввод, вам нужно использовать что-то вроде fgets(). Пример:

char *defaultPath = "/mnt/Projects";
...
printf("Enter path for mount drive (%s): ", defaultPath);
fflush(stdout);

/**
 * The following assumes that cMountDrivePath is an
 * array of char in the current scope (i.e., declared as
 * char cMountDrivePath[SIZE], not char *cMountDrivePath)
 */
if (fgets(cMountDrivePath, sizeof cMountDrivePath, stdin) != NULL)
{
  /**
   * Find the newline and, if present, zero it out
   */
  char *newline = strchr(cMountDrivePath, '\n');
  if (newline)
    *newline = 0;

  if (strlen(cMountDrivePath) == 0) // input was empty
  {
    strcpy(cMountDrivePath, defaultPath)
  }
}

РЕДАКТИРОВАТЬ

Изменено default на defaultPath; забыл, что default является зарезервированным словом. Плохо Код обезьяны, без бананов!

4 голосов
/ 22 февраля 2010

Я думаю, fgets() дает вам немного больше возможностей для ввода, особенно пустых строк.

1 голос
/ 22 февраля 2010

Или, если вы решили использовать scanf, используйте строку формата, ограничивающую число символов, которые будут сканироваться (для предотвращения ошибок переполнения буфера).

Например, если ваш буфер 128 байтов (включая терминатор nul):

scanf("%127s", &cMountDrivePath);
1 голос
/ 22 февраля 2010

scanf - это зло, потому что он не проверяет границы!

Пожалуйста, используйте getline из библиотеки GNU C .

Если ваш компилятор поддерживает C ++, просто используйте istream :: getline

0 голосов
/ 23 ноября 2018

возможно, вы можете использовать это:

void defaultScanf (char *value, char defaultValue)
{
    char trash;

    *value = getchar(); 
    /* set your default valut */
    if (*value == '\n') {
        *value = defaultValue;
    } else {
        *value -= '0'; /* transform char to int */

        /* clean your buffer */
        do trash = getchar();
        while (trash != '\n' && trash != EOF);
    }
}
0 голосов
/ 03 ноября 2014

Со страницы руководства для scanf:

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Эти функции возвращают количество элементов ввода, которые были успешно сопоставлены и назначенный, который может быть меньше, чем предусмотрено, или даже ноль в событие раннего неудачного сопоставления.

Вы можете использовать эту информацию для проверки отсутствия ввода данных пользователем (просто новая строка \n):

printf("Enter path for mount drive (/mnt/Projects) \n");
if (scanf("%80[^\n]s", &cMountDrivePath) < 1) {
    /* assign default value */ ;
}
0 голосов
/ 22 февраля 2010

Нет, scanf () не может быть принят для "значений по умолчанию". Вы должны получить входные данные, проверить их на пустоту и самостоятельно назначить значение по умолчанию.

Как вы узнали, scanf () сложен; Я согласен с extraneon, что fgets (), вероятно, то, что вы ищете.

Edit:

Причина, по которой scanf () не реагирует ... scanf () возвращает после него a) обработал все спецификаторы преобразования или b) обнаружил ошибку. Как и во всех спецификаторах преобразования (в данном случае "% s"), начальные пробелы пропускаются. Кроме того, "% s" читает все символы до следующего пробела .

Нажатие возврата вставляет '\ n' в стандартный ввод. Поэтому, если вы нажмете клавишу возврата до того, как введете что-либо еще (за исключением, возможно, пары символов табуляции и пробелов), scanf () пропустит ваш ввод и продолжит ждать ввода без пробелов.

Что бы вы ни вводили, scanf () не будет "видеть" его, пока вы не нажмете return, потому что ваш ввод хранится в буфере консоли. (В противном случае вы не сможете вернуться назад через ввод.) Нажатие return снова вводит "\ n" во входной поток, поэтому ваш "% s" завершается, даже если вы не входили ни в какие вкладки / пробелы в строке, которую вы ввели.

Если вы сделали ввод пробелов, ваш cMountDrivePath будет содержать только первое «слово» вплоть до первого пробела, поэтому оставление пробелов в именах каталогов или файлов делает вещи чертовски раздражающими. Это также оставило бы оставшуюся часть строки во входном буфере, поэтому в следующий раз, когда вы вызываете scanf (), он не будет немедленно запрашивать ввод, а продолжит обрабатывать то, что было буферизовано во время предыдущего вызова - еще одна досадная деталь для scanf ( ) новички, которых нужно остерегаться.

Надеюсь, это немного прояснило для вас (и для других еще впереди).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...