Menu

Problème d'affichage en programmation en C

-
Bonjour,
J'ai réaliser un programme qui à pour but d'afficher un client, une commande, et une liste de commande en attente. J'ai réaliser une fonction affichage pour les commandes et les clients cependant cet affichage à des bug (numéro apparaissant par " magie" , des tabulation au mauvais endroits) ... Pouvez-vous m'aider ??
De plus losque j'essaye d'ajouter à ma fonction un affichage pour la liste de commande en attente un message d'erreur d'invalid operand sort, cependant je ne voit pas comment la rectifier. Je vous prit de regarder mon code laissé si dessous qui accompagne ce post.
Merci d'avance Cordialement.

tp.h


#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct
{
char idArticle[6];
char denomination[30];
float prixU;
int quantEnStock;
}Article;



typedef struct
{
char idClient[6];
char civilite[4];
char nom[25];
char prenom[25];
int codePostal;
char ville[30];
}Client;

typedef struct
{
char idCommande[5];
char idArticle[5];
char idClient[5];
int quantNonLiv;
}Commande;

typedef struct maillon
{
Commande com;
struct maillon * suiv;
} Maillon,* Liste;

Article lireArt(FILE *fe);
Client lireClient(FILE *fe);
int chargementArt(FILE *fe,Article *tArt[], int max);
Client *chargementCli(FILE *fe,int *tmax, int *nb);

void afficherArt(Article a);
void afficherTArt(Article *tArt[],int max);
void afficherCli(Client c);
void afficheTabCli(Client tabC[], int tmax);

Liste listeVide(void);
Liste ajouterEnTete(Liste l,Commande c);
Liste ajouter(Liste l,Commande c);
void afficheCommande(Commande c);
void afficher(Liste l);


tp.c

#include "tp.h"

Article lireArt(FILE *fe)
{
Article a;
fgets(a.idArticle,7,fe);
a.idArticle[strlen(a.idArticle)-1]='\0';
fgets(a.denomination,30,fe);
a.denomination[strlen(a.denomination)-1]='\0';
fscanf(fe,"%f%*c%d%*c",&a.prixU,&a.quantEnStock);
return a;
}


Client lireClient(FILE *fe)
{
Client c;
fgets(c.idClient,7,fe);
c.idClient[strlen(c.idClient)-1]='\0';
fscanf(fe,"%s%*c",c.civilite);
fgets(c.nom,25,fe);
c.nom[strlen(c.nom)-1]='\0';
fgets(c.prenom,25,fe);
c.prenom[strlen(c.prenom)-1]='\0';
fscanf(fe,"%d%*c",&c.codePostal);
fgets(c.ville,30,fe);
c.ville[strlen(c.ville)-1]='\0';
return c;
}

int chargementArt(FILE *fe,Article *tArt[], int max)
{
Article a;
int i=0;
a=lireArt(fe);
while(!feof(fe))
{
if(i==max)
{
printf("tableau plein\n");
return -2;
}
tArt[i]=(Article*) malloc (sizeof(Article));
if(tArt[i]==NULL)
{ printf("Problème de malloc \n");
return -1;
}


*tArt[i]=a;i=i+1;a=lireArt(fe);}return i;}Client *chargementCli(FILE *fe,int *tmax, int *nb){int i=0;Client *tabC,*aux;*tmax=5;Client c;tabC=(Client*)malloc(*tmax*sizeof(Client));if(tabC==NULL){printf("Pb malloc\n");return NULL;}c=lireClient(fe);while(!feof(fe)){if(i==*tmax){*tmax=*tmax+5;aux=(Client*)realloc(tabC,*tmax*sizeof(Client));if(aux==NULL){printf("Pb realloc\n");return NULL;}tabC=aux;}tabC[i]=c;i=i+1;c=lireClient(fe);}*nb=i;return tabC;}void afficherArt(Article a){printf("%s\t%s\t%.2f\t%d\n", a.idArticle,a.denomination,a.prixU,a.quantEnStock);}void afficherTArt(Article *tArt[],int max){int i;for(i=0;i<max;i++)afficherArt(*tArt[i]);}void afficherCli(Client c){printf("%s\t%s\t%s\t%s\t%d\t%s\n",c.idClient,c.civilite,c.nom,c.prenom,c.ville,c.ville);}void afficheTabCli(Client tabC[], int tmax){int i;for(i=0;i<tmax;i++)afficherCli(tabC[i]);}Liste listeVide(void){return NULL;}Liste ajouterEnTete(Liste l,Commande c){Maillon *m;m=(Maillon*)malloc(sizeof(Maillon));if(m==NULL){printf("problème malloc\n");exit (1);}m->com=c;m->suiv=l;return m;}Liste ajouter(Liste l,Commande c){if(l==NULL)return ajouterEnTete(l,c);if(c==l->com)return l;l->suiv=ajouter(l->suiv,c);return l;}void afficheCommande(Commande c){printf("%s\t%s\t%s\t%d\n",c.idCommande,c.idArticle,c.idClient,c.quantNonLiv);}void afficher(Liste l){ Commande c;if(listeVide){ printf("opération impossible !\n");return;}afficheCommande(c);afficher(l);}


