Bug pas compris sur le résultat de mon programme

Fermé
Arolios - Modifié le 22 avril 2022 à 08:21
 Arolios - 23 avril 2022 à 19:10
Bonjour à tous,

Je suis sur un projet pour mes cours, il est presque finalisé, mais j'ai quelques petits problèmes que je ne comprends pas.

Le but du projet et de récupérer via un fichier CSV des informations selon les colonnes (dans notre cas la colonne 6/76/85e colonnes), de les trier avec les fonctions de tri d'insertion et de sélection, et ne pas les trier, selon un nombre de ligne précis. Ensuite nous devons les remettre dans un fichier csv avec le nombre de lignes analysés et le temps que cela a mis.

Lorsqu'on sélectionne comme choix le tri par sélection, il nous laisse encore mettre les chiffres qu'on veut (while ligne 249).
J'ai également un problème avec le fclose(fdonnees); dernière ligne du programme. (expected declaration of statement at end of input).

Merci d'avance si vous pouvez m'aider un petit peu.

#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MAX 1000000

typedef char string[1024];//def du type de variable string

typedef struct reference {

    int AGED;
    long long int SURF;
    string PROF;

}ref;

ref reftab[MAX];

long int limite=0;
void triParInsertion() //Permet de trier les données par un tri par insertion
{

    //Déclaration des variables

    int cpt; //compteur
    int unit; //stockage temporaire
    int dureeTriInsert; //duree du tri
    long int unit2; //stockage temporaire
    int cpt2; //compteur 2
    string unitPROF;//stockage temporaire pour PROF
    int PROFCOMP;

    clock_t debutTriInsert; //2 variables pour le temps de tri
    clock_t finTriInsert;
    
    char TriInsertBuffer[50]; 
    char TriInsertBufferProf[50];

    FILE* fdonneesInsertion = fopen("donneeInsertion.csv", "at"); //ouverture/création du fictier csv

    for (cpt=0;cpt<50;cpt++) //On met le buffer vide
    {
        TriInsertBuffer[cpt]='\0';
    }
    printf("Tri par insertion......Tri par insertion \n");
    debutTriInsert=clock();
    
    for (cpt=0;cpt<limite;cpt++)//début du tri
    {
        //tri AGED
        unit=reftab[cpt].AGED;
        cpt2=cpt;
        while ((cpt2>0)&&(reftab[cpt2-1].AGED>unit))
        {
            reftab[cpt2].AGED=reftab[cpt2-1].AGED;
            cpt2=cpt2-1;
        }
        reftab[cpt2].AGED=unit;

        //tri PROF
        strcpy(TriInsertBufferProf,reftab[cpt].PROF);
        cpt2=cpt;

        PROFCOMP=strncmp(reftab[cpt2-1].PROF,TriInsertBufferProf,4);

        while( (cpt2 > 0) && (PROFCOMP > 0))
        {
            strcpy(reftab[cpt2].PROF,reftab[cpt2-1].PROF);
            cpt2=cpt2-1;
        }
        strcpy(reftab[cpt2].PROF,TriInsertBufferProf);

        //tri SURF
        unit2=reftab[cpt].AGED;
        cpt2=cpt;
        while ((cpt2>0)&&(reftab[cpt2-1].AGED>unit))
        {
            reftab[cpt2].AGED=reftab[cpt2-1].AGED;
            cpt2=cpt2-1;
        }
        reftab[cpt2].AGED=unit2;
    }
    finTriInsert=clock();

    //affichage après tri
    for(cpt=0;cpt<limite;cpt++)
    {
        printf("TriInsertionAged=%d TriInsertionProf=%s TriInsertionSurf=%lld \n",reftab[cpt].AGED,reftab[cpt].PROF,reftab[cpt].SURF); //affichage dans le terminal
    }
    dureeTriInsert=(finTriInsert-debutTriInsert)/1000;//calcul du temps

    //mise des données dans le fichier csv
    sprintf(TriInsertBuffer,"%d,%d",cpt,dureeTriInsert);
    fprintf(fdonneesInsertion, "%s\n",TriInsertBuffer);
}

