【问题标题】:Passing an array of structs as arguments of a function将结构数组作为函数的参数传递
【发布时间】:2020-11-26 13:17:45
【问题描述】:

我正在尝试将结构数组作为参数传递给函数并更改其自身的结构的值。代码的目的是建立一个议程。这个特定的函数void newEvent(); 应该按照它所说的去做:添加一个新事件(新结构)。代码如下:

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

#define MAX_LENGTH 100
#define N 12
#define HOURS 24
#define MINUTES 60

typedef struct appointment Appointment;

struct appointment {

    short int day;
    short int month;
    short int time[HOURS][MINUTES];
    char description[MAX_LENGTH];

};

Appointment meeting[N];

void newEvent (Appointment *meeting, int i, int event) {


    short int startingHour = 0, startingMinute = 0, endingHour = 0, endingMinute = 0;
    int j, z, flag = 0;

        printf("Enter a description of the appointment (max 100 characters): \n");
        fgets(meeting[i].description, MAX_LENGTH, stdin);

        printf("Date of the appointment (dd/mm): ");
        scanf("%hd/%hd", &meeting[i].day, &meeting[i].month);
        fflush(stdin);


    do {
        do {
            do {
                printf("Starts (hh:mm): ");
                scanf("%hd:%hd", &startingHour, &startingMinute);
                fflush(stdin);

                printf("Ends (hh:mm): ");
                scanf("%hd:%hd", &endingHour, &endingMinute);
                fflush(stdin);
            } while(startingHour > endingHour);
        } while((startingHour < 0 || startingHour > 23) || (endingHour < 0 || endingHour > 23) || (startingMinute < 0 || startingMinute > 59) || (endingMinute < 0 || endingMinute > 59));

        for (j = startingHour; j <= endingHour; j++) {
            for( z = startingMinute; z < MINUTES && flag == 0; z++) {
                if (j < endingHour) {
                    meeting[i].time[j][z] = 1;
                }
                if ((z > 0) && (z % (MINUTES - 1)) == 0) {
                    j++;
                    z = 0;
                }
                if (j == endingHour && z < endingMinute) {
                    meeting[i].time[j][z] = 1;
                }
                if ((j == endingHour) && (z == endingMinute)) {
                    flag = 1;
                }
            }
        }

        flag = 0;

        printf("\n");

        for(int a = 0; a < event; a++) {
            if((meeting[i].day == meeting[a].day) && (meeting[i].month == meeting[a].month)) {
                for (j = 0; j < HOURS; j++) {
                    for( z = 0; z < MINUTES; z++) {
                        if((meeting[i].time[j][z] == meeting[a].time[j][z]) && meeting[i].time[j][z] == 1) {
                            flag = 1;
                        }
                    }
                }
            }
        }
    } while(flag != 0);

    event++;
    flag = 0;


}