testtp.c

        #include "tp.h"

        void test(void)
        {
        FILE *fe;
        Article *tArt[200], a;
        Client *tabC;
        Commande c;
        int nbArt, tmax, nb;
        char nomfich[20];
        Liste l;
        printf("donnez le nom du fichier : ");
        scanf("%s",nomfich);
        fe=fopen(nomfich,"r");
        if(fe==NULL)
        {
        printf("Probleme d'ouverture du fichier en lecture\n");
        return;
        }
        if(strcmp(nomfich,"articles.txt")==0)
        { nbArt=chargementArt(fe,tArt, 200);
        afficherTArt(tArt,nbArt);
        }
        if(strcmp(nomfich,"clients.txt")==0)
        { tabC=chargementCli(fe,&tmax,&nb);
        afficheTabCli(tabC, nb);
        }
        if(strcmp(nomfich,"lignesCommandesEncours.txt")==0)
        { l=ajouter(l,c);
        afficher(l);
        }
        fclose(fe);
        }


        int main(){
        test();
        return 0;
        } 

EDIT : Ajout des balises de code (la coloration syntaxique).
Explications disponibles ici : ICI

Merci d'y penser dans tes prochains messages.
Afficher la suite 

Votre réponse

2 réponses

Messages postés
4874
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 janvier 2019
930
0
Merci
Salut Hamster18,

Il y a certainement un problème de copier-coller dans l'affichage de ton code pour tp.c où toute la fin du fichier apparaît sur une seule ligne sur ce qui est posté sur le forum.

Sinon, chez moi, ton code ne compile pas en raison de l'erreur produite par
if(c==l->com)
dans la fonction
Liste ajouter(Liste l,Commande c)
. En effet, si le C permet d'affecter le contenu d'une struct à une autre de même type sans avoir à affecter chaque membre individuellement, tu n'as pas la même possibilité pour les comparaisons.

Donc, tu ne peux pas comparer 2 struct comme cela en C. Tu dois comparer individuellement les membres des deux structs.

Pour le reste je n'ai pas analysé ton code, ni pu l'exécuter, et on ne peut, de toutes façons, pas reproduire les problèmes d'affichage que tu indiques sans disposer des 3 fichiers de données utilisés par le programme.

S'il s'agit seulement d'un problème d'affichage, plutôt que de poster la totalité de ton code avec les fichiers de données utilisés, pourquoi ne crées-tu pas un court programme de quelques lignes avec des données de test limitées intégrées en dur et illustrant le problème constaté ?

Pour poster ton code sous forme lisible sur le forum de CCM, suit les indications de ce lien.

Dal
Hamster18
Messages postés
5
Date d'inscription
mercredi 2 janvier 2019
Dernière intervention
4 janvier 2019
-
Bonjour Dal,
Oui les différents champs de articles.txt sont séparer par des tabulations. Pour l'alternative que vous me proposer je ne voit pas ce que je doit faire.

Cordialement.
[Dal]
Messages postés
4874
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 janvier 2019
930 -
Sachant que le code ASCII de la tabulation est 9, tu peux énumérer les caractères d'une chaîne en recherchant celui-là, afin de délimiter le contenu.

Par exemple :

#include <stdio.h>

int main(void) {
    char * st = "Texte  séparé  par des tabulations";

    while (*st) {
        /* si le caractère courant est une tabulation
         * on va à la ligne et on ne l'affiche pas */
        if (*st == 9)
            printf("\n");
        else
            printf("%c", *st);
        st++;
    }
    /* on termine en beauté en allant à la ligne */
    printf("\n");

    return 0;
}

donne :