void TriSelection()//permet de triée un tableau en plaçant les éléments par permutations à la fin du tableau
{
    //ouverture des fichiers
    //Déclaration de variables
    int cpt; //compteur
    int cpt2; //compteur 2
    int unit; //stockage temporaire
    int top; //stockage de la case du tableau top
    long int unit2; //stockage temporaire
    int TriSelectionDuree; //stockage de la durée
    string unitPROF;//stockage temporaire pour PROF

    clock_t debutTriSelection;
    clock_t finTriSelection;

    char BuffTriSelection[50];

    FILE* fdonneesSelection = fopen("donneeSelection.csv", "at");
    //Début
    //Tri SELECTION AGED
    cpt=MAX; //mise au max du compteur pour le décompagte 
    while (cpt>0) 
    {
        top=0;
        for (cpt2=0;cpt2<=cpt;cpt2++)
        {
            if (reftab[cpt2].AGED>reftab[top].AGED)
            {
                top=cpt2;
            }
        }
        reftab[top].AGED;
        reftab[top].AGED=reftab[cpt].AGED;
        reftab[cpt].AGED=unit;
        cpt=cpt-1;
    }
    //Tri Selection SURF
    cpt=MAX;
    while (cpt>0)
    {
        top=0;
        for (cpt2=0;cpt2<=cpt;cpt2++)
        {
            if (reftab[cpt2].SURF>reftab[top].SURF)
            {
                top=cpt2;
            }
        }
        unit2=reftab[top].SURF;
        reftab[top].SURF=reftab[cpt].SURF;
        reftab[cpt].SURF=unit2;
        cpt=cpt-1;
    }
    //Tri Selection PROF
    cpt=MAX;
    while (cpt>0)
    {
        top=0;
        for (cpt2=0;cpt2<=cpt;cpt2++)
        {
            if (reftab[cpt2].PROF>reftab[top].PROF)
            {
                top=cpt2;
            }
        }
        strcpy(unitPROF,reftab[top].PROF); //changement de égal vers strcpy car chaîne de caractères
        strcpy(reftab[top].PROF,reftab[cpt].PROF);
        strcpy(reftab[cpt].PROF,unitPROF);
        cpt=cpt-1;
    }
    for(cpt=0;cpt<limite;cpt++)
    {
        printf("TriInsertionAged=%d TriInsertionProf=%s TriInsertionSurf=%lld \n",reftab[cpt].AGED,reftab[cpt].PROF,reftab[cpt].SURF); //affichage dans le terminal
    }
    TriSelectionDuree=(finTriSelection-debutTriSelection)/1000;//calcul du temps
    
    //Mise dans le fichier csv
    sprintf(BuffTriSelection,"%d,%d",cpt,TriSelectionDuree);
    fprintf(fdonneesSelection, "%s\n",BuffTriSelection);
}

