我有一个数据库应用程序,添加和删除了一些记录后,我进入情况6以释放内存并退出应用程序。我知道我退出程序存储器后会自动获得免费,但正如老师所说,我会这样做。删除记录时遇到的堆损坏同样问题,然后尝试释放最后一条记录。在下面可以找到我的程序。我知道要更长一些,但经过很多天又几个小时,我无法确定问题所在。在下面,您将找到我的代码。
#include <stdio.h>
#include <malloc.h>
#include <string.h>
typedef struct StudentDynamic
{
char* firstName;
char* lastName;
float grade;
}StudentDynamic;
void exportCSV(char *filename, StudentDynamic* pStudents, int nStudents)
{
printf("\n Creating %s.csv file. \n ", filename);
FILE *fp;
filename = strcat(filename, ".csv");
fp = fopen(filename, "wb+");
fprintf(fp, "Student No., First Name, Last Name, Grade");
for (int i = 0; i<nStudents; ++i)
{
fprintf(fp, "\n%d", i + 1);
fprintf(fp, ",%s ", pStudents[i].firstName);
fprintf(fp, ",%s ", pStudents[i].lastName);
fprintf(fp, ",%f ", pStudents[i].grade);
}
fclose(fp);
printf("\n File %s succesfully created!\n", filename);
}
void printStudents(StudentDynamic* pStudents, int nStudents)
{
printf("==========");
printf(" List of Students");
printf(" ========== \n");
for (int i = 0; i < nStudents; ++i)
{
printf("%d. %12s %12s %8.2f", i + 1,
pStudents[i].firstName,
pStudents[i].lastName,
pStudents[i].grade);
printf("\n");
}
}
void rewriteFile(StudentDynamic* pStudents, int nStudents)
{
for (int i = 0; i < nStudents - 1; ++i)
for (int j = i + 1; j < nStudents; ++j)
{
if (pStudents[i].grade > pStudents[j].grade)
{
StudentDynamic aux;
aux = pStudents[i];
pStudents[i] = pStudents[j];
pStudents[j] = aux;
}
}
FILE *rwF;
rwF = fopen("logfile.bin", "wb");
for (int i = 0; i<nStudents; ++i)
{
fprintf(rwF, "%s\n", pStudents[i].firstName);
fprintf(rwF, "%s\n", pStudents[i].lastName);
if (i + 1 == nStudents)
{
fprintf(rwF, "%f", pStudents[i].grade);
break;
}
fprintf(rwF, "%f\n", pStudents[i].grade);
}
fclose(rwF);
}
int main()
{
int nStudents, i = 0;
StudentDynamic* pStudents = NULL;
char auxfirstName[255], auxlastName[255];
float auxGrade, updGrade;
FILE *pFile;
pFile = fopen("logfile.bin", "rb");
if (pFile == NULL)
{
printf("Could not open file or is empty! Exiting...");
exit(2);
}
while (!feof(pFile) && pFile != " ")
{
pStudents = (StudentDynamic*)realloc(pStudents, sizeof(StudentDynamic)*(i + 2));
fscanf(pFile, "%s", auxfirstName);
pStudents[i].firstName = (char*)malloc(strlen(auxfirstName) + 1);
strcpy(pStudents[i].firstName, auxfirstName);
fscanf(pFile, "%s", auxlastName);
pStudents[i].lastName = (char*)malloc(strlen(auxlastName) + 1);
strcpy(pStudents[i].lastName, auxlastName);
fscanf(pFile, "%f", &auxGrade);
pStudents[i].grade = auxGrade;
strcpy(auxfirstName, "");
strcpy(auxlastName, "");
auxGrade = 0;
i++;
}
nStudents = i;
for (int i = 0; i < nStudents - 1; ++i)
for (int j = i + 1; j < nStudents; ++j)
{
if (pStudents[i].grade > pStudents[j].grade)
{
StudentDynamic aux;
aux = pStudents[i];
pStudents[i] = pStudents[j];
pStudents[j] = aux;
}
}
fclose(pFile);
char choice;
printf("\t\t================== STUDENT DATABASE APPLICATION ==================");
printf("\n\n");
printf(" \n\t\t\t============================================");
printf("\n \t\t\t 1. Create Student");
printf("\n \t\t\t 2. Update Record");
printf("\n \t\t\t 3. Delete Record");
printf("\n \t\t\t 4. Export DB to CSV");
printf("\n \t\t\t 5. List Students");
printf("\n \t\t\t 6. Exit Program");
printf(" \n\t\t\t============================================");
printf("\n\n");
printf(" Select Your Choice : ");
getch();
while (1)
{
choice = getchar();
switch (choice)
{
case '1':
nStudents++;
pStudents = (StudentDynamic*)realloc(pStudents, sizeof(StudentDynamic) * (nStudents + 1));
printf("Details of the new student:\n");
printf("First name: ");
scanf("%s", auxfirstName);
pStudents[nStudents - 1].firstName = (char*)malloc(strlen(auxfirstName) + 1);
strcpy(pStudents[nStudents - 1].firstName, auxfirstName);
printf("Last Name: ");
scanf("%s", auxlastName);
pStudents[nStudents - 1].lastName = (char*)malloc(strlen(auxlastName) + 1);
strcpy(pStudents[nStudents - 1].lastName, auxlastName);
printf("Grade: ");
scanf("%f", &auxGrade);
pStudents[nStudents - 1].grade = auxGrade;
i++;
rewriteFile(pStudents, nStudents);
printf("\n Enter Another Choice : ");
break;
case '2':
int idtoUpdate;
printf("Update Records for student number: ");
scanf("%d", &idtoUpdate);
idtoUpdate = idtoUpdate - 1;
if (idtoUpdate>nStudents)
printf("Your number is bigger than number of Students. Enter a correct number.");
else
{
int auxI = idtoUpdate;
printf("\n");
printf("Change details for student number %d. \n", auxI + 1);
printf("type 1 for Yes / type 0 for Next step\n");
int changeChoice = 0, changeCount;
printf("Want to change First name?:");
scanf("%d", &changeChoice);
changeCount = 0;
if (changeChoice == 1)
{
changeCount++;
printf("Change First name: ");
scanf("%s", auxfirstName);
pStudents[auxI].firstName = (char*)malloc(strlen(auxfirstName) + 1);
strcpy(pStudents[auxI].firstName, auxfirstName);
}
changeChoice = 0;
printf("Want to change Last name?:");
scanf("%d", &changeChoice);
if (changeChoice == 1)
{
changeCount++;
printf("Change Last Name: ");
scanf("%s", auxlastName);
pStudents[auxI].lastName = (char*)malloc(strlen(auxlastName) + 1);
strcpy(pStudents[auxI].lastName, auxlastName);
}
changeChoice = 0;
printf("Want to change the Grade?:");
scanf("%d", &changeChoice);
if (changeChoice == 1)
{
updGrade = 0;
changeCount++;
printf("Change Grade: ");
scanf(" %f", &updGrade);
pStudents[auxI].grade = updGrade;
}
if (changeCount != 0)
rewriteFile(pStudents, nStudents);
}
printf("\n Enter Another Choice : ");
break;
case '3':
int idtoDelete;
printf("Delete Records for student number: ");
scanf("%d", &idtoDelete);
idtoDelete = idtoDelete - 1;
if (idtoDelete>nStudents)
printf("Your number is bigger than number of Students. Enter a correct number.");
else
{
for (int i = idtoDelete; i < nStudents - 1; ++i)
{
strcpy(pStudents[i].firstName, pStudents[i + 1].firstName);
strcpy(pStudents[i].lastName, pStudents[i + 1].lastName);
pStudents[i].grade = pStudents[i + 1].grade;
}
free(pStudents[nStudents-1].firstName);
free(pStudents[nStudents - 1].lastName);
nStudents--;
rewriteFile(pStudents, nStudents);
}
printf("\n Enter Another Choice : ");
break;
case '4':
char str[10];
printf("\n Enter the filename (max. 10 characters): ");
scanf("%s", str);
exportCSV(str, pStudents, nStudents);
printf("\n Enter Another Choice : ");
break;
case '5':
printf("\n");
for (int i = 0; i < nStudents - 1; ++i)
for (int j = i + 1; j < nStudents; ++j)
{
if (pStudents[i].grade > pStudents[j].grade)
{
StudentDynamic aux;
aux = pStudents[i];
pStudents[i] = pStudents[j];
pStudents[j] = aux;
}
}
printStudents(pStudents, nStudents);
printf("\n Enter Another Choice : ");
break;
case '6':
for (int i = 0; i < nStudents-1; ++i)
{
free(pStudents[i].firstName);
free(pStudents[i].lastName);
}
free(pStudents);
printf("\n");
printf("\t\t Thank you for using my application.");
printf("\n\n");
exit(0);
}
}
return 0;
}
最佳答案
在一个地方分配额外的记录时,使用:
pStudents = (StudentDynamic*)realloc(pStudents, sizeof(StudentDynamic)*(i + 2));
我认为您在其中创建了太多记录,应该是i +1
稍后在您使用的代码中
pStudents = (StudentDynamic*)realloc(pStudents, sizeof(StudentDynamic) * (nStudents + 1));
并且看起来是正确的。因为这是您遇到问题的最后一个学生记录,所以这就是问题所在,当读取文件时,最后会有一条额外的记录。您在数组末尾的任何内容中都没有多余的记录。
关于c - 在C中正常阻塞后检测到堆损坏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48213749/