Forum Programmation.c scanf s'arrête au espaces

Posté par  (site web personnel) .
Étiquettes : aucune
0
15
oct.
2004
Linux unixsrv 2.4.18-bf2.4 #1 Son Apr 14 09:53:28 CEST 2002 i686 unknown

(debian)

#include <stdio.h>


int main(void)
{
char *toto;

scanf("%s",toto);
printf("\n%s\n",toto);
return 0;
}

montaigne@unixsrv:~$ ./testscan
ceci est un test

ceci
montaigne@unixsrv:~$

là je comprend pas : si je me souviens bien, espace est le caractère 32, par le caractère 0.

Est-ce un bug, est-ce normal, y-a t il une solution ?
  • # j'ai oublié de préciser

    Posté par  (site web personnel) . Évalué à 1.

    gcc --version

    2.95.4

    « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

    • [^] # Re: j'ai oublié de préciser

      Posté par  . Évalué à 2.

      Salut.

      Je ne pense pas que cela vienne de la version de ton compilo. En jetant un petit oeil à la doc de scanf on trouve :

      s Matches a sequence of non-white-space characters;
      the next pointer must be a pointer to char, and the
      array must be large enough to accept all the
      sequence and the terminating NULL character. The
      input string stops at white space or at the maximum
      field width, whichever occurs first.

      Donc, la doc dit que le texte entré s'arrête sur un espace ou si la longueur maximale est atteinte.
      • [^] # Re: j'ai oublié de préciser

        Posté par  (site web personnel) . Évalué à 1.

        moralité, on veut récupérer une chaîne avec des espaces, on fait quoi ?

        « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

        • [^] # Re: j'ai oublié de préciser

          Posté par  . Évalué à 1.

          on peut pas.

          faut se demerder avec les strstr et les strncpy
          • [^] # Re: j'ai oublié de préciser

            Posté par  . Évalué à 2.

            on peut pas.

            Ben si, justement. Tu viens de donner la solution.
            'faut juste préciser explicitement que dans un cas aussi simple où il n'y a pas de reconnaissance de format ni de conversion, on utilise un appel d'un peu plus bas niveau.

            Donc strcpy(), et effectivement strncpy(), même chose mais te permettant de spécifier la taille du buffer d'arrivée, ce qui est quand même nettement mieux.

            A noter que si tu travailles sur un flux, typiquement si l'utilisateur saisit une chaîne, ou lorsque que tu veux lire toutes les lignes d'un fichier texte, une par une, alors fgets() est ta petite amie.
  • # RTFM scanf

    Posté par  (site web personnel) . Évalué à 1.

    %s envoie une sequence de caracteres sans espace (a sequence of non-white-space characters)
  • # Chaîne en C -> allocation

    Posté par  . Évalué à 3.

    Tu dois prévoir la place, pour que scanf te copie les octets dedans.
    Actuellement to char *toto pointe n'importe où.
    ->
    char toto[128];
    ou bien
    char *toto = (char*)malloc(256);
    avant de demander à scanf de te copier des octets, selon le format que tu lui communiques, depuis l'entrée standard.
    -> si tu es sûr que ça tient dans 127 caractères
    char toto[128];
    scanf("%127s", toto);
    printf("\n%s\n");
    return 0;
    mais si ce n'est que pour lire des chaînes (pas des entiers, hexa ...)
    préférer fread
    => man scanf; man fread
    Hope this helps.
    • [^] # Re: Chaîne en C -> allocation

      Posté par  . Évalué à 5.

      Le mieux ce serait d'utiliser fgets :

      fgets (toto, 128, stdin);


      Ça sert justement à lire des chaînes de caractères, et ça permet d'éviter les dépassements de tampon.
      • [^] # Re: Chaîne en C -> allocation

        Posté par  (site web personnel) . Évalué à 1.

        merci, parfait, c'est exactement ce que je cherchais :)

        « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

      • [^] # Re: Chaîne en C -> allocation

        Posté par  (site web personnel) . Évalué à 3.

        Oui, fgets est la solution pour remédier au scanf.

        Par contre, il ne faut pas oublier de préciser que fgets récupère aussi le retour chariot (\n) et le stocke dans la chaîne de caractère, contrairement à scanf.

        Donc pour le supprimer, il faut faire quelque chose comme :
        toto[strlen(toto)-1]='\0';
  • # malloc

    Posté par  . Évalué à 2.

    Il me semble qu'il y a une chose qui cloche dans ton programme: tu n'initialise pas ton pointeur!
    Tu devrais faire:
    char toto[100];
    ou bien:
    char *toto;
    toto = (char*)malloc(100);
    • [^] # patch

      Posté par  (site web personnel) . Évalué à 2.

      -toto = (char*)malloc(100);
      +toto = (char*)malloc(100) || exit(EXIT_FAILURE);

      pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.