Efficacité de scanf sur des chaine

Résolu
Signaler
Messages postés
133
Date d'inscription
vendredi 17 novembre 2000
Statut
Membre
Dernière intervention
29 avril 2008
-
Messages postés
133
Date d'inscription
vendredi 17 novembre 2000
Statut
Membre
Dernière intervention
29 avril 2008
-
Salut a tous, je dois faire un prog qui affiche les initiales d'une chaine en majuscule :
ex
en entrée:
vive le c
en sortie:
VLC

Au debut j'ai penssé a ce code
#include <stdio.h>

int main()
{
  char chaine[256]=" ",chaine2[256]=" ";
  int i,j = 0;
  //saisie de la chaine  
  scanf("%s",&chaine[i]);
  //on transforme d'office le premier caractere
  chaine2[0]=chaine[0]-32;
  j++;
 
     while(chaine[i]!='\0')
       {
     if(chaine[i]=' ')
       {chaine2[j]=chaine[i+1]-32;
       j++;
       }
     i++;
     
       }
     //on affiche la chaine
     printf("%s\n",chaine2);
     return 0;
}

Mais j'avais des resultat incoherent. puis a l'aide d'une simple boucle j'ai remarqué que scanf("%s") stoppe la saisie quand le caractere est un espace.
En effet javais saisi "vive le c" et avec la boucle je constatais qu'il n'y avait  plus que "vive" dans la chaine.

J'ai donc essayé de changer le mode de saisie de la chaine :

#include <stdio.h>

int main()
{
  char chaine[256]=" ",chaine2[256]=" ";
  int i,j = 0;
 do
   {
      scanf("%c",&chaine[i]);
      i++;
    } while (chaine[i]!='\0');
 
 /* Boucle pour verifier la chaine
for (i=0;i<10;i++)
   printf("%d=%c\n",i,chaine[i]);*/
 
  chaine2[0]=chaine[0]-32;
    j++;
    while(chaine[i]!='\0')
      {
    if(chaine[i]=' ')
      {chaine2[j]=chaine[i+1]-32;
      j++;
      }
    i++;
   
      }
    printf("%s\n",chaine2);
    return 0;
}

Or ici j'ai une erreur de segmentation.
Voila j'attends vos reponsses (et je sent que j'ai fait une connerie mais c'est pas grave )

15 réponses

Messages postés
3212
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
16
Ok. Essais ceci dans ce cas:

int main ()

{

    char buf[256], out[256], *c = buf, *d = out;


    fgets(buf, sizeof(buf), stdin);


  if(*c >= 'A' && *c <= 'z') {

    *d = *c;

    if(*c >= 'a' && *c <= 'z')  *d -= 32;

    ++d; ++c;

  }

  while(*c) {

    if(*c++ == ' ') {

      if(*c >= 'A' && *c <= 'z') {

        *d = *c;

        if(*c >= 'a' && *c <= 'z') *d -= 32;

        ++d;

      }

    }

  }

    *d = 0;


    printf("%s\n", out);


    return 0;

}


On obtient un accès direct avec des pointeurs. Pas besoin d'indexer
comme tab[i] qui demande un calcule de position de la mémoire (qui coute du temps processeur).

C++ (@++)<!--
Messages postés
3212
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
16
Comme dirait BruNews, faut pas avoir peur de consulter le MSDN
http://msdn2.microsoft.com/en-us/library/ms859626.aspx

++variable : On incrémente la variable d'abord puis on utilise sa valeur
variable++ : On utilise la valeur de la variable d'abord puis on incrémente

Pour ce qui est des pointeurs, je reste formel. C'est plus rapide que d'indexer. Si ça peut t'aider, renomme tout simplement les pointeurs en un nom plus compréhensible.
Quoi qu'il en soit, il ne faut pas codé pour l'ergonomie du code. Si ton code est complexe, commente le mais ne change pas tout pour quelque chose de plus lent sous prétexte que c'est plus jolie.

Bonne continuation.

C++ (@++)<!--
Messages postés
3212
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
16
Oups, le lien que je t'ai donné explique l'utilisation de fgets pour Windows CE. C'est pas très grave, c'est la même chose mais voici tout de même le bon lien:
http://msdn2.microsoft.com/en-us/library/c37dh6kf(VS.80).aspx

C++ (@++)<!--
Messages postés
317
Date d'inscription
vendredi 25 mai 2007
Statut
Membre
Dernière intervention
19 octobre 2007

Salut,

Je te conseille d'utiliser une boucle while avec un getc, qui s'arrete des que tu trouves un \n tu mets tout ca dans une chaine, admettons puis tu fais une boucle de la maniere suivante:

debutDeMot <--- vrai tantque chaine non terminee faire
si le caractere courant est une lettre et debutDeMot alors
afficher en majuscule le caractere
 finsi 
si le caractere courant est un espace alors
   debutDeMot <--- vrai
  sinon
debutDeMot <--- faux
   finsi
 aller au caractere suivant
 finsi

=
Messages postés
133
Date d'inscription
vendredi 17 novembre 2000
Statut
Membre
Dernière intervention
29 avril 2008

heu getc t'es sur ?
car quand je fais 
#include <stdio.h>
#include <string.h>

int main()
{
  char chaine[256]=" ",chaine2[256]=" ";
  int i,j = 0;
 do
   {
      getc(chaine);
      i++;
    } while (chaine[i]!='\0');
 
 /* Boucle pour verifier la chaine
for (i=0;i<10;i++)
   printf("%d=%c\n",i,chaine[i]);*/
 
  chaine2[0]=chaine[0]-32;
    j++;
    while(chaine[i]!='\0')
      {
    if(chaine[i]=' ')
      {chaine2[j]=chaine[i+1]-32;
      j++;
      }
    i++;
   
      }
    printf("%s\n",chaine2);
    return 0;
}