$ gcc -Wall tabulations.c
$ ./a.out
Texte
séparé
par
des
tabulations
$
[Dal]
Messages postés
4874
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 janvier 2019
930 -
Si la ligne récupérée par fgets est dans un tableau de char, tu peux déclarer un pointeur sur char où tu mets l'adresse du (premier élément) du tableau, et t'en servir comme ... pointeur :-) pour énumérer les caractères de la ligne et procéder de façon similaire, par exemple, pour mettre chaque champ de la ligne dans un tableau de chaînes :

#include <stdio.h>

int main(void) {
    char ligne[] = "Texte   séparé  par des tabulations";
    char * st = ligne;

    char champs[5][BUFSIZ];

    for (int i = 0; i < 5; i++) {
        int nb = 0;
        while (*st && *st != 9) {
            champs[i][nb] = *st;
            st++;
            nb++;
        }
        champs[i][nb] = '\0';
        st++;
    }

    for (int i = 0; i < 5; i++)
        printf("Champ %d : %s\n", i + 1, champs[i]);

    return 0;
}

produit de manière similaire :

$ gcc -Wall tabulations.c 
$ ./a.out 
Champ 1 : Texte
Champ 2 : séparé
Champ 3 : par
Champ 4 : des
Champ 5 : tabulations
$

Bien sûr, tu peux alors aussi simplement parcourir les caractères de
char ligne[]
en utilisant un indice. Mais cela rajoute une variable d'indice et des crochets dans tous les sens avec cette variable dedans, ce qui rend le code moins beau :-)
Hamster18
Messages postés
5
Date d'inscription
mercredi 2 janvier 2019
Dernière intervention
4 janvier 2019
-
Bonjour Dal,
Vos solutions semblent très intéressante, cependant elles induisent un retour a la ligne à chaque tabulation. Cet affichage induit que que les articles ne seront afficher en ligne mais les un en dessous des autres. Existerait-il un moyen de "garder" l'affichage de départ ?

Merci d'avance.
Cordialement.
[Dal]
Messages postés
4874
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 janvier 2019
930 -
oui, en utilisant la méthode décrite dans mon précédent message :

https://www.commentcamarche.net/forum/affich-35782053-probleme-d-affichage-en-programmation-en-c#3

je te donne les méthodes à utiliser, et j'illustre même la méthode par du code, à toi de comprendre la méthode et le code qui la met en oeuvre et de te l'approprier pour l'appliquer à ton problème et faire ton propre code :-)
Commenter la réponse de [Dal]
0
Merci
Bonjour Dal, je suis l'une des camarades de Hamster18 pour le projet et j'ai tenté quelques modifications suite à vos commentaires. Je voulais savoir ce qu'il en était de cette version ? Merci d'avance, cordialement.


Liste ajouterEnTete(Liste l,Commande c)
{
	Maillon *m;
	m=(Maillon*)malloc(sizeof(Maillon));
	if(m==NULL)
		{
			printf("problème malloc\n");
			exit (1);
		}
	strcpy(m->com.idCommande,c.idCommande);
	strcpy(m->com.idArticle,c.idArticle);
	strcpy(m->com.idClient,c.idClient);
	m->com.quantNonLiv=c.quantNonLiv;
	m->suiv=l;
	return m;
}	

Liste ajouter(Liste l,Commande c)
{
	if(l==NULL)
		return ajouterEnTete(l,c);
	if(c.idCommande==l->com.idCommande && c.idArticle==l->com.idArticle && c.idClient==l->com.idClient && c.quantNonLiv==l->com.quantNonLiv)
		return l;
	l->suiv=ajouter(l->suiv,c);
	return l;
}
[Dal]
Messages postés
4874
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 janvier 2019
930 -
Bonjour Pllwk,

La question que pose Hamster18 sur ce fil concerne un problème de récupération de champs de données à partir d'une ligne comprenant une tabulation en caractère séparateur et d'affichage correctement formaté sous forme de tableau sans "décalages".

Ton code ne concerne manifestement pas ces problèmes.

De plus, tu ne poses pas de réelle question. Si tu as une question distincte de celle concernant le présent fil, poste un nouveau message sur le forum avec un code minimal compilable et exécutable illustrant ton problème, en décrivant ton problème, c'est à dire ce que fait ton code, ce qu'il devrait faire selon toi, et pourquoi tu penses que c'est un problème et un membre du forum pourra peut-être répondre à ta question.
Commenter la réponse de Pllwk