2016-11-12 2 views
0

Je n'arrive pas à trier ce fichier, en attribuant à chaque ligne un index. Le but est d'inviter l'utilisateur à taper l'index afin que le programme puisse retourner la ligne de programme correspondant au numéro d'index. Voici mon code:Comment trier les chaînes à partir d'un fichier en attribuant à chaque ligne un index ordonné à l'aide du tri par insertion C

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

void printUnsortedStringFromFile(int amount, char A[]); 
void printSortedStringFromFile(int amount, char A[]); 
//bool binSearchNUM(int amount, int A[amount], int target, int *current); 

int main() 
{ 

    FILE* spData = fopen("grades.csv", "r"); 
    int ch, number_of_lines = 0; 
    do 
    { 
     ch = fgetc(spData); 
     if (ch == '\n') 
      number_of_lines++; 
    } while (ch != EOF); 

    if (ch != '\n' && number_of_lines != 0) 
     number_of_lines++; 

    fclose(spData); 

    printf("There are %d lines in file grades.csv . \n", number_of_lines); 
    int amount = number_of_lines; 
    char A[amount]; 
    printUnsortedStringFromFile(amount, A); 
    printSortedStringFromFile(amount, A); 
    return 0; 
} 


void printUnsortedStringFromFile(int amount, char A[]) 
{ 
    FILE *spData; 
    spData = fopen("grades.csv", "r"); 
    if(spData == NULL) 
    { 
     fprintf(stderr, "Error opening the file grades.csv.\n"); 
     exit(1); 
    } 


    int ex1; 
    int ex2; 
    int ex3; 
    int StudentNUM; 
    char StudentAVG; 

    printf("+-------+------+------+------+-----+\n"); 
    printf("|Student|Exam 1|Exam 2|Exam 3|Grade|\n"); 
    printf("+-------+------+------+------+-----+\n"); 
    int z = 0; 
    while((fgets(A, amount, spData)) != NULL) 
    { 
     sscanf(A, "%d, %d, %d, %d, %c", &StudentNUM, &ex1, &ex2, &ex3, &StudentAVG); 
     printf("| %d| %d| %d| %d| %c| \n", StudentNUM, ex1, ex2, ex3, StudentAVG); 
     z++; 
//prints unsorted correctly 
    } 
    printf("+-------+------+------+------+-----+\n"); 

    if (fclose(spData) == EOF) 
    { 
     fprintf(stderr, "Error closing the file grades.csv. \n"); 
     exit(2); 
    } 
} 
void printSortedStringFromFile(int amount, char A[]) 
{ 
    FILE *spData; 
    spData = fopen("grades.csv", "r"); 
    if(spData == NULL) 
    { 
     fprintf(stderr, "Error opening the file grades.csv.\n"); 
     exit(1); 
    } 
    //help needed implementing insertion sort to sort each string as an index here 
    { 
    int walk; 
    int temp; 
    for (int cur = 1; cur < amount; cur++) 
     { 
     bool located = false; 
     temp = A[cur], walk = cur-1; 
     while (walk >= 0 && !located) 
     { 
      if (temp < A[walk]) 
       { 
       A[walk+1] = A[walk]; 
       walk--; 
        } 
        else 
        { 
         located = true; 
        } 
     } 
      A[walk+1] = temp; 
     } 
    } 


    int StudentNUM; 
    char StudentAVG; 

    printf("+-----+-------+-----+\n"); 
    printf("|Index|Student|Grade|\n"); 
    printf("+-----+-------+-----+\n"); 
    int z = 0; 
    while((fgets(A, amount, spData)) != NULL) 
    { 
     sscanf(A, "%d, %c", &StudentNUM, &StudentAVG); 
     printf("| %d| %c| \n", StudentNUM, StudentAVG); 
     z++; 
//student ID prints, grade average doesn/t, unsure how to sort these strings into a numbered(index) list 
    } 
    if (fclose(spData) == EOF) 
    { 
     fprintf(stderr, "Error closing the file grades.csv. \n"); 
     exit(2); 
    } 

} 
/* (correct) example output: 
There are 5 lines in file grades.csv. 
Original: 
+-------+------+------+------+-----+ 
|Student|Exam 1|Exam 2|Exam 3|Grade| 
+-------+------+------+------+-----+ 
| 535743| 67| 96| 93| B| 
| 112213| 87| 65| 72| C| 
| 612778| 59| 58| 97| C| 
| 151774| 52| 100| 86| C| 
| 406704| 54| 72| 80| D| 
+-------+------+------+------+-----+ 
Sorted: 
+-----+-------+-----+ 
|Index|Student|Grade| 
+-----+-------+-----+ 
| 1| 112213| C| 
| 2| 151774| C| 
| 3| 406704| D| 
| 4| 535743| B| 
| 5| 612778| C| 
+-----+-------+-----+ 
*/ 