a la compilation sa me dit :
pierre@darkwhite:~/C/ioi$ gcc -o initiales initiales.c
initiales.c: In function ‘main’:
initiales.c:10: warning: passing argument 1 of ‘_IO_getc’ from incompatible pointer type

et avec gets sa marche mé sa segfault apres
Messages postés
992
Date d'inscription
jeudi 2 novembre 2000
Statut
Membre
Dernière intervention
24 avril 2013
2
non , utilise plutot gets();
Contrairement au scanf ca ne s arrete pas a l espace

ex:
char maChaine[50];
printf("Entrez un mot \n");
gets(maChaine);

Voila apres tu lis ta chaine comme d'hab

Tu calcule la longueur de ta chaine strlen(maChaine) #include <string.h>
tu fais une boucle genre for(i=0;i<strlen(maChaine),i-;++)

et qd il le faut tu met tu rempli ta chaine2

ciao
Messages postés
992
Date d'inscription
jeudi 2 novembre 2000
Statut
Membre
Dernière intervention
24 avril 2013
2
et avec gets sa marche mé sa segfault apres

déso j ai vu ca apres ms en meme tps comprends rien a ceux que tu veux dire
Messages postés
133
Date d'inscription
vendredi 17 novembre 2000
Statut
Membre
Dernière intervention
29 avril 2008

Et bien moi je veux que par exemple ta une chaine :
bonjour tous le monde
et en sortie ta que les initiales des mots :
BTM

et en utilisant gets :
#include <stdio.h>
#include <string.h>

int main()
{
  char chaine[256]=" ",chaine2[256]=" ";
  int i,j = 0;
 do
   {
      gets(chaine);
      i++;
    } while (chaine[i]!='\0');
 
 /* Boucle pour verifier la chaine
for (i=0;i<10;i++)
   printf("%d=%c\n",i,chaine[i]);*/
 
  chaine2[0]=chaine[0]-32;
    j++;
    while(chaine[i]!='\0')
      {
    if(chaine[i]=' ')
      {chaine2[j]=chaine[i+1]-32;
      j++;
      }
    i++;
   
      }
    printf("%s\n",chaine2);
    return 0;
}

A la compilation j'ai :
pierre@darkwhite:~/C/ioi$ gcc -o initiales initiales.c
/tmp/cciyavwf.o: dans la fonction « main »:
initiales.c:(.text+0x7f): AVERTISSEMENT: the `gets' function is dangerous and should not be used.

A l'execution j'ai :
pierre@darkwhite:~/C/ioi$ ./initiales
bonjour a tous
Erreur de segmentation
Messages postés
3212
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
16
Voici quelque chose de fonctionnel:

int main ()

{

    char buf[256], *c = buf;


    fgets(buf, sizeof(buf), stdin);


    if(*c >= 'a' && *c <= 'z')  *c++  -= 32;

    while(*c)

       if(*c++ == ' ' && (*c >= 'a' && *c <= 'z')) *c -= 32;


    printf("%s\n", buf);


    return 0;

}

C++ (@++)<!--
Messages postés
133
Date d'inscription
vendredi 17 novembre 2000
Statut
Membre
Dernière intervention
29 avril 2008

hum,
J'aurais quelques questions
1) Dejà chez moi sa marche pas car je crois sakingdom que tu n'a pas saisi ce que je veux :
en effet avec ton  code j'ai :
En entree: "bonjours a tous" et en sortie: "Bonjour A Tous"
Or moi je veux  En entree: "bonjours a tous"et en sortie: "BAT"

2) Pourquoi vous utilisez toujours des pointeurs au lieu d'utiliser la forme de tableau? Sa sert a rien de mettre un pointeur en plus la ??????
Messages postés
317
Date d'inscription
vendredi 25 mai 2007
Statut
Membre
Dernière intervention
19 octobre 2007

SAKingdom



code bien illisible mais bravo, bel effort, peu de caracteres :p

j'aime assez

=
Messages postés
317
Date d'inscription
vendredi 25 mai 2007
Statut
Membre
Dernière intervention
19 octobre 2007

darkwhite



je pense avoir donne le code pour faire ca nous non ?
avec debutDeMot

=
Messages postés
133
Date d'inscription
vendredi 17 novembre 2000
Statut
Membre
Dernière intervention
29 avril 2008

avec getc sa marche pas et gets sa seg fault !!
Messages postés
133
Date d'inscription
vendredi 17 novembre 2000
Statut
Membre
Dernière intervention
29 avril 2008

Pourrait tu mexpliquer les lignes :
*  fgets(buf, sizeof(buf), stdin); <= Que signifie les deux derniers arguments
*  if(*c++ == ' ') <= Ici pour savoir qui est prioritaire ? est ce que c'est *c incrementé de 1 qui est comparé a ' ' ou est ce que c'est *c qui est comparé a ' ' et qui est incrementé de 1 pour la suite du code ?
Pour ma part je pencherai pour la deuxieme proposition (la j'aurais tout compris)
Messages postés
133
Date d'inscription
vendredi 17 novembre 2000
Statut
Membre
Dernière intervention
29 avril 2008

Je ne critique pas les pointeurs je m'etonne des cettte manie qu'onn les codeurs a chaque fois que je presente un coe xD
Merci beaucoup pour tes conseils

a+