int main() {

    int ctrl = 0, event = 0, i, flag = 0, erase = 0;


    for(i = 0; i < N; i++) {
        for(int j = 0; j < HOURS; j++) {
            for(int z = 0; z < MINUTES; z++) {
                meeting[i].time[j][z] = 0;
            }
        }
    }

    do {
        system("cls");
        printf("1) Add an appointment\n");
        printf("2) Delete an appointment\n");
        printf("3) print month appointment\n");
        printf("4) Leave\n");

        printf("\nYour choice: ");
        scanf("%d", &ctrl);
        fflush(stdin);
        system("cls");

        switch (ctrl) {

        case 1:

            for (i = event; i < (event + 1); i++){
                newEvent(meeting, i, event);
            }

            system("PAUSE");
            break;

        case 2:
            printf("*** DELETING AN EVENT ***\n");
            printf("-------------------------\n");

            printf("Here down below is your agenda: \n");

            flag = 0;

            for(int i = 0; i < event; i++) {
                printf("Event n. %d description: \n%s\n", i + 1, meeting[i].description);
                printf("Date: %hd/%hd\n", meeting[i].day, meeting[i].month);
                for(int j = 0; j < HOURS; j++) {
                    for (int z = 0; z < MINUTES && flag == 0; z++) {
                        if(meeting[i].time[j][z] == 1) {
                            printf("Starts: %d:%d\n", j, z);
                            flag = 1;
                        }
                    }
                }

                flag = 0;

                for(int j = HOURS; j > 0; j--) {
                    for (int z = MINUTES; z >= 0 && flag == 0; z--) {
                        if(meeting[i].time[j][z] == 1) {
                            printf("Ends: %d:%d\n", j, z);
                            flag = 1;
                        }
                    }
                }

                flag = 0;

                printf("-------------------------------\n");
                printf("\n\n");
            }

            printf("Which event you would like to erase? \n");
            scanf("%d", &erase);

            for (int i = (erase - 1); i < event; i++) {
                meeting[i] = meeting[i+1];
                event--;
            }

            flag = 0;

            printf("Here down below your updated agenda: \n");

            for(int i = 0; i < event; i++) {
                printf("Event n. %d description: \n%s\n", i + 1, meeting[i].description);
                printf("Date: %hd/%hd\n", meeting[i].day, meeting[i].month);
                for(int j = 0; j < HOURS; j++) {
                    for (int z = 0; z < MINUTES && flag == 0; z++) {
                        if(meeting[i].time[j][z] == 1) {
                            printf("Starts: %d:%d\n", j, z);
                            flag = 1;
                        }
                    }
                }

                flag = 0;

                for(int j = HOURS; j > 0; j--) {
                    for (int z = MINUTES; z >= 0 && flag == 0; z--) {
                        if(meeting[i].time[j][z] == 1) {
                            printf("Ends: %d:%d\n", j, z);
                            flag = 1;
                        }
                    }
                }

                flag = 0;

                printf("-------------------------------\n");
                printf("\n\n");
            }

            system("PAUSE");
            break;

        case 3:

            printf("*** SHOWING ALL YOUR EVENTS ***\n");
            printf("-------------------------------\n");

            if(event == 0){
                printf("Nothing to show here :( \n");
            }

            flag = 0;

            for(int i = 0; i < event; i++) {
                printf("Event n. %d description: \n%s\n", i + 1, meeting[i].description);
                printf("Date: %hd/%hd\n", meeting[i].day, meeting[i].month);
                for(int j = 0; j < HOURS; j++) {
                    for (int z = 0; z < MINUTES && flag == 0; z++) {
                        if(meeting[i].time[j][z] == 1) {
                            printf("Starts: %d:%d\n", j, z);
                            flag = 1;
                        }
                    }
                }

                flag = 0;

                for(int j = HOURS; j > 0; j--) {
                    for (int z = MINUTES; z >= 0 && flag == 0; z--) {
                        if(meeting[i].time[j][z] == 1) {
                            printf("Ends: %d:%d\n", j, z);
                            flag = 1;
                        }
                    }
                }

                flag = 0;

                printf("-------------------------------\n");
                printf("\n\n");
            }


            system("PAUSE");
            break;
        }
    } while(ctrl != 4);


    return 0;
}

不幸的是,我收到了一条警告,上面写着warning: passing argument 1 of 'newEvent' from incompatible pointer type [-Wincompatible-pointer-types]

PS:我放在这里的代码有点简化(您可以从... 看到它),但我认为足以让人们比我更好地使用 C 进行编码了解问题出在哪里。

【问题讨论】:

  • 如果newEvent 只需要与一个会议合作,并且为该会议分配了空间(现有结构,可以是结构数组的元素),那么只需将其设置为参数Appointment *meeting。表达式&amp;meeting[i] 是单个结构的地址meeting[i],所以它是一个Appointment *。您不需要**,除非您不仅要传递事物的地址,还要传递指向事物的指针的地址。
  • 我想改变结构本身的实际参数,所以我的想法是传递结构数组的地址,传递指向每个结构的指针的地址。
  • 重新“传递指向每个结构的指针的地址”:数组不是指针。在Appointment meeting[N]; 之后,meeting 是指定数组的标识符。它不是指向数组的指针,也不是指向数组第一个元素的指针。 &amp;meeting 不是指针的地址;它是数组的地址。当在表达式中使用不是sizeof 或一元&amp; 的操作数时,meeting 将被转换为指向其第一个元素的指针,但它本身并不是这样的指针。传递&amp;meeting 不会传递Appointment **。
  • Re“我想改变结构本身的实际参数”:结构没有参数。他们有成员。要使函数能够修改结构(包括其成员),只需传递结构的地址。 meeting 是一个结构数组。 meeting[i] 是一种结构。 &amp;meeting[i] 是一个结构的地址。更改meeting[i]。所有newEvent 需要的是&amp;meeting[i]。它不需要meeting 和i。
  • 但是如果我只将&amp;meeting[i] 传递给函数,则无法引用函数内部数组的每个结构

