faire un return d'un tableau

faire un return d'un tableau - C - Programmation

Marsh Posté le 13-03-2017 à 21:45:08    

Bonjour,
 
je fais une conversion entier vers binaire (l'entier doit avoir valeur entre 0 et 255) et je veux récuperer ça dans une autre fonction pour l'envoyer au lcd. je voudrais récuperer le resultat de la conversion dans un tableau de char.
voici le code ça marche sauf pour conversion et envoi au lcd (ç'est incomplet)

Code :
  1. #include <conio.h>
  2. #include<stdlib.h>
  3. #include<stdio.h>
  4. #include<Windows.h>
  5. #define PA 0// on met en entree à 1 (PA pour Data)
  6. #define PB 1//en sortie à 0 inutilisé
  7. #define PC 2//pcl en sortie et pch en sortie ? (PC1 pour R/W) et (PC2 pour RS)
  8. void _stdcall set8255cw(unsigned char cw_byte);
  9. unsigned char _stdcall read8255(unsigned char PortNumber);
  10. void _stdcall write8255(unsigned char PortNumber,unsigned char Value);
  11. void _stdcall init_lcd();
  12. unsigned char _stdcall check_busy_byte();
  13. void menus();
  14. void commandeLCD(int booleen,unsigned char adresse);
  15. void envoichaine();
  16. void decalage();
  17. char* affBin(int decimal);//fonction pour conversion decimal vers binaire
  18. //PC0 pour E *** PC1 pour R/W *** PC2 pour RS *** PA pour Data
  19. //cycle d'écriture: RS à 0 instruction/1data, R/W à 0 ecriture(R/W à 1 lecture), mettre E à 1, écrire la data, mettre E à 0
  20. void main()
  21. {
  22. set8255cw(0x8A); //1000 1010
  23. printf("\nInitialisation du LCD : Appuyez sur une touche enter" );
  24. init_lcd();//appuyer sur enter pour sortir de la fonction  
  25. commandeLCD(0,0x01);//efface l'ecran 1er paramètre =0 car instruction et deuxième paramètre ==1 car envoi du byte 1 dans cours sur PA
  26. //est ce necessaire après initlcd de faire effacer ecran ??? si on met sur la ligne 1 colonne 1 alor ça efface l'ecran ????commandeLCD(0,0x80);
  27. menus();
  28. }
  29. void menus()
  30. {
  31. char Menu;
  32. short choix=1;
  33. do
  34. {
  35.  printf("____________________________________\n" );
  36.  printf("1) Afficher Chaine (1er ligne)\n" );
  37.  printf("2) Afficher Chaine (2eme ligne)\n" );
  38.  printf("3) Decalage \n" );
  39.  printf("4) Conversion decimal vers binaire\n" );
  40.  printf("5) Quitter" );
  41.  printf("____________________________________\n" );
  42.  fflush(stdin);
  43.  scanf_s("%d",&Menu);
  44.  switch(Menu)
  45.  {
  46.   case 1 :
  47.    commandeLCD(0,0x80);
  48.    envoichaine();
  49.    break;
  50.   case 2 :
  51.    commandeLCD(0,0xC0);
  52.    envoichaine();
  53.    break;
  54.   case 3 :
  55.    decalage();
  56.    break;
  57.   case 4:
  58.    break;
  59.         case 5 :
  60.                 choix=0;
  61.                 break;
  62.  }
  63. }while(choix!=0);
  64. }
  65. // void commandeLCD >>>> choix de instruction ou data via booleen en paramètre et ensuite cycle d'ecriture
  66. void commandeLCD(int booleen,unsigned char adresse)//booleen == 0 alors instruc sinon data alors 1 dans booleen ***** adresse pour 1 effacer lcd ou 0x80 pour première ligne ou deuxième ligne  
  67. {
  68. //cycle d'écriture: RS à 0/1, R/W à 0, mettre E à 1, écrire la data, mettre E à 0
  69. unsigned char busy_byte;
  70. unsigned char PC2Byte;
  71. do{
  72.  busy_byte=check_busy_byte();
  73.  busy_byte&=0x80;
  74.   }while(busy_byte!=0);
  75. if( booleen ==0)// selon qu'on fait une instruction ou data donc si ==0 alors instruction
  76.  {
  77.  PC2Byte=read8255(PC);
  78.  PC2Byte=PC2Byte & 0xFB;//mise à 0 de RS (PC2) donc instruction 0xFB  11111011  
  79.     write8255(PC, PC2Byte);
  80.  }
  81. else
  82. {
  83.  if(booleen == 1)// selon qu'on fait une instruction ou data
  84.  {
  85.   PC2Byte=read8255(PC);
  86.         PC2Byte=PC2Byte | 0x04;//mise à 1 de RS (PC2) ça veut dire envoi d'une donnée et non pas une instruction
  87.             write8255(PC, PC2Byte);
  88.  }
  89. }
  90. PC2Byte=read8255(PC);
  91. PC2Byte = PC2Byte & 0xFD; //Mise à 0 de R/W (PC1) donc ecriture
  92. write8255(PC, PC2Byte);
  93. PC2Byte=read8255(PC);
  94. PC2Byte = PC2Byte | 0x01; //Mise à 1 de E (PC0) sans changer les autres bits>> demarre l'ecriture
  95. write8255(PC, PC2Byte);
  96. //écriture de la donnée
  97. write8255(PA, adresse);//adresse==1 OU 0x80 OU deuxième ligne OU *chaine pour envoi de caractères
  98. Sleep(1);
  99. PC2Byte=read8255(PC);
  100. PC2Byte = PC2Byte & 0xFE; //Mise à 0 de E (PC0) et les autres bits ne sont pas changés>>> envoi de l'ecriture
  101. write8255(PC, PC2Byte);
  102. }
  103. //write8255(PA,1);//après avoir mis rs à 0 voici l'instru pour effacer le lcd mettre à 1 le bit 1 de PA voir cours
  104. //write8255(PC, 0)//enable à 0 la donnee part (l'ecran est efface)
  105. // void envoichaine()>>>>>>> saisie d'une chaine de caractères et envoi sur l'ecran lcd  
  106. //via l'appel de fonction commandeLCD qui a comme paramètres 1 (pour dire que ç'est une instruction) et chaine[i] envoi caract par caract
  107. void envoichaine()
  108. {
  109. char chaine[15];
  110. short i=0;
  111. short taille;
  112. printf("Saisir chaine : " );
  113.     fflush(stdin);
  114.     fgets(chaine,15,stdin);
  115.     taille=strlen(chaine);
  116.     chaine[taille+1]='\0';
  117.    
  118.     while (chaine[i]!=chaine[taille])
  119.     {
  120.         commandeLCD(1,chaine[i]);//on envoie caractère tant qu'on n'est pas arrivé au caractère 0 de fin de chaine
  121.  i++;
  122.     }
  123. puts(chaine);
  124. }
  125. // void decalage() >>>>> choix de decalage via un menu par l'user de décalage à gauche(a) ou droite(b) puis saisie du nombre de decalage
  126. //à effectuer et puis appel à la fonction commandeLCD qui a comme paramètres 1(car ç'est data et pas instruction)
  127. void decalage()
  128. {
  129. char Menu;
  130. short choix=1;
  131. short nbldecalage;
  132. do
  133. {
  134.  printf("____________________________________\n" );
  135.  printf("a) Ecrire a pour Decalage droite\n" );
  136.  printf("b) Ecrire b pour Decalage gauche\n" );
  137.  printf("c) Quitter" );
  138.  printf("____________________________________\n" );
  139.  fflush(stdin);
  140.  scanf("%s",&Menu);
  141.  switch(Menu)
  142.  {
  143.   case 'a' ://droite decalage
  144.    printf("\nEntrez le nombre de decalages :  " ); 
  145.             scanf("%d", &nbldecalage);
  146.             for( int i=0; i<nbldecalage; i++ )
  147.             {
  148.    commandeLCD(1,0x1C); //00011R/L00       bit R/L à 1 si decalage 1 à droite(decalage du texte DDRAM) donc 00011100
  149.    }
  150.    break;
  151.   case 'b'://gauche decalage
  152.    printf("\nEntrez le nombre de decalages :  " ); 
  153.             scanf("%d", &nbldecalage);
  154.             for( int i=0; i<nbldecalage; i++ )
  155.             {
  156.    commandeLCD(1, 0x18); //00011R/L00       bit R/L à 0 si decalage 1 à gauche(decalage du texte DDRAM) donc 00011000
  157.    }
  158.    break;
  159.      case 'c' :
  160.                 choix=0;
  161.                 break;
  162.  }
  163. }while(choix!=0);
  164. }
  165. /*convertir()
  166. // diviser le nombre decimal par 2 successivement et le reste de la division represente le nombre binaire
  167. division entière donc si y a un reste le bit à 1 sinon le bit à 0 puis inverser pour le lire le nombre binaire
  168. 44/2 >> division sans reste donc bit à 0
  169. 22/2 >> division sans reste donc bit à 0
  170. 11/2>> division avec reste donc  bit à 1
  171. 5/2.....       bit à 1
  172. 2/2         bit à 0
  173. 1/2             avec reste donc  bit à 1
  174. lecture du nombre binaire  à l'envers 00101100 ce qui vaut 44 en decimal*/
  175. char* affBin(int decimal)
  176. {
  177. char*chainebinaire=NULL;
  178. chainebinaire=(char*)malloc(8*sizeof*chainebinaire);
  179. int nbrdecimal;
  180. int i=0;
  181.      puts("Entrez un nombre positif" );
  182.      scanf("%d", &nbrdecimal);
  183.     if (decimal != 0)//condition de sortie de la boucle fonction recursive
  184. {
  185.         if (decimal > 1)//2ème condition de sortie de fonction recursive
  186.  {
  187.             affBin(decimal / 2);//verifie si divisible par 2 et si toujours supèrieur à 1 et
  188.        // les valeurs successives de decimal sont mises sur la pile
  189.   //printf("%d",decimal);
  190.         }
  191.  //printf("%d\n",decimal);
  192.         printf("%d", decimal % 2);
  193.  int i=0;
  194.  while(i<8)
  195.  {
  196.   chainebinaire[i]=(decimal%2);
  197.  sprintf(chainebinaire,((char*)(decimal%2)));
  198.  //chainebinaire[i]=itoa(chainebinaire,decimal%2,2);
  199.  i++;
  200.  }
  201.  //la division modulo d'un nombre vaut 0(chiffre pair) si pas de reste et 1(chiffre impaire) si y a un reste     
  202.     } // on va afficher directement le premier bit comme ça ç'est bien à l'envers et
  203.    //ainsi de suite(on affiche les modulo des valeurs de decimal qui ont été mises sur la pile)
  204. else
  205. {
  206.  printf("0" );
  207.  for(int i=0;i<8;i++)
  208.  {
  209.  chainebinaire[i]='0';
  210.  }
  211. }
  212. return &chainebinaire;
  213. }
  214. void envoichaine2()
  215. {
  216. short i=0;
  217. short taille;
  218. int size;
  219. char decim[25];
  220. int decim2;
  221. char chaine1[100]={"Entrez un nombre: "};
  222.    char chaine2[100]={"decimal: "};
  223.    char conversionbinaire[200];
  224.   taille=strlen(chaine1);
  225.    chaine1[taille+1]='\0';
  226.    commandeLCD(0,0x80);//on se positionne sur la première ligne du lcd pour envoyer entrez un nombre
  227.    
  228.     while (chaine1[i]!=chaine1[taille])
  229.     {
  230.         commandeLCD(1,chaine1[i]);//on envoie caractère tant qu'on n'est pas arrivé au caractère 0 de fin de chaine
  231.  i++;
  232.     }
  233. commandeLCD(0,0xC0);//on se place sur la deuxième ligne pour envoyer la phrase decimal:
  234. taille=strlen(chaine2);
  235.    chaine2[taille+1]='\0';
  236.      while (chaine2[i]!=chaine2[taille])
  237.     {
  238.         commandeLCD(1,chaine2[i]);//on envoie caractère tant qu'on n'est pas arrivé au caractère 0 de fin de chaine
  239.  i++;
  240.     }
  241. //saisie du nombre decim à convertir et envoi sur l'ecran lcd
  242. fflush(stdin);
  243. gets(decim);
  244. size=strlen(decim);
  245. //commandeLCD(0,0xC0);//je suis déjà sur la deuxième ligne ?? ça va ecrire à la suite de decimal:????
  246.   i=0;
  247.   do
  248.   {
  249.    commandeLCD(1,decim[i]);
  250.    i++;
  251.   }while (decim[i] !=decim[size]);
  252.  strcpy( conversionbinaire,affBin(decim));
  253.  /*size=strlen(conversionbinaire);
  254.  i=0;
  255.   do
  256.   {
  257.    commandeLCD(1,conversionbinaire[i]);
  258.    i++;
  259.   }while (conversionbinaire[i] !=conversionbinaire[size]);*/
  260. }


Message édité par bjs le 13-03-2017 à 22:12:18
Reply

Marsh Posté le 13-03-2017 à 21:45:08   

Reply

Marsh Posté le 13-03-2017 à 22:30:50    

J'ai pas essayé de comprendre le code, c'est pas très digeste et je vois des choses douteuses genre sprintf(chainebinaire,((char*)(decimal%2)));.

 

De manière générale: Impossible de retourner un tableau depuis une fonction. On peut retourner un pointeur issu de malloc comme tu le fais mais ce n'est pas forcément très propre car il faut penser à libérer la mémoire ailleurs (ce que tu ne fais pas, en tout cas je ne vois pas de free()).
Tu peux passer un pointeur vers un espace mémoire déjà réservé(!!) à ta fonction.

 

Après si il faut absolument retourner des tableaux on peut les mettre dans un struct mais c'est pas forcément très élégant... (et inutile içi).

 

edit: Tu devrais activer (et prendre en compte) les warnings de ton compilateur!
> "gcc" "t.c" -Wall -O3 -c -std=c99
t.c:20:6: warning: return type of 'main' is not 'int' [-Wmain]
t.c: In function 'menus':
t.c:43:9: warning: implicit declaration of function 'scanf_s' [-Wimplicit-function-declaration]
t.c: In function 'decalage':
t.c:148:13: warning: format '%d' expects argument of type 'int *', but argument 2 has type 'short int *' [-Wformat]
t.c:156:13: warning: format '%d' expects argument of type 'int *', but argument 2 has type 'short int *' [-Wformat]

t.c: In function 'affBin':
t.c:216:5: warning: return from incompatible pointer type [enabled by default]
t.c:216:5: warning: function returns address of local variable [enabled by default]

t.c:184:9: warning: unused variable 'i' [-Wunused-variable]
t.c: In function 'envoichaine2':
t.c:257:5: warning: passing argument 1 of 'affBin' makes integer from pointer without a cast [enabled by default]
t.c:179:7: note: expected 'int' but argument is of type 'char *'
t.c:224:9: warning: unused variable 'decim2' [-Wunused-variable]


Message édité par rat de combat le 13-03-2017 à 22:35:18
Reply

Marsh Posté le 13-03-2017 à 23:02:01    

Désolé, je viens de regarder le début de ton code et pour moi c'est disons pas au point...
 
P.ex.

Code :
  1. void envoichaine()
  2. {
  3.     char chaine[15];
  4.     short i=0;
  5.     short taille;
  6.     printf("Saisir chaine : " );
  7.     fflush(stdin);
  8.     fgets(chaine,15,stdin);
  9.     taille=strlen(chaine);
  10.     chaine[taille+1]='\0';
  11.     while (chaine[i]!=chaine[taille])
  12.     {
  13.         commandeLCD(1,chaine[i]);//on envoie caractère tant qu'on n'est pas arrivé au caractère 0 de fin de chaine
  14.         i++;
  15.     }
  16.     puts(chaine);
  17. }


 
Ceci
    taille=strlen(chaine);
    chaine[taille+1]='\0';
c'est dangereux: Si l'utilisateur entre 14 ou plus de caractères strlen() retourne 14 et donc taille+1=15 et donc out of bound...
 
Tu veux enlèver un éventuell '\n' c'est ça?
Alors

Code :
  1. char chaine[15];
  2. short taille;
  3. printf("Saisir chaine : " );
  4. fgets(chaine,15,stdin);
  5. taille=strlen(chaine);
  6. if(taille!=0 && chaine[taille-1]=='\n')
  7.  chaine[taille-1]='\0';
  8. printf("-%s-\n", chaine);


fgets() termine toujours avec un '\0', pas de soucis de ce côté.
 
Ensuite
    commandeLCD(1,chaine[i]);//on envoie caractère tant qu'on n'est pas arrivé au caractère 0 de fin de chaine
La fonction est définie ainsi:
    void commandeLCD(int booleen,unsigned char adresse)
Donc tu passe un caractère (imprimable) comme adresse? Ou c'est plutôt une donnée et le nom est mal choisi? Sans parler du problème de signedness (char vs unsigned char)... Petite remarque: Le mot c'est boolean.
 
La condition de la boucle n'est pas fausse mais pas très lisible, plutôt un classique while(chaine[i]!='\0') ou même while(chaine[i]).
 
Ceci
    fflush(stdin);
a un résultat indéfini (source K&R 2nd ed. page 242).
 
Vu les warnings il y a forcément d'autres problèmes...
 
EDIT: Aie!
char Menu; scanf("%s",&Menu); (dans void decalage())
Refléchis à ce qui va se passer si l'utilisateur entre iosfiposdfiodsfimdspfioidsof p.ex...
 
Comme je pense que c'est un projet universitaire je ne vais pas corriger d'avantage.


Message édité par rat de combat le 13-03-2017 à 23:09:38
Reply

Marsh Posté le 13-03-2017 à 23:14:09    

void envoichaine2()
 
{
 
 short i=0;
 short taille;
 int size;
 char decim[10];
 int decim2=0;
 char chaine1[100]={"Entrez un nombre: "};
   char chaine2[100]={"decimal: "};
   char conversionbinaire[10];
   char conversionhexa[10];
 
  taille=strlen(chaine1);
   
   commandeLCD(0,0x80);//on se positionne sur la première ligne du lcd pour envoyer entrez un nombre
     
    while (chaine1[i]!=chaine1[taille])
    {
        commandeLCD(1,chaine1[i]);//on envoie caractère tant qu'on n'est pas arrivé au caractère 0 de fin de chaine
  i++;
 
    }
 commandeLCD(0,0xC0);//on se place sur la deuxième ligne pour envoyer la phrase decimal:
 taille=strlen(chaine2);
   
     while (chaine2[i]!=chaine2[taille])
    {
        commandeLCD(1,chaine2[i]);//on envoie caractère tant qu'on n'est pas arrivé au caractère 0 de fin de chaine
  i++;
 
    }
 //saisie du nombre decim à convertir et envoi sur l'ecran lcd
 fflush(stdin);
 fgets(decim,8,stdin);
 size=strlen(decim);
 //commandeLCD(0,0xC0);//je suis déjà sur la deuxième ligne ?? ça va ecrire à la suite de decimal:????
 
   i=0;
   do
   {
    commandeLCD(1,decim[i]);
    i++;
   }while (decim[i] !=decim[size]);
   
  decim2=atoi(decim);//conversion du char en int car itoa attend un int
   itoa (decim2,decim,10);//conversion d'un entier en char en base 10
  printf ("decimal: %s\n",decim);
  itoa (decim2,conversionhexa,16);//conversion d'un entier en char en base 16
  printf ("hexadecimal: %s\n",conversionhexa);
  itoa (decim2,conversionbinaire,2);// conversion d'un entier en char en base 16
  printf ("binaire: %s\n",conversionbinaire);
  commandeLCD(0,0x01);//effacer l'ecran avant d'afficher les conversions et se place sur la première ligne du lcd
  int size2=strlen(conversionbinaire);
  i=0;
   do
   {
    commandeLCD(1,conversionbinaire[i]);
    i++;
   }while (conversionbinaire[i] !=conversionbinaire[size2]);
   
   
   commandeLCD(0,0xC0);// se placer sur la deuxième ligne de l'ecran lcd
  int size3=strlen(conversionhexa);
  i=0;
   do
   {
    commandeLCD(1,conversionbinaire[i]);
    i++;
   }while (conversionbinaire[i] !=conversionbinaire[size3]);
}


Message édité par bjs le 13-03-2017 à 23:16:00
Reply

Marsh Posté le 13-03-2017 à 23:14:48    

j'ai supprimé la fonction affBin qui me cassait la tete et j'ai tout fait à la suite dans une seule fonction
pour le caractère de fin de chaine '0' ça va pas sur le lcd car il le connait pas et affiche un caractère inconnu .... j'ai esssayé sur le lcd en labo
pour adresse j'avais mal choisi le nom
ç'est juste un petit labo pas un projet on a 5 labos à faire ...


Message édité par bjs le 13-03-2017 à 23:24:25
Reply

Marsh Posté le 13-03-2017 à 23:29:18    

Citation :

pour le caractère de fin de chaine '0' ça va pas sur le lcd car il le connait pas et affiche un caractère inconnu

Déjà je suppose que c'est une faute de frappe de ta part, il y a une grosse différence entre '0' et '\0'! Bien sûr faut pas envoyer '\0' au LCD mais un code bien fait (while(string[i]!='\0')) ne le fera pas!?! :??:  

Citation :

ç'est juste un petit labo pas un projet on a 5 labos à faire ...

Mais il y a bien une note au but? Alors ça revient au même.
 
C'est quoi comme études que tu fais et en quelle année?

Reply

Marsh Posté le 13-03-2017 à 23:32:12    

je suis en haute école. je suis en deuxième et j'ai 2 cours de première qui me restent.  
ce labo fait partie d'un cours de première
je pense que ç'est mieux la deuxième façon car je m'y retrouve mieux et elle est plus simple et je pense qu'il y a pas d'erreurs dans la fonction envoichaine2()??

Reply

Marsh Posté le 13-03-2017 à 23:33:18    

ç'est pas coté y a juste le dernier labo qui est plus dur qui est coté sur le robot voiture
ç'est pas noté(ah en français pas en belge)  y a juste le dernier labo qui est noté (robot)


Message édité par bjs le 13-03-2017 à 23:34:02
Reply

Marsh Posté le 13-03-2017 à 23:45:51    

bjs a écrit :

je suis en haute école.

Ah d'accord, c'est en Belgique, je ne connais pas leur système.

Citation :

je pense qu'il y a pas d'erreurs dans la fonction envoichaine2()??

Il n'y a rien qui va faire planter le PC à première vue mais c'est loin d'être propre!

 

Déjà c'est quoi ces machins, tu veux faire quoi??

Code :
  1. char chaine1[100]= {"Entrez un nombre: "};
  2. taille=strlen(chaine1);
  3. chaine1[taille+1]='\0';

C'est parfaitement inutile. chaine1 contient déjà un '\0' au bon endroit et si il y en avait pas il ne faudrait surtout pas utiliser strlen()! Les {} ne sont pas nécessaires comme l'indication d'une taille à moins de vouloir modifier le contenu plus tard et d'avoir besoin de plus de place.

 

Ensuite tu mélanges les while() et les do while() et il n'y a pas de gestion d'erreurs, que se passe-t-il si l'utilisateur entre autre chose qu'un nombre?
En plus je répète: fflush(stdin) est indéfini.
Aussi tu utilises des constantes un peu partout, c'est mieux (plus lisible et/ou plus sûr) d'utiliser des #define (ou des const, aucune idée pourquoi le #define est si répandu pour ce genre de trucs...) ou selon la situation un truc genre typedef enum.


Message édité par rat de combat le 13-03-2017 à 23:49:32
Reply

Marsh Posté le 13-03-2017 à 23:57:59    

ok merci pour tes conseils, j'ai enlevé les do while et j'ai remplacé par un while.
j'ai enlevé les accolades pour l'initialisation de la chaine à envoyer au lcd(ça doit être comme l'exemple de la capture de l'ecran lcd du cahier de labo)
ç'est un petit labo et les autres cours de première y a bcp de blindage des saisies donc il le demande pas ici et on suppose que l'user est intelligent


Message édité par bjs le 14-03-2017 à 00:00:42
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed