Efficacité de scanf sur des chaine

Résolu
cs_darkwhite Messages postés 133 Date d'inscription vendredi 17 novembre 2000 Statut Membre Dernière intervention 29 avril 2008 - 27 mai 2007 à 21:14
cs_darkwhite Messages postés 133 Date d'inscription vendredi 17 novembre 2000 Statut Membre Dernière intervention 29 avril 2008 - 28 mai 2007 à 10:29
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

SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
27 mai 2007 à 22:53
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++ (@++)<!--
3
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
28 mai 2007 à 01:45
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++ (@++)<!--
3
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
28 mai 2007 à 01:50
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++ (@++)<!--
3
The_Guardian Messages postés 317 Date d'inscription vendredi 25 mai 2007 Statut Membre Dernière intervention 19 octobre 2007 1
27 mai 2007 à 21:51
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

=
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_darkwhite Messages postés 133 Date d'inscription vendredi 17 novembre 2000 Statut Membre Dernière intervention 29 avril 2008
27 mai 2007 à 22:08
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
0
Nicolas___ Messages postés 992 Date d'inscription jeudi 2 novembre 2000 Statut Membre Dernière intervention 24 avril 2013 1
27 mai 2007 à 22:17
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
0
Nicolas___ Messages postés 992 Date d'inscription jeudi 2 novembre 2000 Statut Membre Dernière intervention 24 avril 2013 1
27 mai 2007 à 22:19
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
0
cs_darkwhite Messages postés 133 Date d'inscription vendredi 17 novembre 2000 Statut Membre Dernière intervention 29 avril 2008
27 mai 2007 à 22:24
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
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
27 mai 2007 à 22:28
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++ (@++)<!--
0
cs_darkwhite Messages postés 133 Date d'inscription vendredi 17 novembre 2000 Statut Membre Dernière intervention 29 avril 2008
27 mai 2007 à 22:35
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 ??????
0
The_Guardian Messages postés 317 Date d'inscription vendredi 25 mai 2007 Statut Membre Dernière intervention 19 octobre 2007 1
27 mai 2007 à 22:38
SAKingdom



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

j'aime assez

=
0
The_Guardian Messages postés 317 Date d'inscription vendredi 25 mai 2007 Statut Membre Dernière intervention 19 octobre 2007 1
27 mai 2007 à 22:40
darkwhite



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

=
0
cs_darkwhite Messages postés 133 Date d'inscription vendredi 17 novembre 2000 Statut Membre Dernière intervention 29 avril 2008
27 mai 2007 à 22:41
avec getc sa marche pas et gets sa seg fault !!
0
cs_darkwhite Messages postés 133 Date d'inscription vendredi 17 novembre 2000 Statut Membre Dernière intervention 29 avril 2008
27 mai 2007 à 23:35
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)
0
cs_darkwhite Messages postés 133 Date d'inscription vendredi 17 novembre 2000 Statut Membre Dernière intervention 29 avril 2008
28 mai 2007 à 10:29
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+
0
Rejoignez-nous