web-dev-qa-db-fra.com

Comment autorisez-vous la saisie d'espaces à l'aide de scanf?

En utilisant le code suivant:

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

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

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

Un utilisateur peut entrer son nom, mais quand il entre un nom avec un espace comme Lucas Aardvark, scanf() coupe tout après Lucas. Comment faire scanf() permettre des espaces

117
Kredns

Les personnes (et surtout les débutants) ne doivent jamais utiliser scanf("%s") ou gets() ni aucune autre fonction ne bénéficiant pas d'une protection contre le débordement de mémoire tampon, sauf si vous êtes certain que l'entrée aura toujours un format spécifique (et peut-être même pas à ce moment-là) .

Rappelez-vous que scanf signifie "numériser formaté" et qu'il existe un précieux petit moins formaté que les données saisies par l'utilisateur. C'est idéal si vous avez un contrôle total sur le format des données d'entrée, mais que vous ne pouvez généralement pas l'utiliser pour la saisie par l'utilisateur.

Utilisez fgets() (qui a la protection de débordement de tampon) pour obtenir votre entrée dans une chaîne et sscanf() pour l’évaluer. Puisque vous voulez juste ce que l'utilisateur a entré sans analyser, vous n'avez pas vraiment besoin de sscanf() dans ce cas:

#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;
}
164
paxdiablo

Essayer

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

J'espère que cela pourra aider. 

113
Kelly Gendron

Cet exemple utilise un scanset inversé, donc scanf continue à prendre des valeurs jusqu'à ce qu'il rencontre un '\ n' - nouvelle ligne, ainsi les espaces sont également sauvegardés.

#include <stdio.h>

int main (int argc, char const *argv[])
{
    char name[20];
    scanf("%[^\n]s",name);
    printf("%s\n", name);
    return 0;
}
45
SVA

Vous pouvez utiliser ceci

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

Ou ca

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

21
Vitim.us

N'utilisez pas scanf() pour lire des chaînes sans spécifier une largeur de champ. Vous devriez également vérifier les valeurs de retour pour les erreurs:

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

Sinon, utilisez 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);
}
7
Christoph

Vous pouvez utiliser la fonction fgets() pour lire une chaîne ou utiliser scanf("%[^\n]s",name); pour que la lecture de chaîne se termine lorsque vous rencontrez un caractère de nouvelle ligne.

6
Anshul garg

getline()

Maintenant, une partie de POSIX, néanmoins.

Il s’occupe également du problème d’allocation de mémoire tampon que vous avez évoqué précédemment, bien que vous deviez vous occuper de freeing de la mémoire.

4
dmckee

Si quelqu'un cherche encore, voici ce qui a fonctionné pour moi: lire une longueur arbitraire de chaîne, y compris des espaces.

Merci à de nombreuses affiches sur le Web pour avoir partagé cette solution simple et élégante. Si cela fonctionne, le crédit leur revient, mais toute erreur est la mienne.

char *name;
scanf ("%m[^\n]s",&name);
printf ("%s\n",name);
4
Always Learning

Vous pouvez utiliser scanf à cette fin avec un petit truc. En fait, vous devez autoriser les entrées utilisateur jusqu'à ce que l'utilisateur appuie sur Entrée (\n). Cela tiendra compte de tous les personnages, y compris space. Voici un exemple:

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

Comment ça marche? Lorsque l'utilisateur saisit des caractères à partir de l'entrée standard, ils sont stockés dans chaîne variable jusqu'au premier espace vide. Après cela, le reste de l'entrée restera dans le flux d'entrée et attendra le prochain scanf. Ensuite, nous avons une boucle for qui prend char par char à partir du flux d’entrée (jusqu'au \n) et les ajoute à la fin de chaîne variable, formant ainsi une chaîne complète identique à celle saisie par le clavier.

J'espère que cela aidera quelqu'un! 

1
akelec

Bien que vous ne devriez vraiment pas utiliser scanf() pour ce genre de chose, car il existe de bien meilleurs appels tels que gets() ou getline(), vous pouvez le faire:

#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
Ed Zavada
/*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;
 }
0
venkata sandeep