源代码中的主要问题是字符串
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.
用作加载和读取一行的缓冲区。
在您的示例中,第一行是“等级”。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]
仅用于指数化。
答案是第二部分。
源代码中的第二个问题是,为了通过插入排序升序学生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++;
}