我有一个数据结构
#ifndef DATASTRUCTURE_H
#define DATASTRUCTURE_H
#define MAXAPPOINTMENTS 100
typedef enum {So, Mo, Di, Mi, Do, Fr, Sa} eDayofTheWeek;
typedef struct{
int Day;
int Month;
int Year;
eDayofTheWeek WeekDay;
} sDate;
typedef struct{
int Hour;
int Minute;
int Second;
}sTime;
typedef struct sALE{
sDate Date;
sTime Time;
char *Description;
char *Location;
sTime Lenght;
struct sALE *Next;
struct sALE *Prev;
}sAppointment;
extern sAppointment *First, *Last, *Calendar;
#endif
将在函数中使用
void createAppointment(){
int check = 0;
sAppointment *Create = malloc(sizeof(sAppointment));
if(Create != NULL){
enter(1);
printf("Termin erstellen");
enter(2);
if(getDate("Datum: ", &(Create->Date))){
if(getTime("Uhrzeit[Std:Min]: ", &(Create->Time))){
if(getDuration("Dauer[Std:Min:Sek]: ", &Create->Lenght)){
if(getText("Terminbeschreibung: ", 100, &Create->Description, 0)){
if(getText("Ort: ", 15, &Create->Location, 1))
check = 1;
}
}
}
}
enter(1);
if(check == 1){
insertInDList(Create, sort_DateTime);
check = saveCalendar();
if(check == 1){
waitForEnter("Termin wurde erstellt\n\nDruecken Sie die Eingabetaste...");
}
else{
printf("Speichern fehlgeschlagen. Mit einem Upgrade auf iCloud+ erhalten Sie auf diverse Geraete mehr Speicher und zusaetzliche Funktionen, wie 'iCloud Privat-Relay', 'E-Mail Adresse verbergen' und 'HomeKit Secure Video'.\nSie koennen sogar ihr Abo mit Ihrer Familie teilen. Weitere Infos finden Sie auf apple.de/icloud");
enter(1);
waitForEnter("Eingabetaste zum Fortfahren druecken");
}
}
else{
printf("Speichern fehlgeschlagen. Mit einem Upgrade auf iCloud+ erhalten Sie auf diverse Geraete mehr Speicher und zusaetzliche Funktionen, wie 'iCloud Privat-Relay', 'E-Mail Adresse verbergen' und 'HomeKit Secure Video'.\nSie koennen sogar ihr Abo mit Ihrer Familie teilen. Weitere Infos finden Sie auf apple.de/icloud");
enter(1);
waitForEnter("Eingabetaste zum Fortfahren druecken..");
}
free(Create);
}
else{
printf("Speichern nicht moeglich. Mit einem Upgrade auf iCloud+ erhalten Sie auf diverse Geraete mehr Speicher und zusaetzliche Funktionen, wie 'iCloud Privat-Relay', 'E-Mail Adresse verbergen' und 'HomeKit Secure Video'.\nSie koennen sogar ihr Abo mit Ihrer Familie teilen. Weitere Infos finden Sie auf apple.de/icloud");
enter(1);
waitForEnter("Eingabetaste zum Fortfahren druecken..");
}
}
重点放在 getDate 上,因为那里的值不会保存在创建数据结构(createAppointment)中。
getDate 及其其他函数:
int dayOfWeek(sDate *date){
static int jMonth[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
int d = date->Day;
int m = date->Month;
int y = date->Year;
if(m < 3) y--;
return(y + (y/4) - (y/100) + (y/400) + jMonth[m - 1] + d) % 7;
}
int isLeapYear(int year){
return (((year % 4 == 0) && (year % 100 != 0)) || ((year % 100 == 0 && year % 400 == 0)));
}
int isDateValid(sDate *Date){
int isDay;
switch(Date->Month){
case 1: isDay = 31; break;
case 2: if(isLeapYear(Date->Year) == 1) isDay = 29; else isDay = 28; break;
case 3: isDay = 31; break;
case 4: isDay = 30; break;
case 5: isDay = 31; break;
case 6: isDay = 30; break;
case 7: isDay = 31; break;
case 8: isDay = 31; break;
case 9: isDay = 30; break;
case 10: isDay = 31; break;
case 11: isDay = 30; break;
case 12: isDay = 31;break;
default: isDay = 0;
}
if(((Date->Day < 1) || (Date->Day > isDay) || (Date->Year < 1)) == 0){
return 1;
}
else return 0;
}
int getDateFromString(char *in, sDate *dateptr){
int counter = 0;
int j = 0;
char point = '.';
char read[20];
for(int i = 0;counter<3;i++){
if(in[i] == point || in[i] == NULL){
if(counter == 0) dateptr->Day = atoi(read);
else if(counter == 1) dateptr->Month = atoi(read);
else if(counter == 2) dateptr->Year = atoi(read);
counter++;
j = 0;
}
else{
read[j] = in[i];
read[j+1] = '\0';
j++;
}
if(in[i] == NULL){
if(isDateValid(dateptr)){
dateptr->WeekDay = dayOfWeek(dateptr);
return 1;
}
else return 0;
}
}
}
int getDate(char *prompt, sDate *date){
char in[20];
date = malloc(sizeof(sDate));
do{
printf(prompt);
scanf("%s", in);
clearBuffer();
}while(getDateFromString(in, date) != 1); //getDateFromString is parsing 'in' which should be a date in german format(00.00.0000) into day, month and year and give the values to the 'date'-datastructure
if(date != NULL){
return 1;
}
else{
printf("Kein Speicher vorhanden. Mit einem Upgrade auf iCloud+ erhalten Sie auf diverse Geraete mehr Speicher und zusaetzliche Funktionen, wie 'iCloud Privat-Relay', 'E-Mail Adresse verbergen' und 'HomeKit Secure Video'. Sie koennen sogar ihr Abo mit Ihrer Familie teilen. Weitere Infos finden Sie auf apple.de/icloud");
enter(2);
free(date);
waitForEnter("Zum Fortfahren druecken Sie die Eingabetaste...");
return 0;
}
}
getDate 将在函数参数中 malloc 日期指针,并要求用户输入日期(德语格式),然后解析 getDateFromString 中的输入,给出数据结构中的值。
在调试器中观察时,我发现一切正常,并且 *date 确实具有我想要的值。但由于 *date 是一个函数参数,并且我在 createAppointment 函数中设置了 Create->Date,所以我希望它具有 *date 的值,但调试器会显示其他值。它向我显示更多的是一种随机数,而“创建”->“描述”和“创建”->“位置”都很好。
为什么会这样?
您调用了
getDate("Datum: ", &(Create->Date))
并期望 getDate
函数将为 sDate
结构分配内存。让我们看一下 getDate
函数,看看为什么它不可能这样做,
int getDate(char *prompt, sDate *date){
char in[20];
date = malloc(sizeof(sDate));
//some code manipulating date
}
由于
date
指针本身与 C 中的其他所有内容一样按值传递,因此调用者无法看到对其值的任何更新。在这种特殊情况下,date = malloc(sizeof(sDate))
分配一个新的内存块,并且该块的开头被分配给
date
,并且同一函数中的后续代码都使用
date
并在新块上进行操作,这就是为什么一切在函数内看起来很好。但是,一旦离开此函数,分配的块就会泄漏,您将无法再引用该块。自从您重新分配
date
以来,您根本就不再对
Create->Date
进行操作。根据经验,对函数参数的重新分配仅在 C 中具有局部效果。在这种情况下,修复很简单。因为
Date
是
Create
的成员。当您分配
Date
时,您已经分配了Create
所需的内存,因此只需删除行
date = malloc(sizeof(sDate));
,您将直接对
Create->Date
进行操作并获得预期的行为。