标签: arrays c function pointers


【解决方案1】:

当您传递一个数组时,您不是按值传递,一个简单的可视化方法是考虑scanf("%d", &amp;var) 与scanf("%s", var)。当您传递结构数组时,因为它只是一个数组,所以您不是按值传递:

所以,这个

void newEvent (Appointment **meeting, int i, int event)

变成

void newEvent (Appointment *meeting, int i, int event) 或者这个 void newEvent (Appointment meeting[], int i, int event) 任何你喜欢的可读性。

还有这个

newEvent(&amp;meeting[i], i, event);

变成

newEvent(meeting, i, event);

这是我用来测试的代码:

#include <stdio.h>

#define N 100
#define MAX_LENGTH 100

typedef struct appointment Appointment;

struct appointment {
     /*short int day;
     short int month;
     short int time[HOURS][MINUTES];*/
     char description[MAX_LENGTH];
};

void newEvent (Appointment *meeting, int i, int event) {

     printf("Enter a description of the appointment (max 100 characters): \n");
     fgets(meeting[i].description, MAX_LENGTH, stdin);
}

int main() {
    Appointment meeting[N];
    int event = 0;
    for (int i = 0; i < (event + 1); i++){
        newEvent(meeting, i, event);
    }
    printf("%s\n", meeting[0].description);
    
    return 0;

}

你的第一个问题是这样的:

printf("\nYour choice: ");
scanf("%d", &ctrl);
fflush(stdin);

您无法刷新stdin,因此在您将int 读入ctrl 后,您将在stdin 上留下\n,生成的对fgets 的调用会收到\n 并继续.所以做这样的事情来让\n脱离标准输入。

char buf[10];
printf("\nYour choice: ");
fflush(stdout); /* always flush stdout if no newline */
fgets(buf, 10, stdin);
ctrl = atoi(buf);

我没有完成其余的代码,但您所做的是将留在stdin 上的\n 存储到meeting[i].description

【讨论】:

  • 我尝试过这样做,但似乎结构没有改变。你知道为什么吗?
  • 我将编辑我的答案以包含我用来测试的代码,请记住 fgets 捕获新行。
  • 我不知道为什么,但我的程序没有将任何内容保存到结构的字段中。这个printf("%s\n", meeting[0].description); 会给我任何东西
  • 将我粘贴到问题中的代码复制到一个新文件中,复制并运行它,并分享您的错误。
  • 现在它可以工作了,但我已经尝试使用我自己的整个代码,当尝试将所有结构打印到数组中时,它不会显示任何内容。如果你愿意,我可以在这里粘贴代码。
【解决方案2】:

这取决于你想做什么。根据您的问题,您想要传递结构数组,所以您想要做的是:newEvent(meeting, i, event); 和void newEvent (Appointment *meeting, int i, int event);。像这样,您可以按照自己的意愿分别传递整个数组和索引。

【讨论】:

  • 正如我之前所说,我的目的是更改结构本身的实际参数,所以我的想法是通过在称为会议的结构上传递指针的地址来传递结构数组的地址
【解决方案3】:

首先,我认为您应该 malloc 您的约会数组。像这样:

Appointment* meeting = (Appointment*)malloc(N * sizeof(Appointment));

现在您的数组将在内存中而不是在堆栈中。 (完成后不要忘记free(meeting))。我真的不明白int i 应该在void newEvent 中是什么,但你要么给newEvent 整个数组,要么只给一个元素meetings[i]。

如果你给出整个数组,你应该这样做:

void newEvent(Appointment* meetings, int i){
  //for example
  char* descrip = "...";
  strcpy(meetings[i].description, descrip);
  meetings[i].day = 15;
}
//to call the function:
newEvent(meetings, the meeting u want to change);

如果你只给函数一个元素,你应该这样做:

void newEvent(Appointment* meetings){
  //for example
  char* descrip = "...";
  strcpy(meetings->description, descrip);
  meetings->day = 15;
}
//to call it
newEvent(&meetings[the meeting u want to change]);

在所有情况下,如果您想初始化所有这些,请执行以下操作:

for (int i = 0; i < events; i++){
  newEvent(meetings, i);
  //or
  newEvent(&meetings[i]);
}

【讨论】:

  • 非常感谢,我会试试这个,看看会发生什么
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-22
  • 1970-01-01
  • 2018-09-17
  • 1970-01-01
相关资源
最近更新 更多