2016-11-12 1 views
0

このファイルをソートする際に問題があり、各行にインデックスを付けています。全体のポイントは、プログラムがインデックス番号に対応するプログラム行を返すことができるように、ユーザーにインデックスを入力するよう促すことです。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| 
+-----+-------+-----+ 
*/ 

答えて

0

Answer Part One.

あなたのソースコード内の主な問題は、文字列char A[amount];です: はここに私のコードです。

main()関数では、変数Aが行数に割り当てられます。

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); 

そして両方printUnsortedStringFromFile()printSortedStringFromFile()機能に同じ変数Aロード1行を読み取るためにバッファとして使用されます。

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.

あなたのソースコード内の第二の問題は、挿入ソートで学生-IDのソートレコードを昇順に順に推奨物価スライドは、だけでなく、保存する必要があるということですインデックスだけでなく、各レコードの内容も記録します。I以下のような構造を定義し使用することをお勧め:

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

次に(main()に)charからstruct gradesRecordにごA[]配列を変換します

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

printUnsortedStringFromFile()機能では、アレイA[]は直接使用されています読み取りループ:

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 

そしてprintSortedStringFromFile()機能において、アレイA[]ソート読み取りループにおいて、第2のループで表示、記憶するために使用される:読み取り、全ての行の選択ソート、

最初のループ:

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++; 
} 

第二のループ、ソートされたテーブル表示:最初の回答に記載のすべての変更を合成するために

+0

協力いただきありがとうございます、私のソートされていないテーブルが今細かいプリントアウトされますが、私は昇順で学生IDをソートする方法について混乱していますそれぞれ対応するインデックスを持つ挿入ソートを使用します。 – fgdark

+0

はい、私の答えはあなたの質問の完全な解決策ではないことを知っていますが、それを見つけるための第一歩です。あなたの質問を編集して**挿入分類**を使って生徒IDを昇順に並べ替える方法を強調できますか? –

+0

索引付けと挿入のソートを使用して、** "アンサーパート2" **を追加してください。 –

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

を、私はここで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

ありがとうございました。 – fgdark

関連する問題