Répondre

0

Answer Part One.

Le principal problème dans votre code source est la chaîne char A[amount];.

Dans la fonction main(), la variable A est affectée au nombre de lignes? !!

In your example, number_of_lines = 5 means A[amount] = A[5] is able to store only a 4-characters string + null terminator.

printf("There are %d lines in file grades.csv . \n", number_of_lines); 
int amount = number_of_lines; 
char A[amount]; 
printUnsortedStringFromFile(amount, A); 
printSortedStringFromFile(amount, A); 

ensuite sur les deux printUnsortedStringFromFile() et printSortedStringFromFile() fonctionne de la même grandeur A est utilisé comme tampon pour charger et lire une ligne.

In your example, the first line of 'grades.csv' is longer 4 characters and is truncated before calling sscanf() .

while((fgets(A, amount, spData)) != NULL) 
{ 
    sscanf(A, "%d, %d, %d, %d, %c", &StudentNUM, &ex1, &ex2, &ex3, &StudentAVG); 

A solution could be to use a local char sTmp[80] for the fgets() and sscanf() and use the A[amount] only for the indexation.


Answer Part Two.

Le deuxième problème dans votre code source est que l'indexation proposée afin de monter les dossiers de tri étudiant-id trier d'insertion, a besoin de stocker non seulement la index mais aussi le contenu de chaque enregistrement.Je suggère d'utiliser définir une structure comme suit:

struct gradesRecord { 
    int iIndex;  // index on the file 
    int iStudentNUM; // 'Student' field 
    int iExamVAL[3]; // 'Exam 1'..'Exam 3' fields 
    char cStudentAVG; // 'Grade' field 
}; 

ensuite convertir votre tableau A[] de char à struct gradesRecord (en main()):

int amount = number_of_lines; 
struct gradesRecord A[amount]; 
printUnsortedStringFromFile(amount, A); 
printSortedStringFromFile(amount, A); 

Dans la fonction printUnsortedStringFromFile(), le tableau A[] est utilisé directement dans la boucle de lecture:

To prevent a bad formatted text-file, it is recommended to check the returned value of sscanf() in order to detect missing parameters (see the nArg variable and how to check bellow).

char sLine[81]; // local string to read one row 
int z = 0; // storage index 
int nArg; 

while((fgets(sLine, 80, spData)) != NULL) 
{ 
    nArg = sscanf(sLine, "%d, %d, %d, %d, %c", 
     &(A[z].iStudentNUM), &(A[z].iExamVAL[0]), 
     &(A[z].iExamVAL[1]), &(A[z].iExamVAL[2]), 
     &(A[z].cStudentAVG)); 

    if (nArg != 5) { 
     // the input line is not correct !!! 
     // manage that error. 
    } 

    printf("|%7d| %5d| %5d| %5d| %c| \n", A[z].iStudentNUM, 
     A[z].iExamVAL[0], A[z].iExamVAL[1], A[z].iExamVAL[2], 
     A[z].cStudentAVG); 
    z++; // next row 

Puis dans la fonction printSortedStringFromFile(), le tableau A[] est utilisé pour stocker, trier dans la boucle de lecture, puis affichée dans une deuxième boucle:

Première boucle, la lecture et le tri de sélection de toutes les lignes:

char sLine[81]; 
int iLine = 0, iRow; 
struct gradesRecord grRow,grTmp; 

while((fgets(sLine, 80, spData)) != NULL) 
{ 
    // extract one Row and store it into grRow 
    sscanf(sLine, "%d, %d, %d, %d, %c", 
     &(grRow.iStudentNUM), &(grRow.iExamVAL[0]), 
     &(grRow.iExamVAL[1]), &(grRow.iExamVAL[2]), 
     &(grRow.cStudentAVG)); 
    // keep the line index of that row 
    grRow.iIndex = iLine; 
    // search loop = insertion sort algorithm 
    for (iRow=0;iRow<iLine;iRow++) { 
     // detect if new student is before the store one 
     if (grRow.iStudentNUM < A[iRow].iStudentNUM) { 
      // exchange both stuident records through grTmp 
      memcpy(&grTmp,&(A[iRow]),sizeof(struct gradesRecord)); 
      memcpy(&(A[iRow]),&grRow,sizeof(struct gradesRecord)); 
      memcpy(&grRow,&grTmp,sizeof(struct gradesRecord)); 
     } 
    } 
    // store the biggest student at the end 
    memcpy(&(A[iLine]),&grRow,sizeof(struct gradesRecord)); 
    iLine++; 
} 

Deuxième boucle, afficher la table triée:

while (z < amount) 
{ 
    StudentNUM = A[z].iStudentNUM; 
    StudentAVG = A[z].cStudentAVG; 
    index = A[z].iIndex; 
    printf("| %4d|%7d| %c| \n", index, StudentNUM, StudentAVG); 
    z++; 
} 
+0

Merci de nous aider, ma table non triés est maintenant l'impression est bien passé, mais je suis confus sur la façon de trier les étudiants ID de dans l'ordre croissant utilisant un tri par insertion avec un index correspondant. – fgdark

+0

Oui, je sais que ma réponse n'est pas la solution complète de votre question, mais c'est un premier pas pour en trouver un. Pourriez-vous modifier votre question pour mettre en évidence que ** comment trier les identifiants des élèves dans l'ordre croissant en utilisant le tri par insertion **? –

+0

Ajout de ** "Réponse Partie Deux." ** avec indexation et tri d'insertion. –

0

afin de synthétiser toutes les modifications décrites dans la première réponse, j'ajouter ici la source complète Follo w:

1- The function main() and struct gradesRecord :

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

struct gradesRecord { 
    int iIndex;  // index on the file 
    int iStudentNUM; // 'Student' field 
    int iExamVAL[3]; // 'Exam 1'..'Exam 3' fields 
    char cStudentAVG; // 'Grade' field 
}; 

void printUnsortedStringFromFile(int amount, struct gradesRecord A[]); 
void printSortedStringFromFile(int amount, struct gradesRecord A[]); 

int main() 
{ 

    FILE* spData = fopen("grades.csv", "r"); 
    int ch, number_of_lines = 0; 
    do 
    { 
     ch = fgetc(spData); 
     if (ch == '\n') 
      number_of_lines++; 
    } while (ch != EOF); 

    if (ch != '\n' && number_of_lines != 0) 
     number_of_lines++; 

    fclose(spData); 

    printf("There are %d lines in file grades.csv . \n", number_of_lines); 
    int amount = number_of_lines; 
    struct gradesRecord A[amount]; 
    printUnsortedStringFromFile(amount, A); 
    printSortedStringFromFile(amount, A); 
    return 0; 
} 

2- The function printUnsortedStringFromFile() :

void printUnsortedStringFromFile(int amount, struct gradesRecord A[]) 
{ 
    FILE *spData; 
    spData = fopen("grades.csv", "r"); 
    if(spData == NULL) 
    { 
     fprintf(stderr, "Error opening the file grades.csv.\n"); 
     exit(1); 
    } 

    printf("+-------+------+------+------+-----+\n"); 
    printf("|Student|Exam 1|Exam 2|Exam 3|Grade|\n"); 
    printf("+-------+------+------+------+-----+\n"); 
    char sLine[81]; // local string to read one row 
    int z = 0; 
    while((fgets(sLine, 80, spData)) != NULL) 
    { 
     sscanf(sLine, "%d, %d, %d, %d, %c", 
      &(A[z].iStudentNUM), &(A[z].iExamVAL[0]), 
      &(A[z].iExamVAL[1]), &(A[z].iExamVAL[2]), 
      &(A[z].cStudentAVG)); 

     printf("|%7d| %5d| %5d| %5d| %c| \n", A[z].iStudentNUM, 
      A[z].iExamVAL[0], A[z].iExamVAL[1], A[z].iExamVAL[2], 
      A[z].cStudentAVG); 
     z++; 
    } 
    printf("+-------+------+------+------+-----+\n"); 

    if (fclose(spData) == EOF) 
    { 
     fprintf(stderr, "Error closing the file grades.csv. \n"); 
     exit(2); 
    } 
} 

3- And the function printSortedStringFromFile() :

void printSortedStringFromFile(int amount, struct gradesRecord A[]) 
{ 
    FILE *spData; 
    spData = fopen("grades.csv", "r"); 
    if(spData == NULL) 
    { 
     fprintf(stderr, "Error opening the file grades.csv.\n"); 
     exit(1); 
    } 

    char sLine[81]; 
    int iLine = 0, iRow; 
    struct gradesRecord grRow,grTmp; 

    while((fgets(sLine, 80, spData)) != NULL) 
    { 
     // extract one Row and store it into grRow 
     sscanf(sLine, "%d, %d, %d, %d, %c", 
      &(grRow.iStudentNUM), &(grRow.iExamVAL[0]), 
      &(grRow.iExamVAL[1]), &(grRow.iExamVAL[2]), 
      &(grRow.cStudentAVG)); 
     // keep the line index of that row 
     grRow.iIndex = iLine; 
     // search loop = insertion sort algorithm 
     for (iRow=0;iRow<iLine;iRow++) { 
      // detect if new student is before the store one 
      if (grRow.iStudentNUM < A[iRow].iStudentNUM) { 
       // exchange both stuident records through grTmp 
       memcpy(&grTmp,&(A[iRow]),sizeof(struct gradesRecord)); 
       memcpy(&(A[iRow]),&grRow,sizeof(struct gradesRecord)); 
       memcpy(&grRow,&grTmp,sizeof(struct gradesRecord)); 
      } 
     } 
     // store the biggest student at the end 
     memcpy(&(A[iLine]),&grRow,sizeof(struct gradesRecord)); 
     iLine++; 
    } 

    int StudentNUM; 
    char StudentAVG; 

    printf("+-----+-------+-----+\n"); 
    printf("|Index|Student|Grade|\n"); 
    printf("+-----+-------+-----+\n"); 
    int z = 0; 
    int index; 
    while (z < amount) 
    { 
     StudentNUM = A[z].iStudentNUM; // access to sorted array 
     StudentAVG = A[z].cStudentAVG; 
     index = A[z].iIndex; 
     printf("| %4d|%7d| %c| \n", index, StudentNUM, StudentAVG); 
     z++; 
    } 
    if (fclose(spData) == EOF) 
    { 
     fprintf(stderr, "Error closing the file grades.csv. \n"); 
     exit(2); 
    } 

} 
+0

Merci beaucoup. – fgdark