gpt4 book ai didi

c - 程序不写入文件并在加载时崩溃

转载 作者:太空宇宙 更新时间:2023-11-04 07:59:43 25 4
gpt4 key购买 nike

所以我需要写入和读取二进制文件,但似乎做不到,而且在使用 readFromFile 时,程序崩溃了。我需要帮助写入二进制文件,然后从中读取并在关闭程序后稍后恢复我的工作。我不知道我做错了什么,我已经搜索了很长时间,但没有结果。这是我的程序代码:

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>

typedef struct{
char *subjName;
char *lectName;
char *lectSurname;
int credits;
int num_students;
}Subject;

typedef struct{
Subject **subjs;
int num_subjs;
}Subjects;

int numOfSubjs=0;

void listInput();
void listEdit();
void listDelete();
void listPrint();
int userChoice(int select);
int enterNumber(char *name);
void saveToFile(Subjects *subjects);
void readFromFile(Subjects *subjects);

int main() {

Subjects *subjects = malloc(sizeof(Subjects));
subjects->num_subjs = 0;
subjects->subjs = NULL;
readFromFile(subjects);
int r=1;
while(r!=0){
int select=userChoice(select);
switch(select){
case 1:
listPrint(subjects);
break;

case 2:
listInput(&subjects);
break;

case 3:
listDelete(subjects);
break;

case 4:
listEdit(subjects);
break;

case 0:
r=0;
break;
}
}
saveToFile(subjects);
return 0;
}

int userChoice(int select){ // menu options
int choice,input=0;
printf("(1). View all the data\n");
printf("(2). Enter new data\n");
printf("(3). Delete data\n");
printf("(4). Edit data\n");
printf("(0). Exit\n");
printf("-----------------------------\n");

while(input!=1){
choice = enterNumber("menu");
if(choice>4 || choice<0){
printf("Invalid input \n");
}
else
input = 1;
}
return choice;
}

void listPrint(Subjects *subjects){ // print data
int i;
for(i=0; i< numOfSubjs; i++){
printf("%d, %s, %s, %s, %d, %d\n",i+1, subjects->subjs[i]->subjName, subjects->subjs[i]->lectName, subjects->subjs[i]->lectSurname, subjects->subjs[i]->credits, subjects->subjs[i]->num_students);
}
printf("Number of entries: %d \n", numOfSubjs);
}

char *getln() //dynamically allocate input string
{
char *line = NULL, *tmp = NULL;
size_t size = 0, index = 0;
int ch = 1;

while (ch) {
ch = getc(stdin);
if (ch == '\n')
ch = 0;

if (size <= index) {
size += 1;
tmp = realloc(line, size);
if (!tmp) {
free(line);
line = NULL;
break;
}
line = tmp;
}

line[index++] = ch;
}

return line;
}



void saveToFile(Subjects *subjects){
FILE *data;
data = fopen("data.bin","wb");
printf("%s", subjects->subjs[0]);
for(int i=0; i<numOfSubjs; i++){
fwrite(&subjects->subjs[i],sizeof(Subject*),1,data);
}
fclose(data);
}

void readFromFile(Subjects *subjects){
FILE *data;
int i=0;
data = fopen("data.bin","rb");
while(!feof(data))
{
fread(&subjects->subjs[i],sizeof(Subject*),1,data);
i++;
}
fclose(data);
}

int isText(char *str,char *name){ // check if is text
for(int i = 0; i < strlen(str);i++){
if((str[i]<'A' || str[i]>'z') && str[i]!=' '){
printf("Error, %s must be a text \n",name);
return 0;
}
}
return 1;
}

int enterNumber(char *name){ // enter number and check if is number
int input=0, crash=0, num=0;
while(input!=1)
{
crash=0;
printf("Enter the number of %s\n", name);
scanf("%d", &num);
while(getchar()!='\n')
{
crash++;
}
if(crash>0 || num<0)
printf("Error, enter a not negative number of %s\n", name);
else if(crash==0)
input=1;
}
return num;
}

void listInput(Subjects **p_subjects){ // input new data

Subject *new_subj = malloc(sizeof(Subject));
new_subj->subjName = NULL;
new_subj->lectName = NULL;
new_subj->lectSurname = NULL;
new_subj->credits = 0;
new_subj->num_students = 0;

do{
printf("Enter the name of the subject \n");
new_subj->subjName = getln();
}while(!isText(new_subj->subjName,"Subject name"));

do{
printf("Enter the name of the lecturer \n");
new_subj->lectName = getln();
new_subj->lectName[0] &= '_';
}while(!isText(new_subj->lectName,"Lecturer's name"));

do{

printf("Enter the surname of the lecturer\n");
new_subj->lectSurname = getln();
new_subj->lectSurname[0] &= '_'; //Convert to uppercase if lowercase
}while(!isText(new_subj->lectSurname,"Lecturer's name"));

new_subj->credits = enterNumber("credits");

new_subj->num_students = enterNumber("students");

(*p_subjects)->subjs = realloc((*p_subjects)->subjs,sizeof(Subject*)*(++(*p_subjects)->num_subjs));
(*p_subjects)->subjs[(*p_subjects)->num_subjs-1] = new_subj;
numOfSubjs++;
printf("Added a new entry.\n\n");
}

