如何使用C中的插入排序为每行提供有序索引,从文件中对字符串进行排序

时间:2016-11-12 22:18:11

标签: c string sorting indexing insertion

我在排序此文件时遇到问题,为每行提供索引。重点是提示用户输入索引,以便程序可以返回与索引号对应的程序行。 这是我的代码:

#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|
+-----+-------+-----+
*/

2 个答案:

答案 0 :(得分:0)

  

回答第一部分。

源代码中的主要问题是字符串char A[amount];

main()函数中,变量A被分配给行数?!!

  

在您的示例中,number_of_lines = 5表示A[amount] = A[5]   能够只存储4个字符的字符串+空终止符。

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用作加载和读取一行的缓冲区。

  

在您的示例中,'grades.csv'的第一行是4个字符   并在调用sscanf()之前被截断。

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

解决方案可能是使用本地char sTmp[80]作为fgets()   和sscanf()并仅使用A[amount]进行索引。

  

回答第二部分。

源代码中的第二个问题是建议的索引以便通过插入排序来提升student-id排序记录,不仅需要存储索引,还需要存储每条记录的内容。我建议使用如下定义结构:

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

然后将A[]数组从char转换为struct gradesRecord(在main()中):

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

printUnsortedStringFromFile()函数中,数组A[]直接在读取循环中使用:

  

为防止格式错误的文本文件,建议检查   返回值sscanf()以检测缺少的参数(请参阅nArg变量以及如何检查以下内容)。

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[]用于存储,在读取循环中排序,然后在第二个循环中显示:

首先循环,读取和选择所有行的排序:

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

第二个循环,显示已排序的表:

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

答案 1 :(得分:0)

为了综合第一个答案中描述的所有修改,我在这里添加完整的来源如下:

  

1-功能main()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-函数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-功能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);
    }

}