我对C非常陌生并且苦苦挣扎。我遍布整个地方,无法找到任何我能理解或符合我疑问的内容。我的任务是创建一个数组,其中包含有关使用结构的6人的详细信息。然后,我必须创建一个菜单系统,允许某人搜索性别,名字,姓氏,出生日期和开始日期。
这是我的.h文件:
#define NAME_LENGTH 50
struct strDate
{
int nDay;
int nMnth;
int nYear;
};
struct strPerson
{
char arcFirstName[NAME_LENGTH];
char arcLastName[NAME_LENGTH];
char cSex;
struct strDate strDOB;
struct strDate strStartDate;
};
这是我的.c文件(为了在这里保持代码最小化,我已经取出了除了一个结构定义之外的所有结构定义。数组的元素1-5与元素0非常相似,只有实际数据不同):
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "Header.h"
/*Function prototypes*/
void Gender(struct strPerson *arPeople[5]);
void FirstName(struct strPerson *arPeople[5]);
void Surname(struct strPerson *arPeople[5]);
void Name(struct strPerson *arPeople[5]);
void YearOfBirth(struct strPerson *arPeople[5]);
void WholeDOB(struct strPerson *arPeople[5]);
void DOB(struct strPerson *arPeople[5]);
void YearOfStart(struct strPerson *arPeople[5]);
int main(void)
{
int nChoice = 1;
struct strPerson arPeople[5];
/*populating structure within array "arPeople"*/
strcpy(arPeople[0].arcFirstName, "David");
strcpy(arPeople[0].arcLastName, "Hodgkiss");
arPeople[0].cSex = 'M';
arPeople[0].strDOB.nDay = 13;
arPeople[0].strDOB.nMnth = 5;
arPeople[0].strDOB.nYear = 1964;
arPeople[0].strStartDate.nDay = 1;
arPeople[0].strStartDate.nMnth = 9;
arPeople[0].strStartDate.nYear = 2001;
while (nChoice != 5)
{
printf("\nPlease enter number relating to search option required...\n");
printf("1 Search by Gender\n");
printf("2 Search by Name\n");
printf("3 Search by Date of Birth\n");
printf("4 Search by Start Date\n");
printf("5 Exit\n\n");
printf("Please enter your choice : ");
scanf("%d", &nChoice);
printf("\n");
switch (nChoice)
{
case 1: Gender(arPeople);
break;
case 2: Name(arPeople);
break;
case 3: DOB(arPeople);
break;
case 4: YearOfStart(arPeople);
break;
case 5: break;
default: printf("Invalid input, please try again : \n\n");
}
}
system("pause");
return 0;
}
void Gender(struct strPerson *arPeople[5])
{
char cSexMF = 'M';
printf("Please enter 'M' to search for male members of staff or 'F' to search for female memebers of staff : \n\n");
scanf("%c \n", &cSexMF);
printf(".... %c ... %c ....\n", cSexMF, arPeople[0].cSex);
}
所以这显然只是按性别搜索...我的问题是:
如何在菜单系统中调用main中的功能?目前我一直收到错误&#34;警告C4047:&#39;功能&#39; :&#39; strPerson **&#39;不同的间接水平来自&#39; strPerson [5]&#39;&#34;。我完全不知道这意味着什么。
假设我已正确地将其传递给函数,那么如何从数组中打印任何内容?我在上面尝试打印arPeople[0].cSex
时,它表示&#34;表达式必须具有结构或联合类型&#34;。我不明白这一点,因为我认为我已将它作为一个结构传递,所以它会知道我所引用的内容。
我非常感谢这方面的一些帮助,我看到了我能想到的所有地方,搜索了我能想到的一切,但我仍然无法使它发挥作用。我已经在这里待了好几天试图解决这个问题,并且如果我的课不及格,我甚至不在乎。
答案 0 :(得分:2)
为什么使用指针数组?而不是:
void Gender(struct strPerson *arPeople[5])
{
char cSexMF = 'M';
printf("Please enter 'M' to search for male members of staff or 'F' to search for female memebers of staff : \n\n");
scanf("%c \n", &cSexMF);
printf(".... %c ... %c ....\n", cSexMF, arPeople[0].cSex);
}
执行此操作(这通常是将数组作为C中的参数传递给函数的方式):
void Gender(struct strPerson arPeople[], int arrLength)
{
// Enter search criteria
char cSexMF = 0;
printf("Please enter 'M' to search for male members of staff or 'F' to search for female memebers of staff : \n\n");
scanf(" %c", &cSexMF);
// Go through array
for(int i = 0; i<arrLength; i++)
{
// Check gender of each element of array against what user entered
if(arPeople[i].cSex == cSexMF)
{
printf(".... %c ... %c .... %s\n", cSexMF, arPeople[i].cSex, arPeople[i].arcFirstName);
}
}
}
这应该打印性别与用户输入的人匹配的姓名和性别;你可以将这种技术应用到你的其他方法中,就像我说我怀疑你需要使用这个结构:struct strPerson *arPeople[5]
,在你的情况下。
答案 1 :(得分:0)
让我们从基础知识开始:在评估表达式时,在C / C ++中,&#34;最大的咀嚼&#34;规则适用,尽可能正确,仍然得到有效的表达,然后向左走。
这是如何适用的?让我们评估您的数据声明
struct strPerson *arPeople[5]
arPeople
arPeople[5]
*arPeople[5]
strPerson *arPeople[5]
现在,回到你的问题:数组被编译器处理为与指针相同;采取以下声明:
int *p0;
int p1[20];
p0和p1都是从编译器的角度来看的指针:p0 [0]和p1 [1]代表第一个元素,p0 ++ / p1 ++增加地址,依此类推。这并不是说指针与数组相同,它们只是对待它们。
当你想传入一个数组作为参数时,下面的函数原型做同样的事情:
void foo(int* p);
void foo(int p[]);
void foo(int p[10]);
编译器将为它们生成完全相同的代码,从它的角度来看,您将地址传递给数据块的开头。
如果你想修改数组struct strPerson arPeople[5]
,那么你的函数原型应该只是:
void Gender(struct strPerson *arPeople);
OR
void Gender(struct strPerson arPeople[]);
出于上述所有原因。
希望这有助于澄清事情......
答案 2 :(得分:0)
除非它是sizeof
或一元&
运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,表达式为类型&#34; T
&#34;的N元素数组;将被转换(&#34;衰减&#34;)到类型为&#34的表达式;指向T
&#34;的指针,并且表达式的值将是第一个元素的地址。阵列。
此外,在函数参数声明的上下文中,T a[]
或T a[N]
形式的声明将被视为T *
。
在函数调用中
Gender(arPeople);
表达式arPeople
是从struct strPerson
&#34;的类型&#34; 5元素数组转换而来的to&#34;指向struct strPerson
&#34;或struct strPerson *
。
因此,您的函数声明和定义需要写成
void Gender( struct strPerson *arPeople )
在您的代码中,您将arPeople
参数声明为指针数组,根据上面的第二条规则将其视为指向指针的指针,这是您的错误所在消息来自。请注意,您可以在指针表达式上使用下标运算符[]
,因此您仍然可以编写类似
printf(".... %c ... %c ....\n", cSexMF, arPeople[0].cSex);
你可以传递一个实际的指向数组的指针,如下所示:
Gender( &arPeople );
因为在这种情况下,表达式arPeople
是一元&
运算符的操作数,所以它不会被转换为指针类型;表达式&arPeople
的类型是&#34;指向struct strPerson
&#34;或struct strPerson (*)[5]
的5元素数组的指针。在这种情况下,您的函数声明和定义需要写为
void Gender( struct strPerson (*arPeople)[5] )
我不建议这样做有两个原因。首先,你的函数只能处理5个元素的数组,这个数组并不是非常灵活(指向5个元素的指针与指向某个数字的指针不兼容 - 不是 - 5元素阵列)。其次,在代码正文中,必须在应用下标之前取消引用指针,如下所示:
printf(".... %c ... %c ....\n", cSexMF, (*arPeople)[0].cSex);
^^^^^^^^^^^
老实说,这会让事情变得混乱。
一些风格笔记:
您不希望传递数组而不传递其大小,因为接收函数只获取指向第一个元素的指针,而不是实际的数组对象。我建议您更改函数以获取其他大小参数:
void Gender( struct strPerson *arPeople, size_t arSize )
并将其命名为
Gender( arPeople, sizeof arPeople / sizeof *arPeople );
这样,您的Gender
函数就知道数组中有多少元素。
其次,为了便于维护,您可以在main
函数之前定义函数,如下所示:
void Gender( struct strPerson *arPeople, size_t arSize )
{
// code for Gender function
}
void Surname( struct strPerson *arPeople, size_t arSize )
{
// code for Surname function
}
...
int main( void )
{
// code for main function
}
这样您就不必担心保持函数声明和定义同步。它确实让你的代码被读取&#34;向后&#34;但是相信我,从维护的角度来看,这会使事情变得更加简单。