void listDelete(Subjects *subjects){ // delete entries
int del;
if(numOfSubjs==0)
printf("Number of entries is 0, can't delete anything\n");
else{
printf("Enter 0 to exit. Number of subjects : %d \n", numOfSubjs);
while(1){
del = enterNumber("entry which you would like to delete");
if(del<=numOfSubjs && del>0){
for(int i = del-1; i<numOfSubjs-1; i++){
subjects->subjs[i]=subjects->subjs[i+1];
subjects->subjs = realloc(subjects->subjs,sizeof(Subject*)*(--subjects->num_subjs));
}
numOfSubjs--;
break;
}
if(del>numOfSubjs)
printf("Error, input a number between 1 and %d (or enter 0 to exit)\n", numOfSubjs);
else
break;
}
}
}
void listEdit(Subjects *subjects){ // edit entries
int choice=0, editEntry=0, editSubj=0;
if(numOfSubjs == 0)
printf("Number of entries is 0, can't edit anthing\n");
else{
while(1){
printf("Number of entry must be between 1 and %d \n", numOfSubjs);
choice = enterNumber("entry you would like to edit.");
if(choice>0 && choice<=numOfSubjs){
while(1){
editEntry = enterNumber("what would you like to edit\n 1 - Subject name\n 2 - Lecturer's name\n 3 - Lecturer's surname\n 4 - Number of credits\n 5 - Number of students");
if(editEntry>0 && editEntry <=5){
switch(editEntry){
case 1:
do{
printf("Enter the name of the subject \n");
subjects->subjs[choice-1]->subjName = getln();
}while(!isText(subjects->subjs[choice-1]->subjName,"Subject name"));
break;
case 2:
do{
printf("Enter Lecturer's name \n");
subjects->subjs[choice-1]->lectName = getln();
}while(!isText(subjects->subjs[choice-1]->lectName,"Lecturer's name"));
break;
case 3:
do{
printf("Enter Lecturer's surname \n");
subjects->subjs[choice-1]->lectSurname = getln();
}while(!isText(subjects->subjs[choice-1]->lectSurname,"Lecturer's surname"));
break;
case 4:
subjects->subjs[choice-1]->credits = enterNumber("credits");
break;
case 5:
subjects->subjs[choice-1]->num_students = enterNumber("students");
break;

}
}
break;
}
}
break;
}
}
}

最佳答案

&subjects->subjs[i], 这是未定义的行为。访问垃圾值。您需要正确初始化它正确的内存地址。你不能在任何地方这样做。

(*subjects).subjssubjects->subjs -> 这没有指向任何地方。它是 NULL

同样在这里你不需要双指针。一个指针会做你想做的事。

typedef struct{
Subject *subjs;
int num_subjs;
}Subjects;

对于单指针,这就像

Subjects *subjects = malloc(sizeof(Subjects));
subjects->num_subjs = 10;
subjects->subjs = malloc(subjects->num_subjs * sizeof Subject);
subjects->subjs[0].subjName = malloc(40);

每个 malloc 都应该用它的返回值来检查。如果它为 NULL,则继续或访问它将会出错。

当您完成使用它时,相应地 free() 它。


一些基本的东西:-

  typedef struct{
Subject *subjs;
int num_subjs;
}Subjects;

现在让我们看一下代码。

Op 询问为什么 OP 应该初始化并且不是;t subjects->num_subjs = 0;
subjects->subjs = NULL;
还不够吗?

指针是一个应该保存地址的变量。这里的 Subject* 将保存类型为 Subject 的变量的地址。

现在在这里,您首先对其进行了初始化。

您已经分配了一个内存并将其地址分配给 Subject* 变量 subjects

现在让我们看看你还做了什么。

subjects->num_subjs = 0;
subjects->subjs = NULL;

你初始化了它。然后你尝试访问它(subjects->subjs[i])。你能告诉我它指向哪里吗? (subject->subjs)?

答案是否定的。它指向无处。它现在包含 NULL 值。难道你不认为你应该告诉它你想持有多少 subject 并相应地分配?是的,你应该这样做,这正是我在所示示例中所做的。

每当你有一个指针变量时,问问自己它包含什么——如果这个值是你知道的,而不是一些随机的垃圾值。

关于c - 程序不写入文件并在加载时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47559200/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com