Jak zezwolić na Wprowadzanie spacji za pomocą scanf?

Używając następującego kodu:

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

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

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

Użytkownik może wpisać swoją nazwę, ale po wpisaniu nazwy ze spacją jak Lucas Aardvark, scanf() po prostu odcina wszystko po Lucas. Jak zrobić scanf() Zezwalaj na spacje

Author: alk, 2009-08-08

11 answers

Ludzie (i szczególnie początkujący) nigdy nie powinni używać scanf("%s") lub gets() ani żadnych innych funkcji, które nie mają ochrony przed przepełnieniem bufora, chyba że wiesz na pewno, że dane wejściowe zawsze będą miały określony format (a może nawet wtedy).

Remember than scanf oznacza "skan sformatowany" i jest niewiele mniej sformatowanych niż dane wprowadzone przez użytkownika. Jest to idealne rozwiązanie, jeśli masz pełną kontrolę nad formatem danych wejściowych, ale ogólnie nieodpowiednie dla użytkownika wejście.

Użyj fgets() (który mA zabezpieczenie przed przepełnieniem bufora), aby pobrać dane wejściowe Do ciągu znaków i sscanf() aby je ocenić. Ponieważ chcesz tylko to, co użytkownik wprowadził bez parsowania, tak naprawdę nie potrzebujesz sscanf() w tym przypadku i tak:

#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;
}
 203
Author: paxdiablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-10 01:11:51

Try

char str[11];
scanf("%10[0-9a-zA-Z ]", str);
Mam nadzieję, że to pomoże.
 129
Author: Kelly Gendron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-12 01:56:56

Ten przykład używa odwróconego scansetu, więc scanf pobiera wartości, dopóki nie napotka' \n ' -- newline, więc spacje są również zapisywane

#include <stdio.h>

int main (int argc, char const *argv[])
{
    char name[20];
    scanf("%[^\n]s",name);
    printf("%s\n", name);
    return 0;
}
 54
Author: SVA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-09 14:31:26

Możesz użyć tego

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

Lub to

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

 23
Author: Vitim.us,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-21 02:53:03

Nie używaj scanf() do odczytu łańcuchów bez określania szerokości pola. Należy również sprawdzić zwracane wartości pod kątem błędów:

#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);
}

Alternatywnie, użyj 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);
}
 8
Author: Christoph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-08 16:04:16

Możesz użyć funkcji fgets() do odczytu łańcucha lub użyć scanf("%[^\n]s",name);, więc odczyt łańcucha zakończy się po napotkaniu znaku nowej linii.

 6
Author: Anshul garg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-17 12:31:12

getline()

Teraz jest częścią POSIX.

Zajmuje się również problemem alokacji buforów, o który pytałeś wcześniej, chociaż musisz zadbać o free w pamięci.

 5
Author: dmckee --- ex-moderator kitten,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-24 17:34:41

Jeśli ktoś nadal szuka, oto, co mi się udało-odczytać dowolną długość łańcucha ze spacjami.

Podziękowania dla wielu plakatów w sieci za udostępnienie tego prostego i eleganckiego rozwiązania. Jeśli to zadziała, zasługa idzie na nich, ale wszelkie błędy są moje.

char *name;
scanf ("%m[^\n]s",&name);
printf ("%s\n",name);
 3
Author: Always Learning,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-06 01:57:37

Możesz użyć scanf do tego celu za pomocą małej sztuczki. W rzeczywistości powinieneś zezwolić na wprowadzanie danych przez użytkownika, dopóki użytkownik nie naciśnie Enter (\n). Będzie to uwzględniało każdy znak, w tym spację . Oto przykład:

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;
}
Jak to działa? Gdy użytkownik wprowadzi znaki ze standardowego wejścia, będą one przechowywane w zmiennej string aż do pierwszego spacji. Następnie reszta wpisu pozostanie w strumieniu wejściowym i czeka na następny scanf. Następnie mamy pętlę for, która pobiera znak przez znak ze strumienia wejściowego (till \n) i apenduje je do końca zmiennej string , tworząc w ten sposób kompletny łańcuch taki sam jak wejście użytkownika z klawiatury.

Mam nadzieję, że to komuś pomoże!

 1
Author: akelec,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-18 11:06:05

Chociaż naprawdę nie powinieneś używać scanf() do tego typu rzeczy, ponieważ są o wiele lepsze połączenia, takie jak gets() lub getline(), można to zrobić:

#include <stdio.h>

char* scan_line(char* buffer, int buffer_size);

char* scan_line(char* buffer, int buffer_size) {
   char* p = buffer;
   int count = 0;
   do {
       char c;
       scanf("%c", &c); // scan a single character
       // break on end of line, string terminating NUL, or end of file
       if (c == '\r' || c == '\n' || c == 0 || c == EOF) {
           *p = 0;
           break;
       }
       *p++ = c; // add the valid character into the buffer
   } while (count < buffer_size - 1);  // don't overrun the buffer
   // ensure the string is null terminated
   buffer[buffer_size - 1] = 0;
   return buffer;
}

#define MAX_SCAN_LENGTH 1024

int main()
{
   char s[MAX_SCAN_LENGTH];
   printf("Enter a string: ");
   scan_line(s, MAX_SCAN_LENGTH);
   printf("got: \"%s\"\n\n", s);
   return 0;
}
 0
Author: Ed Zavada,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-30 16:37:39
/*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;
 }
 -1
Author: venkata sandeep,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-15 13:58:18