Как разрешить ввод пробелов с помощью scanf? - PullRequest
117 голосов
/ 08 августа 2009

Используя следующий код:

char *name = malloc(sizeof(char) + 256); 

printf("What is your name? ");
scanf("%s", name);

printf("Hello %s. Nice to meet you.\n", name);

Пользователь может ввести свое имя, но когда он вводит имя с пробелом, например Lucas Aardvark, scanf() просто обрезает все после Lucas. Как мне сделать scanf() разрешить пробелы

Ответы [ 11 ]

166 голосов
/ 08 августа 2009

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

Помните, что scanf означает «отформатированный отсканированный», и очень мало меньше отформатировано, чем введенные пользователем данные. Идеально, если у вас есть полный контроль над форматом входных данных, но, как правило, он не подходит для ввода пользователем.

Используйте fgets() (который имеет защиту от переполнения буфера), чтобы получить ваш ввод в строку и sscanf(), чтобы оценить ее. Поскольку вы просто хотите, чтобы пользователь ввел данные без разбора, в любом случае вам не нужен sscanf():

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Maximum name size + 1. */

#define MAX_NAME_SZ 256

int main(int argC, char *argV[]) {
    /* Allocate memory and check if okay. */

    char *name = malloc(MAX_NAME_SZ);
    if (name == NULL) {
        printf("No memory\n");
        return 1;
    }

    /* Ask user for name. */

    printf("What is your name? ");

    /* Get the name, with size limit. */

    fgets(name, MAX_NAME_SZ, stdin);

    /* Remove trailing newline, if there. */

    if ((strlen(name) > 0) && (name[strlen (name) - 1] == '\n'))
        name[strlen (name) - 1] = '\0';

    /* Say hello. */

    printf("Hello %s. Nice to meet you.\n", name);

    /* Free memory and exit. */

    free (name);
    return 0;
}
114 голосов
/ 08 августа 2009

Попробуйте

char str[11];
scanf("%10[0-9a-zA-Z ]", str);

Надеюсь, это поможет.

44 голосов
/ 09 августа 2009

В этом примере используется инвертированный набор сканирования, поэтому scanf продолжает принимать значения до тех пор, пока не встретит '\ n' - новую строку, поэтому пробелы также сохраняются

#include <stdio.h>

int main (int argc, char const *argv[])
{
    char name[20];
    scanf("%[^\n]s",name);
    printf("%s\n", name);
    return 0;
}
21 голосов
/ 22 августа 2013

Вы можете использовать это

char name[20];
scanf("%20[^\n]", name);

или это

void getText(char *message, char *variable, int size){
    printf("\n %s: ", message);
    fgets(variable, sizeof(char) * size, stdin);
    sscanf(variable, "%[^\n]", variable);
}

char name[20];
getText("Your name", name, 20);

DEMO

8 голосов
/ 08 августа 2009

Не используйте scanf() для чтения строк без указания ширины поля. Вам также следует проверить возвращаемые значения на наличие ошибок:

#include <stdio.h>

#define NAME_MAX    80
#define NAME_MAX_S "80"

int main(void)
{
    static char name[NAME_MAX + 1]; // + 1 because of null
    if(scanf("%" NAME_MAX_S "[^\n]", name) != 1)
    {
        fputs("io error or premature end of line\n", stderr);
        return 1;
    }

    printf("Hello %s. Nice to meet you.\n", name);
}

В качестве альтернативы используйте fgets():

#include <stdio.h>

#define NAME_MAX 80

int main(void)
{
    static char name[NAME_MAX + 2]; // + 2 because of newline and null
    if(!fgets(name, sizeof(name), stdin))
    {
        fputs("io error\n", stderr);
        return 1;
    }

    // don't print newline
    printf("Hello %.*s. Nice to meet you.\n", strlen(name) - 1, name);
}
6 голосов
/ 17 сентября 2012

Вы можете использовать функцию fgets() для чтения строки или использовать scanf("%[^\n]s",name);, чтобы чтение строки прекратилось при обнаружении символа новой строки.

4 голосов
/ 08 августа 2009

getline()

Теперь часть POSIX, тем не менее.

Он также решает проблему выделения буфера, о которой вы спрашивали ранее, хотя вы должны позаботиться о free использовании памяти.

3 голосов
/ 06 ноября 2017

Если кто-то все еще ищет, вот что сработало для меня - прочитать произвольную длину строки, включая пробелы.

Спасибо многим постерам в сети за то, что поделились этим простым и элегантным решением. Если это работает, кредит идет к ним, но любые ошибки - мои.

char *name;
scanf ("%m[^\n]s",&name);
printf ("%s\n",name);
1 голос
/ 18 января 2015

Вы можете использовать scanf для этой цели с небольшим фокусом. На самом деле, вы должны разрешить ввод данных пользователем, пока пользователь не нажмет Enter (\n). Это будет учитывать каждый символ, включая пробел . Вот пример:

int main()
{
  char string[100], c;
  int i;
  printf("Enter the string: ");
  scanf("%s", string);
  i = strlen(string);      // length of user input till first space
  do
  {
    scanf("%c", &c);
    string[i++] = c;       // reading characters after first space (including it)
  } while (c != '\n');     // until user hits Enter
  string[i - 1] = 0;       // string terminating
return 0;
}

Как это работает? Когда пользователь вводит символы из стандартного ввода, они будут сохраняться в переменной string до первого пробела. После этого оставшаяся часть записи останется во входном потоке и будет ждать следующего сканирования. Затем у нас есть цикл for, который берет символ за символом из входного потока (до \n) и добавляет их к концу переменной string , формируя, таким образом, полную строку, аналогичную пользовательскому вводу с клавиатуры.

Надеюсь, это кому-нибудь поможет!

0 голосов
/ 15 мая 2019
/*reading string which contains spaces*/
#include<stdio.h>
int main()
{
   char *c,*p;
   scanf("%[^\n]s",c);
   p=c;                /*since after reading then pointer points to another 
                       location iam using a second pointer to store the base 
                       address*/ 
   printf("%s",p);
   return 0;
 }
...