int main()
{
    //Déclaration de variables
    int cpt;
    int cpt_2;
    int cpt_struct;
    char element[1024];
    char buffer[50];
    int chiffre=-1;
    int x;
    int i;

    for (cpt=0; cpt < 1024; cpt++)
    {
        element[cpt] = '\0';
    }

    //ouverture des fichiers
    FILE* f = fopen("FD_INDREGZD_2018.csv","r");
    FILE* fdonnees = fopen("donnee.csv", "at");
    
    if ((f==NULL)) 
    {
        //Indique si il y a une erreur d'ouverture de fichier
        printf("Erreur d'ouverture de fichier \n");
    }
    else
    {
        while (chiffre<0)
        {
                printf("Rentrer un multiple supérieur ou égal à 0 pour le nombre de ligne à analyser \n");
                scanf("%d",&chiffre);
        }
        
        limite=chiffre*10000;
        
        clock_t debut=clock(); //nombre pas processeur seconde

        cpt_struct=0;//permet de réinitialiser
        x=0;

        while ((fgets(element, 1024 ,f)!=NULL) && (x<limite )){ 
            for (i=0; i<strlen(element);i++)
            {
                if (element[i]==';')
                {
                    element[i]=' ';
                }
            }
        
        //récupération des bonnes colonnes
        sscanf(element, "%*d%*d%*d%*d%*d%d", &reftab[cpt_struct].AGED);
        sscanf(element, "%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%s",reftab[cpt_struct].PROF);
        sscanf(element, "%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%lld", &reftab[cpt_struct].SURF);
        printf("AGED =%d, PROF=%s, SURF=%lld \n",reftab[cpt_struct].AGED,reftab[cpt_struct].PROF,reftab[cpt_struct].SURF);

        cpt_struct++;
        x++;
        }

    clock_t fin=clock();
    int duree=(fin-debut)/1000;
    printf("La durée d'éxecution est de %d millisecondes pour %d lignes",duree,x);
    sprintf(buffer,"%d,%d",cpt_struct,duree);
    fprintf(fdonnees, "%s\n",buffer);
    
    printf("Quel tri voulez-vous faire ? taper 1 pour sélection taper 2 pour insertion \n");
    scanf("%d",&chiffre);
    
    while ((chiffre==2)||(chiffre==1))
    {
        printf("Quel tri voulez-vous faire ? taper 1 pour sélection taper 2 pour insertion \n");
        scanf("%d",&chiffre);
    }
    if (chiffre==1)
    {
            TriSelection();
    }
    else (chiffre==2);
    {
            triParInsertion();
    }
    }

    fclose(f);
    fclose(fdonnees);


https://www.zupimages.net/viewer.php?id=22%2F16%2F678v.png -> problème avec le tri insertion.


Correction des balises de code, voir ici https://codes-sources.commentcamarche.net/faq/11288-les-balises-de-code

7 réponses

[Dal] Messages postés 6175 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 30 avril 2024 1 083
Modifié le 22 avril 2022 à 10:15
Salut Arolios,

Je n'ai regardé que les lignes 246 et suivantes.

Tu te serts de scanf() très maladroitement :
  • tu ne contrôles pas la valeur de retour de scanf()
  • tu ne vides pas le buffer de stdin
  • ton
    while ((chiffre==2)||(chiffre==1))
    teste la condition inverse à celle recherchée : ta boucle doit s'exécuter tant que ces conditions ne sont pas vérifiées
  • tu dupliques du code en faisant un premier scanf() en dehors de la boucle de contrôle, qui devrait plutôt être do / while


Ensuite, en ligne 258, tu écris
else (chiffre==2);
alors que tu devrais écrire
else if (chiffre==2)
: il manque le if et tu as rajouté un point virgule à la fin. Du coup ton else ne fait qu'exécuter
(chiffre==2)
et le code qui suit dans les accolades s'exécute quelle que soit la valeur de chiffre.

Pour ton erreur : "expected declaration of statement at end of input", vois s'il ne te manque pas une accolade fermante (dans ce que tu as posté, elle est manifestement manquante, mais c'est peut-être que tu n'as pas posté la fin de ton main.

Dal
0
[Dal] Messages postés 6175 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 30 avril 2024 1 083
Modifié le 22 avril 2022 à 14:28
Voilà une illustration de mes remarques :

#include <stdio.h>
  
void empty_stdin(void) {
        int c;
        while ((c = getchar()) != '\n' && c != EOF)
                /* discard */ ;
}

void TriSelection(void) {
        printf("Je fais TriSelection()\n");
}

void triParInsertion(void) {
        printf("Je fais triParInsertion()\n");
}

int main(void) {
        printf("Quel tri voulez-vous faire ? "
                "taper 1 pour sélection taper 2 pour insertion \n");
        int ret;
        int chiffre;
        do {
                ret = scanf("%d",&chiffre);
                empty_stdin();
        } while ( ret != 1 || !((chiffre == 2) || (chiffre == 1)) );

        if (chiffre == 1) {
                TriSelection();
        } else if (chiffre == 2) {
                triParInsertion();
        } else {
                printf("Nous ne sommes jamais sensés arriver ici\n");
        }

        return 0;
}
1
[Dal] Messages postés 6175 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 30 avril 2024 1 083 > [Dal] Messages postés 6175 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 30 avril 2024
Modifié le 22 avril 2022 à 16:51
J'ai regardé aussi tes lignes 231 à 233, parce qu'elles font aussi un peu mal aux yeux. Ce que tu fais peut marcher, mais si tu te trompes d'un spécificateur ou demain le format change, et tu dois récupérer la 123000ème colonne, tu vas vraiment taper 123000+ spécificateurs ? Tu as plusieurs solutions, l'une d'elle est d'utiliser strtok pour diviser ta chaîne en sous-chaînes et récupérer le champ qui t'intéresse, et là c'est l'ordinateur qui fait le boulot, dans une boucle, de compter les champs pour arriver sur le bon. Il est très fort pour cela, laissons le faire... non ?

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

int main(void) {
        char st[] = "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52;53;54;55;56;57;58;59;60;61;62;63;64;65;66;67;68;69;70;71;72;73;74;75;76;77;78;79;80;81;82;83;84;une chaîne de caractères;86;87";

        char * pch;
        pch = strtok(st, ";");
        int nfield = 0;
        while (pch != NULL) {
                nfield++;
                if (nfield == 6)
                        printf("Mettre \"%s\" dans un int\n", pch);
                else if (nfield == 76)
                        printf("Mettre \"%s\" dans un long long int\n", pch);
                else if (nfield == 85)
                        printf("Mettre \"%s\" dans un tableau de char\n", pch);
                pch = strtok(NULL, ";");
        }
        return 0;
}


https://www.cplusplus.com/reference/cstring/strtok/
0
[Dal] Messages postés 6175 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 30 avril 2024 1 083 > [Dal] Messages postés 6175 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 30 avril 2024
22 avril 2022 à 17:03
il y a plein d'autres choses à dire sur ton code, mais je vais m'arrêter là tant que tu ne réponds pas.
0
Arolios > [Dal] Messages postés 6175 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 30 avril 2024
22 avril 2022 à 22:10
Merci Dal pour tes réponses !

Désolé pour ce long temps d'attente, j'essayais de comprendre et faire ce que tu m'as envoyé.

Je ne connais pas du tout le buffer stdin, du coup je ne sais pas trop par quoi il faut remplacer le /*discard*/ pour ce que le while doit faire. Je n'ai pas compris également le fonctionnement que tu m'as recommandé pour récupérer mes colonnes : je ne vois pas comment avec
st[] 
on peut récupérer les valeurs présentes par lignes dans chaque colonnes, ou du moins je ne vois pas comment l'intégrer avec mon fgets.

J'ai aussi le problème encore, de lorsqu'on met "1" à la réponse du while qui fait qu'on écrit encore à l'infini, mais j'imagine que c'est parce que je n'ai pas compris le stdin.
0
Arolios > Arolios
22 avril 2022 à 22:44
Rebonsoir Dal,

J'ai compris le fonctionnement du clean du stdin, mais malheureusement toujours le problème d'écrire le chiffre à l'infini.

Voici le programme actuelle :
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MAX 1000000

typedef char string[1024];//def du type de variable string

typedef struct reference {

int AGED;
long long int SURF;
string PROF;

}ref;

ref reftab[MAX];

long int limite=0;

void clear_stdin(void)
{
int c;

do
{
c=getchar();
} while (c!='\n'&& c!=EOF);
}
void triParInsertion() //Permet de trier les données par un tri par insertion
{

//Déclaration des variables

int cpt; //compteur
int unit; //stockage temporaire
int dureeTriInsert; //duree du tri
long int unit2; //stockage temporaire
int cpt2; //compteur 2
string unitPROF;//stockage temporaire pour PROF
int PROFCOMP;

clock_t debutTriInsert; //2 variables pour le temps de tri
clock_t finTriInsert;

char TriInsertBuffer[50];
char TriInsertBufferProf[50];

FILE* fdonneesInsertion = fopen("donneeInsertion.csv", "at"); //ouverture/création du fictier csv

for (cpt=0;cpt<50;cpt++) //On met le buffer vide
{
TriInsertBuffer[cpt]='\0';
}
printf("Tri par insertion......Tri par insertion \n");
debutTriInsert=clock();

for (cpt=0;cpt<limite;cpt++)//début du tri
{
//tri AGED
unit=reftab[cpt].AGED;
cpt2=cpt;
while ((cpt2>0)&&(reftab[cpt2-1].AGED>unit))
{
reftab[cpt2].AGED=reftab[cpt2-1].AGED;
cpt2=cpt2-1;
}
reftab[cpt2].AGED=unit;

//tri PROF
strcpy(TriInsertBufferProf,reftab[cpt].PROF);
cpt2=cpt;

PROFCOMP=strncmp(reftab[cpt2-1].PROF,TriInsertBufferProf,4);

while( (cpt2 > 0) && (PROFCOMP > 0))
{
strcpy(reftab[cpt2].PROF,reftab[cpt2-1].PROF);
cpt2=cpt2-1;
}
strcpy(reftab[cpt2].PROF,TriInsertBufferProf);

//tri SURF
unit2=reftab[cpt].AGED;
cpt2=cpt;
while ((cpt2>0)&&(reftab[cpt2-1].AGED>unit))
{
reftab[cpt2].AGED=reftab[cpt2-1].AGED;
cpt2=cpt2-1;
}
reftab[cpt2].AGED=unit2;
}
finTriInsert=clock();

//affichage après tri
for(cpt=0;cpt<limite;cpt++)
{
printf("TriInsertionAged=%d TriInsertionProf=%s TriInsertionSurf=%lld \n",reftab[cpt].AGED,reftab[cpt].PROF,reftab[cpt].SURF); //affichage dans le terminal
}
dureeTriInsert=(finTriInsert-debutTriInsert)/1000;//calcul du temps

//mise des données dans le fichier csv
sprintf(TriInsertBuffer,"%d,%d",cpt,dureeTriInsert);
fprintf(fdonneesInsertion, "%s\n",TriInsertBuffer);
}

void TriSelection()//permet de triée un tableau en plaçant les éléments par permutations à la fin du tableau
{
//ouverture des fichiers
//Déclaration de variables
int cpt; //compteur
int cpt2; //compteur 2
int unit; //stockage temporaire
int top; //stockage de la case du tableau top
long int unit2; //stockage temporaire
int TriSelectionDuree; //stockage de la durée
string unitPROF;//stockage temporaire pour PROF

clock_t debutTriSelection;
clock_t finTriSelection;

char BuffTriSelection[50];

FILE* fdonneesSelection = fopen("donneeSelection.csv", "at");
//Début
//Tri SELECTION AGED
cpt=MAX; //mise au max du compteur pour le décompagte
while (cpt>0)
{
top=0;
for (cpt2=0;cpt2<=cpt;cpt2++)
{
if (reftab[cpt2].AGED>reftab[top].AGED)
{
top=cpt2;
}
}
reftab[top].AGED;
reftab[top].AGED=reftab[cpt].AGED;
reftab[cpt].AGED=unit;
cpt=cpt-1;
}
//Tri Selection SURF
cpt=MAX;
while (cpt>0)
{
top=0;
for (cpt2=0;cpt2<=cpt;cpt2++)
{
if (reftab[cpt2].SURF>reftab[top].SURF)
{
top=cpt2;
}
}
unit2=reftab[top].SURF;
reftab[top].SURF=reftab[cpt].SURF;
reftab[cpt].SURF=unit2;
cpt=cpt-1;
}
//Tri Selection PROF
cpt=MAX;
while (cpt>0)
{
top=0;
for (cpt2=0;cpt2<=cpt;cpt2++)
{
if (reftab[cpt2].PROF>reftab[top].PROF)
{
top=cpt2;
}
}
strcpy(unitPROF,reftab[top].PROF); //changement de égal vers strcpy car chaîne de caractères
strcpy(reftab[top].PROF,reftab[cpt].PROF);
strcpy(reftab[cpt].PROF,unitPROF);
cpt=cpt-1;
}
for(cpt=0;cpt<limite;cpt++)
{
printf("TriInsertionAged=%d TriInsertionProf=%s TriInsertionSurf=%lld \n",reftab[cpt].AGED,reftab[cpt].PROF,reftab[cpt].SURF); //affichage dans le terminal
}
TriSelectionDuree=(finTriSelection-debutTriSelection)/1000;//calcul du temps

//Mise dans le fichier csv
sprintf(BuffTriSelection,"%d,%d",cpt,TriSelectionDuree);
fprintf(fdonneesSelection, "%s\n",BuffTriSelection);
}

int main()
{
//Déclaration de variables
int cpt;
int cpt_2;
int cpt_struct;
char element[1024];
char buffer[50];
int chiffre=-1;
int x;
int i;
int rep;

for (cpt=0; cpt < 1024; cpt++)
{
element[cpt] = '\0';
}

//ouverture des fichiers
FILE* f = fopen("FD_INDREGZD_2018.csv","r");
FILE* fdonnees = fopen("donnee.csv", "at");

if ((f==NULL))
{
//Indique si il y a une erreur d'ouverture de fichier
printf("Erreur d'ouverture de fichier \n");
}
else
{
while (chiffre<0)
{
printf("Rentrer un multiple supérieur ou égal à 0 pour le nombre de ligne à analyser \n");
scanf("%d",&chiffre);
}
clear_stdin();
limite=chiffre*10000;

clock_t debut=clock(); //nombre pas processeur seconde

cpt_struct=0;//permet de réinitialiser
x=0;

while ((fgets(element, 1024 ,f)!=NULL) && (x<limite ))
{
for (i=0; i<strlen(element);i++)
{
if (element[i]==';')
{
element[i]=' ';
}
}

//récupération des bonnes colonnes
sscanf(element, "%*d%*d%*d%*d%*d%d", &reftab[cpt_struct].AGED);
sscanf(element, "%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%s",reftab[cpt_struct].PROF);
sscanf(element, "%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%lld", &reftab[cpt_struct].SURF);
printf("AGED =%d, PROF=%s, SURF=%lld \n",reftab[cpt_struct].AGED,reftab[cpt_struct].PROF,reftab[cpt_struct].SURF);

cpt_struct++;
x++;
}

clock_t fin=clock();

//calcul du temps en secondes
int duree=(fin-debut)/1000;
printf("La durée d'éxecution est de %d millisecondes pour %d lignes",duree,x);

//intégration au fichier csv
sprintf(buffer,"%d,%d",cpt_struct,duree);
fprintf(fdonnees, "%s\n",buffer);

printf("Quel tri voulez-vous faire ? taper 1 pour sélection taper 2 pour insertion \n");
scanf("%d",&rep);
clear_stdin();
while ((rep > 2)|| (rep<1))
{
printf("Quel tri voulez-vous faire ? taper 1 pour sélection taper 2 pour insertion \n");
scanf("%d",&rep);
clear_stdin();
}
if (rep==1)
{
TriSelection();
}
else if (rep==2)
{
triParInsertion();
}
else
{
printf("Impossible \n");
}
return 0;
}
fclose(f);
fclose(fdonnees);


Merci d'avance pour ton aide.
0
[Dal] Messages postés 6175 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 30 avril 2024 1 083
23 avril 2022 à 12:14
Pour la fonction de vidage du buffer de stdin, il n'y avait rien à remplacer dans la fonction que j'avais postée.

Dans le code que tu postes, de nouveau, il manque la dernière accolade fermante pour main(). Sans elle ton code ne peut pas compiler. Ton indentation est trompeuse aussi.

Je me suis résolu à tenter de compiler et exécuter ton code, bien que je ne dispose pas du fichier de données à trier, avec un FD_INDREGZD_2018.csv dans lequel je mets une 20aine de lignes similaires à ce que j'ai mis dans st[] dans mon exemple.

Si on compile ton code, en ajoutant cette accolade fermante manquante après tes 2 fclose(), il compile sans erreurs de syntaxe, mais avec les warnings suivants :

$ gcc -Wall -Wextra 37577339_02.c
37577339_02.c: In function ‘triParInsertion’:
37577339_02.c:42:13: warning: unused variable ‘unitPROF’ [-Wunused-variable]
string unitPROF;//stockage temporaire pour PROF
^~~~~~~~
37577339_02.c: In function ‘TriSelection’:
37577339_02.c:140:21: warning: statement with no effect [-Wunused-value]
reftab[top].AGED;
~~~~~~~~~~~^~~~~
37577339_02.c: In function ‘main’:
37577339_02.c:234:26: warning: comparison of integer expressions of different signedness: ‘int’ and ‘size_t’ {aka ‘long unsigned int’} [-Wsign-compare]
for (i=0; i<strlen(element);i++)
^
37577339_02.c:194:10: warning: unused variable ‘cpt_2’ [-Wunused-variable]
int cpt_2;
^~~~~
37577339_02.c: In function ‘TriSelection’:
37577339_02.c:142:26: warning: ‘unit’ may be used uninitialized in this function [-Wmaybe-uninitialized]
reftab[cpt].AGED=unit;
~~~~~~~~~~~~~~~~^~~~~
37577339_02.c:183:40: warning: ‘finTriSelection’ is used uninitialized in this function [-Wuninitialized]
TriSelectionDuree=(finTriSelection-debutTriSelection)/1000;//calcul du temps
~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
37577339_02.c:183:40: warning: ‘debutTriSelection’ is used uninitialized in this function [-Wuninitialized]


Tu as du nettoyage à faire dans ces lignes.

Selon mes tests, avec un fichier de test comprenant des lignes comme celles que j'ai mise dans st[], pense que ton code récupère les colonnes 6, 76 et 84 (pas 85).

Tu testes de nouveau mal le retour de scanf() et tu ne suis pas les indications que je donnes.

Si, lorsque tu choisis 1, ton programme n'a l'air de rien faire, c'est que ton TriSelection(), qu est bien lancé, est manifestement bogué. Lorsqu'il est lancé, il s'exécute en lançant 3 boucles for sur 1 million d'itérations chacunes, lesquelles sont chacune répétées 1 million de fois dans une boucle while ne retourne jamais. En le lançant avec un débogueur, on voit que le code reste coincé dans l'exécution de la boucle pendant un temps infini et n'a l'air de jamais en sortir :

Par exemple, voilà la première de ces 3 boucles encapsulant une boucle for dans une boucle while.

La macro MAX vaut 1000000 selon ton code

        cpt=MAX;
        while (cpt>0)
        {
                top=0;
                for (cpt2=0;cpt2<=cpt;cpt2++)
                {
                        if (reftab[cpt2].AGED>reftab[top].AGED)
                        {
                                top=cpt2;
                        }
                }
                reftab[top].AGED;
                reftab[top].AGED=reftab[cpt].AGED;
                reftab[cpt].AGED=unit;
                cpt=cpt-1;
        }


Ton ordinateur est tellement mis à genoux, que tu as l'impression qu'il ne fait rien, et tu t'obstine à taper 1 en pensant que tu es encore au stade du scanf() alors que ton programme a effectivement lancé TriSelection(), mais est occupé à faire tous ces calculs.

Je pense aussi que tu ne chronomètres pas ce qu'on te demande de chronométrer, car ton timer débute et s'arrête avant et après la récupération des données, alors qu'il paraîtrait plus logique de timer les algorithmes de tri. Mais, c'est toi qui sais ce qu'on te demande de faire et vois quoi faire ...
0
[Dal] Messages postés 6175 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 30 avril 2024 1 083
Modifié le 23 avril 2022 à 14:17
Tu écris :

Le but du projet et de récupérer via un fichier CSV des informations selon les colonnes (dans notre cas la colonne 6/76/85e colonnes), de les trier avec les fonctions de tri d'insertion et de sélection, et ne pas les trier, selon un nombre de ligne précis. Ensuite nous devons les remettre dans un fichier csv avec le nombre de lignes analysés et le temps que cela a mis.

Ce n'est pas clair.

Tu extraits 3 colonnes et tu dois trier les données.

Tes données sont mises dans le tableau de struct reftab[] définit comme suit :

typedef struct reference {

        int AGED;
        long long int SURF;
        string PROF;

}ref;

ref reftab[MAX];


Tu dois les trier selon les valeurs de quel champ ?

On dirait que tu tries les 3 champs individuellement, et que tu fais des déplacements de données qui mélangent les données contenues dans les champs.... ? Tu vas te retrouver avec des enregistrements incohérents.

Lorsque tu tries les enregistrements dans ton tableau par rapport à un champ, tu dois pemuter tous les champs de l'enregistrement en question. En C, tu peux affecter une struct à une autre de même type, et tu n'as pas besoin d'affecter les champs inviduellement.

Comme ceci :

#include <stdio.h>
  
typedef struct personne {
        int age;
        char nom[100];
        char adresse[200];
} personne;

personne personnes[2] = {
        { .age = 52, .nom = "Barnabé", .adresse = "34, rue du paradis" },
        { .age = 22, .nom = "Anatole", .adresse = "12, rue du paradis" }
};

int main(void) {
        /* tableau personnes non trié */
        printf("Tableau non trié\n");
        for (int i = 0; i < 2; i++)
                printf("Age : %d\tNom : %s\tAdresse : %s\n",
                        personnes[i].age,
                        personnes[i].nom,
                        personnes[i].adresse);
        printf("\n");
        /* on va permuter les deux enregistrements, pour les mettre 
         * dans l'ordre des âges */
        personne temp;
        temp = personnes[0];
        personnes[0] = personnes[1];
        personnes[1] = temp;
        /* tableau personnes trié par âge */
        printf("Tableau trié par âge\n");
        for (int i = 0; i < 2; i++)
                printf("Age : %d\tNom : %s\tAdresse : %s\n",
                        personnes[i].age,
                        personnes[i].nom,
                        personnes[i].adresse);

        return 0;
}


Cela donne, après compilation et exécution :

$ gcc -Wall -Wextra simple.c
$ ./a.out
Tableau non trié
Age : 52 Nom : Barnabé Adresse : 34, rue du paradis
Age : 22 Nom : Anatole Adresse : 12, rue du paradis

Tableau trié par âge
Age : 22 Nom : Anatole Adresse : 12, rue du paradis
Age : 52 Nom : Barnabé Adresse : 34, rue du paradis
$


Lignes 24 à 27, on utilise une variable temp, qui est de même type que la struct que l'on veut permuter avec une autre dans le tableau, et où on stocke temporairement le contenu de l'une des positions afin de réaliser la permutation.

Dal
0
[Dal] Messages postés 6175 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 30 avril 2024 1 083
23 avril 2022 à 14:06
Si tu as un fichier très volumineux, fais tes tests sur un fichier plus petit avec des données parlantes, avec lesquelles il sera facile de comprendre visuellement le résultat que tu obtiens, en affichant à chaque étape ce que tu fais, pour vérifier la bonne exécution de ton code.
0
[Dal] Messages postés 6175 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 30 avril 2024 1 083
23 avril 2022 à 14:29
Aussi, dans TriSelection(), tu déclares bien :

        clock_t debutTriSelection;
        clock_t finTriSelection;


mais tu n'affectes aucune valeur de temps à ces variables non initialisées avec la fonction clock().

Du coup, quand tu fais ton calcul
TriSelectionDuree=(finTriSelection-debutTriSelection)/1000;
, ce calcul se fait sur des valeurs arbitraires contenues dans ces variables non initialisées.
0

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

Posez votre question
[Dal] Messages postés 6175 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 30 avril 2024 1 083
Modifié le 23 avril 2022 à 15:36
Ce que tu fais dans chaque boucle répétée 1 million de fois au carré (multiplié par trois fois), est de ce type :

        /* cette ligne ne fait rien (cf. avertissement compilateur) */
        reftab[top].AGED;
        /* cette autre ligne affecte le contenu d'un champ d'un 
         * enregistrement en position cpt en écrasant celui en
         * position top, qui est donc perdu */
        reftab[top].AGED=reftab[cpt].AGED;
        /* cette autre ligne affecte le contenu de la variable unit,
         * qui n'est initialisée nulle part (cf avertissement 
         * compilateur) et contient donc une valeur arbitraire, à
         * un champ de l'enregistrement en position cpt, qui est 
         * donc aussi perdu */
        reftab[cpt].AGED=unit;


pendant le temps énorme que prend la fonction à s'exécuter, au point qu'elle a l'air de ne jamais pouvoir se terminer et que tu continues de taper 1, à tout hasard, en pensant qu'elle se lancera peut-être si tu tapes à nouveau, la fonction est en fait bien lancée et occupée à faire ce type d"opération 1 million de fois au carré (multiplié par trois fois).

Tes multiples saisies du chiffre 1 vont seulement dans le tampon de stdin et le programme n'en fait rien, car le programme fait autre chose et ne consomme pas les saisies à ce moment.

Si tu attends patiemment que ta fonction se termine (tu peux attendre des heures éventuellement), tu te retrouves avec des pertes de données en raison des données écrasées avec des valeurs arbitraires et des enregistrements incohérents en raison des permutations isolées résultant des multiples tentatives de tris isolés des 3 champs.

Tu dois :
  • pour le nombre d'enregistrements que tu traites (et qui n'est pas de 1 million, je suppose, en tout cas tu demandes à l'utilisateur de saisir le nombre de données qu'il veut, si j'ai bien compris)
  • trier selon le critère de tri qui t'est demandé (par exemple AGED dans l'ordre croissant)
  • permuter les données en utilisant une struct temporaire, te permettant de conserver les données de la struct que tu choisis d'écraser en premier, pour affecter le contenu sauvegardé à l'autre. Tu n'as pas à affecter les membres de la struct individuellement, le C le fait pour toi, fais juste une affectation de la struct. Ainsi les données des struct sont permutées dans leur intégralité.


Si on te demande de trier selon un seul critère de tri, c'est tout ce que tu as à faire.

Si on te demande de trier selon de multiples critères de tri (par exemple AGED dans l'ordre croissant, puis SURF dans l'ordre croissant, afin que tous les enregistrements dont le AGED est identique soient ensuite classés par SURF), tu dois le faire une fois les données triées par AGED, en repérant les enregistrements dont le AGED est identique et en les triant selon leur SURF. Et ainsi de suite si tu as un 3ème critère.

Si on ne te demande pas de trier selon de multiples critères de tri, tu n'as pas à le faire.
0
[Dal] Messages postés 6175 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 30 avril 2024 1 083
23 avril 2022 à 15:42
L'algorithme du tri par sélection est :

  procédure tri_selection(tableau t)
n ← longueur(t)
pour i de 0 à n - 2
min ← i
pour j de i + 1 à n - 1
si t[j] < t[min], alors min ← j
fin pour
si min ≠ i, alors échanger t[i] et t[min]
fin pour
fin procédure


https://fr.wikipedia.org/wiki/Tri_par_s%C3%A9lection

Ton code ne fait pas cela.

Dal
0
[Dal] Messages postés 6175 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 30 avril 2024 1 083
Modifié le 23 avril 2022 à 17:28
Ce code fonctionne en tenant compte des différentes indications que je t'ai données, et en faisant une allocation dynamique de la mémoire nécessaire pour stocker le tableau de struct des données récupérées à trier au lieu d'utiliser une variable globale allouée sur 1 million d'éléments. Le code utilise aussi des fonctions pour simplifier le main.

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

typedef char string[1024];

typedef struct reference {
        int AGED;
        long long int SURF;
        string PROF;

} ref;

void reftab_triselection(ref * reftab, size_t lignes_a_traiter) {
        /* on va trier par AGED dans l'ordre croissant selon l'algorithme :
         * https://fr.wikipedia.org/wiki/Tri_par_s%C3%A9lection */
         size_t n = lignes_a_traiter;
         for (size_t i = 0; i < n - 1; i++) {
                 size_t min = i;
                 for (size_t j = i + 1; j < n; j++)
                         if (reftab[j].AGED < reftab[min].AGED)
                                 min = j;
                 if (min != i) {
                         ref temp;
                         temp = reftab[i];
                         reftab[i] = reftab[min];
                         reftab[min] = temp;
                 }
         }
}

int str2int(char * st) {
        return (int)strtol(st, NULL, 10);
}

long long int str2ll(char * st) {
        return strtoll(st, NULL, 10);
}

ref * reftab_init(size_t lignes_a_traiter) {
        ref * reftab = malloc(sizeof(ref) * lignes_a_traiter);
        if (reftab == NULL) {
                printf("Erreur d'allocation de mémoire\n");
                exit(1);
        }
        return reftab;
}

void reftab_free(ref * reftab) {
        free(reftab);
}

void reftab_recuplignes(FILE * f, ref * reftab, size_t lignes_a_traiter) {
        char ligne[1024];
        size_t count = 0;
        while (fgets(ligne, 1024 ,f) != NULL && count < lignes_a_traiter) {
                char * pch;
                pch = strtok(ligne, ";");
                int nfield = 0;
                while (pch != NULL) {
                        nfield++;
                        if (nfield == 6)
                                reftab[count].AGED = str2int(pch);
                        else if (nfield == 76)
                                reftab[count].SURF = str2ll(pch);
                        else if (nfield == 85)
                                strncpy(reftab[count].PROF, pch, 1024);
                        pch = strtok(NULL, ";");
                }
                count++;
        }
}

void reftab_affiche(ref * reftab, size_t lignes_a_traiter) {
        for (size_t i = 0; i < lignes_a_traiter; i++) {
                printf("AGED: %d\t SURF: %lld\t PROF: %s\n",
                        reftab[i].AGED, reftab[i].SURF, reftab[i].PROF);
        }
}

int main(void) {
        FILE * f = fopen("FD_INDREGZD_2018.csv","r");
        if (f == NULL) {
                printf("Erreur d'ouverture du fichier FD_INDREGZD_2018.csv\n");
                return 1;
        }

        /* disons que l'on traite 5 lignes */
        size_t lignes_a_traiter = 5;
        ref * reftab = reftab_init(lignes_a_traiter);

        /* on récupère les 3 champs voulus sur les 5 lignes */
        reftab_recuplignes(f, reftab, lignes_a_traiter);

        /* on les affiche pour vérifier qu'on a bien ce qu'on veut */
        printf("Données récupérées, non triées :\n");
        reftab_affiche(reftab, lignes_a_traiter);

        /* on appelle la fonction de tri avec reftab */
        reftab_triselection(reftab, lignes_a_traiter);

        /* on affiche les données pour vérifier qu'on a bien ce qu'on veut */
        printf("\n");
        printf("Données triées par AGED :\n");
        reftab_affiche(reftab, lignes_a_traiter);

        reftab_free(reftab);
        fclose(f);

        return 0;
}


On fait un test minimaliste avec un fichier FD_INDREGZD_2018.csv comprenant les 7 lignes de données d'exemple suivantes :

1;2;3;4;5;3;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52;53;54;55;56;57;58;59;60;61;62;63;64;65;66;67;68;69;70;71;72;73;74;75;176;77;78;79;80;81;82;83;84;rouge;86;87
1;2;3;4;5;4;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52;53;54;55;56;57;58;59;60;61;62;63;64;65;66;67;68;69;70;71;72;73;74;75;376;77;78;79;80;81;82;83;84;orange;86;87
1;2;3;4;5;1;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52;53;54;55;56;57;58;59;60;61;62;63;64;65;66;67;68;69;70;71;72;73;74;75;276;77;78;79;80;81;82;83;84;jaune;86;87
1;2;3;4;5;2;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52;53;54;55;56;57;58;59;60;61;62;63;64;65;66;67;68;69;70;71;72;73;74;75;676;77;78;79;80;81;82;83;84;vert;86;87
1;2;3;4;5;2;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52;53;54;55;56;57;58;59;60;61;62;63;64;65;66;67;68;69;70;71;72;73;74;75;276;77;78;79;80;81;82;83;84;bleu;86;87
1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52;53;54;55;56;57;58;59;60;61;62;63;64;65;66;67;68;69;70;71;72;73;74;75;1276;77;78;79;80;81;82;83;84;indigo;86;87
1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52;53;54;55;56;57;58;59;60;61;62;63;64;65;66;67;68;69;70;71;72;73;74;75;1276;77;78;79;80;81;82;83;84;violet;86;87


Dont on va extraire le contenu des 5 premières lignes en colonnes 6, 76 et 85, pour l'afficher, en faire un tri par sélection et le réafficher, ce qui donne :

$ gcc -Wall -Wextra 37577339.c
$ ./a.out
Données récupérées, non triées :
AGED: 3 SURF: 176 PROF: rouge
AGED: 4 SURF: 376 PROF: orange
AGED: 1 SURF: 276 PROF: jaune
AGED: 2 SURF: 676 PROF: vert
AGED: 2 SURF: 276 PROF: bleu

Données triées par AGED :
AGED: 1 SURF: 276 PROF: jaune
AGED: 2 SURF: 676 PROF: vert
AGED: 2 SURF: 276 PROF: bleu
AGED: 3 SURF: 176 PROF: rouge
AGED: 4 SURF: 376 PROF: orange
$


Je te conseille de développer tes propres fonctions, car le but n'est pas que tu copie le travail d'un autre, et il te reste de toutes façons beaucoup de choses à faire pour que ton programme fasse ce qu'il est sensé devoir faire, mais veille à ce qu'en utilisant les mêmes données simplifiées de départ, tu obtiennes les mêmes résultats ci-dessus que tu puisses vérifier.

Sinon, tu alignes du code sans savoir ce que tu fais, ni où tu vas.

C'est tout, je n'écris plus pour le moment :-)

Dal
0
Bonjour Dal

Merci encore une fois pour ton aide !

J'ai relu mon sujet par à ce que tu m'as dit sur mon tri, et en effet j'avais mal compris, je ne dois trier que une seule chose de ma structure.

J'ai aussi rajouté et corriger mes récupérations pour le temps d'exécution.
Je n'ai également plus le problème du million de lignes à traiter avec tri sélection (que j'ai d'ailleurs corriger aussi, j'avais oublié de mettre une variable à une ligne), en remplaçant mon
 cpt=MAX; 
par
 cpt=limite; 
, comme ça il ne se base vraiment que sur le nombre de ligne fourni par l'utilisateur. j'avais essayé de base avec un strlen mais j'avais eu une erreur, mais pour l'instant ça marche.

Pour le reste malheureusement aujourd'hui et demain je n'aurai pas le temps, je regarderai dans la semaine, je te redirai quoi si cela t'intéresse.

En tous merci beaucoup, j'ai pu corriger pas mal de problème !
Bonne soirée à toi. :-)
0