当被调用函数用局部于main函数内的变量作为参数时。出现了问题。因为被调用函数的作用是改变参数的值,所以考虑用指针作为参数。但是struct part q【】(之前是外部变量)是一个存放结构的数组。(结构包含商品的编号,名称,数量三项元素)所以,指向数组元素(结构)的指针怎么声明?当我想要逐项添加或修改结构的三个内容时,又改怎么写?以下是“插入商品”的函数。
void insert(struct part *q,int n)//两个参数是被要求局部于main函数中的外部变量
{
int i=0,part_number;
if(n==MAX_PARTS){
printf("Database is full;can't add more parts.\n");
return;
}
printf("Enter part number:");
scanf("%d",&part_number);
if(find_part(part_number,q,n)>=0){
printf("Part already exists.\n");
return;
}
*q.number=part_number;
printf("Enter part name:");
read_line(*q.name,NAME_LEN);
printf("Enter quantity on hand:");
scanf("%d",*q.on_hand);
n++;
}
*q.number和q[n].number的写法都不对。
#include
typedef struct
{
int x;
} *A;
void foo(A* a)
{
printf("%d", a[0]->x);
}
int main()
{
A a[2];
a[0]->x = 123;
foo(a);
}
q[n]->number
lz能不能不要胡乱采纳,昨天莫名其妙就采纳给一个瞎灌水的
#include <stdio.h>
typedef struct
{
int x;
} *A;
void foo(A* a)
{
printf("%d", a[0]->x);
}
int main()
{
A a[2];
a[0]->x = 123;
foo(a);
}
123
https://c.runoob.com/compile/11 在线验证。
(1)用结构体变量名作为参数。
复制代码 代码如下:
#include
#include
using namespace std;
struct Student{
string name;
int score;
};
int main(){
Student one;
void Print(Student one);
one.name="千手";
one.score=99;
Print(one);
cout<<one.name<<endl;
cout<<one.score<<endl;//验证 score的值是否加一了
return 0;
}
void Print(Student one){
cout<<one.name<<endl;
cout<<++one.score<<endl;//在Print函数中,对score进行加一
}
这种方式值采取的“值传递”的方式,将结构体变量所占的内存单元的内存全部顺序传递给形参。在函数调用期间形参也要占用内存单元。这种传递方式在空间和实践上开销较大,如果结构体的规模很大时,开销是很客观的。
并且,由于采用值传递的方式,如果在函数被执行期间改变了形参的值,该值不能反映到主调函数中的对应的实参,这往往不能满足使用要求。因此一般较少使用这种方法。
(2)用指向结构体变量的指针作为函数参数
复制代码 代码如下:
#include
#include
using namespace std;
struct Student{
string name;
int score;
};
int main(){
Student one;
void Print(Student *p);
one.name="千手";
one.score=99;
Student *p=&one;
Print(p);
cout< cout return 0;
}
void Print(Student *p){
coutname< coutscore<<endl;//在Print函数中,对score进行加一
}
这种方式虽然也是值传递的方式,但是这次传递的值却是指针。通过改变指针指向的结构体变量的值,可以间接改变实参的值。并且,在调用函数期间,仅仅建立了一个指针变量,大大的减小了系统的开销。
(3)用接头体变量的引用变量作函数参数
复制代码 代码如下:
#include
#include
using namespace std;
struct Student{
string name;
int score;
};
int main(){
Student one;
void Print(Student &one);
one.name="千手";
one.score=99;
Print(one);
cout<<one.name<<endl;
cout<<one.score<<endl;//验证 score的值是否加一了
return 0;
}
void Print(Student &one){
cout<<one.name<<endl;
cout<<++one.score<<endl;//在Print函数中,对score进行加一
}
// 员工信息结构体
typedef struct
{
INT8 szEmployeeName[100]; // 员工姓名
UINT16 iEmployeeAge; // 员工年龄
UINT32 iEmployeeNo; // 员工工号
} TEmployeeInfo;
函数GetEmployeeInfo用来对员工信息字段进行赋值,其声明如下:
INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo);
在主函数main中,采用两种参数传递的方法,一种是指针传递,另一种是非指针传递。
二、采用指针传递时的程序代码
采用指针传递时的程序代码如下:
/**********************************************************************
*
文件名称: TestStruct.c
文件标识:无
内容摘要:用于演示结构体变量的用法
其它说明:无
当前版本: V1.0
作 者:周兆熊
完成日期: 20140617
*
修改记录1:// 修改历史记录, 包括修改日期、版本号、修改人及修改内容
修改日期: 20140617
版本号: V1.0
修改人: Zhou Zhaoxiong
修改内容:创建
**********************************************************************/
#include
#include
// 数据类型
typedef signed char INT8;
typedef unsigned char UINT16;
typedef unsigned int UINT32;
typedef signed int INT32;
// 员工信息结构体
typedef struct
{
INT8 szEmployeeName[100]; // 员工姓名
UINT16 iEmployeeAge; // 员工年龄
UINT32 iEmployeeNo; // 员工工号
} TEmployeeInfo;
// 函数声明
INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo); // 获取员工信息函数
INT32 main(void);
/****************************************************************
功能描述: 主函数
输入参数: 无
输出参数: 无
返回值: 0-执行成功 -1-执行失败
其他说明: 无
修改日期 版本号 修改人 修改内容
20140617 V1.0 Zhou Zhaoxiong 创建
****************************************************************/
INT32 main(void)
{
INT32 iRetValue = 0; // 该变量用于表示调用GetEmployeeInfo函数返回的值
TEmployeeInfo *ptEmployeeInfo = NULL; // 该变量用于存放员工信息
// 调用函数对员工信息字段赋值, 并打印出来
iRetValue = GetEmployeeInfo(ptEmployeeInfo);
if (iRetValue != 0)
{
printf("exec GetEmployeeInfo failed.\n");
return -1;
}
printf("员工信息为: \n姓名: %s\n年龄: %d\n工号: %d\n", ptEmployeeInfo->szEmployeeName, ptEmployeeInfo->iEmployeeAge, ptEmployeeInfo->iEmployeeNo);
return 0;
}
/**********************************************************************
功能描述:对员工信息字段赋值
输入参数: ptEmployeeInfo: 员工信息结构体
输出参数: ptEmployeeInfo: 员工信息结构体
返回值: 0-成功 -1-失败
其它说明:无
修改日期 版本号 修改人 修改内容
20140617 V1.0 Zhou Zhaoxiong 创建
***********************************************************************/
INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo)
{
// 先对输入的指针参数进行异常判断
if (ptEmployeeInfo == NULL)
{
printf("Input parameter is NULL.\n");
return -1;
}
strncpy((char *)ptEmployeeInfo->szEmployeeName, "Li Yuanfang", strlen("Li Yuanfang")); // 对姓名字段赋值
ptEmployeeInfo->iEmployeeAge = 100; // 对年龄字段赋值
ptEmployeeInfo->iEmployeeNo = 123456; // 对工号字段赋值
return 0; // 赋值成功, 返回0
}
程序的运行结果如图1所示:
图1 采用指针传递时的程序代码运行结果
从图1可以看出,函数GetEmployeeInfo的入参为空,不能实现赋值的功能。
三、改进后的采用指针传递时的程序代码
既然程序打印出指针为空的信息,那么我们先对传入的指针进行赋值操作是不是就可以了呢?
改进后的采用指针传递时的程序代码如下:
/**********************************************************************
*
文件名称: TestStruct.c
文件标识:无
内容摘要:用于演示结构体变量的用法
其它说明:无
当前版本: V1.0
作 者:周兆熊
完成日期: 20140617
*
修改记录1:// 修改历史记录, 包括修改日期、版本号、修改人及修改内容
修改日期: 20140617
版本号: V1.0
修改人: Zhou Zhaoxiong
修改内容:创建
**********************************************************************/
#include
#include
// 数据类型
typedef signed char INT8;
typedef unsigned char UINT16;
typedef unsigned int UINT32;
typedef signed int INT32;
// 员工信息结构体
typedef struct
{
INT8 szEmployeeName[100]; // 员工姓名
UINT16 iEmployeeAge; // 员工年龄
UINT32 iEmployeeNo; // 员工工号
} TEmployeeInfo;
// 函数声明
INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo); // 获取员工信息函数
INT32 main(void);
/****************************************************************
功能描述: 主函数
输入参数: 无
输出参数: 无
返回值: 0-执行成功 -1-执行失败
其他说明: 无
修改日期 版本号 修改人 修改内容
20140617 V1.0 Zhou Zhaoxiong 创建
****************************************************************/
INT32 main(void)
{
INT32 iRetValue = 0; // 该变量用于表示调用GetEmployeeInfo函数返回的值
TEmployeeInfo *ptEmployeeInfo = NULL; // 该变量用于存放员工信息
// 先对员工信息字段赋值, 防止空指针的存在
strncpy((char *)ptEmployeeInfo->szEmployeeName, "Di Renjie", strlen("Di Renjie")); // 对姓名字段赋值
ptEmployeeInfo->iEmployeeAge = 150; // 对年龄字段赋值
ptEmployeeInfo->iEmployeeNo = 654321; // 对工号字段赋值
// 调用函数对员工信息字段赋值, 并打印出来
iRetValue = GetEmployeeInfo(ptEmployeeInfo);
if (iRetValue != 0)
{
printf("exec GetEmployeeInfo failed.\n");
return -1;
}
printf("员工信息为: \n姓名: %s\n年龄: %d\n工号: %d\n", ptEmployeeInfo->szEmployeeName, ptEmployeeInfo->iEmployeeAge, ptEmployeeInfo->iEmployeeNo);
return 0;
}
/**********************************************************************
功能描述:对员工信息字段赋值
输入参数: ptEmployeeInfo: 员工信息结构体
输出参数: ptEmployeeInfo: 员工信息结构体
返回值: 0-成功 -1-失败
其它说明:无
修改日期 版本号 修改人 修改内容
20140617 V1.0 Zhou Zhaoxiong 创建
***********************************************************************/
INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo)
{
// 先对输入的指针参数进行异常判断
if (ptEmployeeInfo == NULL)
{
printf("Input parameter is NULL.\n");
return -1;
}
strncpy((char *)ptEmployeeInfo->szEmployeeName, "Li Yuanfang", strlen("Li Yuanfang")); // 对姓名字段赋值
ptEmployeeInfo->iEmployeeAge = 100; // 对年龄字段赋值
ptEmployeeInfo->iEmployeeNo = 123456; // 对工号字段赋值
return 0; // 赋值成功, 返回0
}
程序的运行结果如图2所示:
图2 改进后的采用指针传递时的程序代码运行结果
可见,程序出现了内存问题。原因是在传递之前,ptEmployeeInfo指针已经指向了确定的地址,不能让同一个指针同时指向不同的地址。
四、第二次改进后的程序代码
既然不能用指针作为参数进行传递,那么我们就要考虑另外的方法。
以下代码采用非指针的传递方式:
/**********************************************************************
*
文件名称: TestStruct.c
文件标识:无
内容摘要:用于演示结构体变量的用法
其它说明:无
当前版本: V1.0
作 者:周兆熊
完成日期: 20140617
*
修改记录1:// 修改历史记录, 包括修改日期、版本号、修改人及修改内容
修改日期: 20140617
版本号: V1.0
修改人: Zhou Zhaoxiong
修改内容:创建
**********************************************************************/
#include
#include
// 数据类型
typedef signed char INT8;
typedef unsigned char UINT16;
typedef unsigned int UINT32;
typedef signed int INT32;
// 员工信息结构体
typedef struct
{
INT8 szEmployeeName[100]; // 员工姓名
UINT16 iEmployeeAge; // 员工年龄
UINT32 iEmployeeNo; // 员工工号
} TEmployeeInfo;
// 函数声明
INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo); // 获取员工信息函数
INT32 main(void);
/****************************************************************
功能描述: 主函数
输入参数: 无
输出参数: 无
返回值: 0-执行成功 -1-执行失败
其他说明: 无
修改日期 版本号 修改人 修改内容
20140617 V1.0 Zhou Zhaoxiong 创建
****************************************************************/
INT32 main(void)
{
INT32 iRetValue = 0; // 该变量用于表示调用GetEmployeeInfo函数返回的值
TEmployeeInfo tEmployeeInfo = {0}; // 该变量用于存放员工信息
// 调用函数对员工信息字段赋值, 并打印出来
iRetValue = GetEmployeeInfo(&tEmployeeInfo);
if (iRetValue != 0)
{
printf("exec GetEmployeeInfo failed.\n");
return -1;
}
printf("员工信息为: \n姓名: %s\n年龄: %d\n工号: %d\n", tEmployeeInfo.szEmployeeName, tEmployeeInfo.iEmployeeAge, tEmployeeInfo.iEmployeeNo);
return 0;
}
/**********************************************************************
功能描述:对员工信息字段赋值
输入参数: ptEmployeeInfo: 员工信息结构体
输出参数: ptEmployeeInfo: 员工信息结构体
返回值: 0-成功 -1-失败
其它说明:无
修改日期 版本号 修改人 修改内容
20140617 V1.0 Zhou Zhaoxiong 创建
***********************************************************************/
INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo)
{
// 先对输入的指针参数进行异常判断
if (ptEmployeeInfo == NULL)
{
printf("Input parameter is NULL.\n");
return -1;
}
strncpy((char *)ptEmployeeInfo->szEmployeeName, "Li Yuanfang", strlen("Li Yuanfang")); // 对姓名字段赋值
ptEmployeeInfo->iEmployeeAge = 100; // 对年龄字段赋值
ptEmployeeInfo->iEmployeeNo = 123456; // 对工号字段赋值
return 0; // 赋值成功, 返回0
}
程序的执行结果如图3所示:
图3第二次改进后的程序代码执行结果
从图3可以看出,程序执行结果正确,得到了我们想要的结果。
五、总结
在编写代码的过程中,我们需要注意以下方面:
(1) 程序头部、函数头部及重要的程序语句处一定要有注释,这体现了软件开发人员的专业素养。
(2) 函数中出现的变量在定义的同时要进行初始化,函数在调用之前一定要先进行声明。
(3) 对于函数中的指针变量参数,在使用之前一定要先进行异常判断(即判断其是否为NULL)。
(4) 对于有返回值的函数,要用不同的返回值来区别不同的执行结果,并在重要的地方打印出提示信息,方便对代码的调试。
指针是C语言的精华所在,同时也是难点所在。对于一个合格的软件开发工程师来说,一定要熟练掌握指针的使用方法。
C语言 结构体作为函数的参数
1)使用结构体变量作为函数的参数
使用结构体变量作为函数的实参时,采用的是值传递,会将结构体变量所占内存单元的内容全部顺序传递给形参,形参必须是同类型的结构体变量
demo:
复制代码
1 # include
2 # include
3
4 //创建一个Student结构
5 struct Student
6 {
7 char name[30];
8 float fScore[3];
9 }student={"dire",98.5,89.0,93.5}; //初始化结构体变量
10
11 void Display(struct Student su) //形参为同类型的结构体(Student结构)
12 {
13 printf("-----Information------\n");
14 printf("Name:%s",su.name);
15 printf("Chinese:%.2f\n",su.fScore[0]);
16 printf("Math:%.2f\n",su.fScore[1]);
17 printf("English:%.2f",su.fScore[2]);
18 printf("平均分数为:%.2f\n",(su.fScore[0]+su.fScore[1],su.fScore[2])/3);
19 }
20
21 int main ()
22 {
23
24 Display(student);
25
26 return 0;
27 }
复制代码
Printf:
2)使用指向结构体变量的指针作为函数参数
Demo:
复制代码
1 # include
2 # include
3
4 struct Student {
5 char name[20];
6 float fScore[3];
7 }student = {"dire",98.5,89.0,93.5}; //初始化结构体变量
8
9
10 void Display(struct Student *pStruct)
11 {
12 printf("------Information-------\n");
13 printf("Name:%s\n",pStruct->name);
14 printf("Chinese:%.2f\n",(*pStruct).fScore[0]);
15 printf("Math:%.2f\n",(*pStruct).fScore[1]);
16 printf("English:%.2f\n",pStruct->fScore[2]);
17 }
18
19
20 int main ()
21 {
22 Display(&student); //将结构体变量的首地址作为实参传入pStruct指针变量中
23
24 return 0;
25 }
复制代码
3)使用结构体变量的成员作为函数参数
这种方式为函数传递参数与普通的变量作为实参是一样的,是值传递
C语言用结构体指针作函数参数
这种方式比用结构体变量作函数参数效率高,因为无需传递各个成员的值,只需传递一个地址,且函数中的结构体成员并不占据新的内存单元,而与主调函数中的成员共享存储单元。这种方式还可通过修改形参所指成员影响实参所对应的成员值。
例如
struct book
{
char bookname[30];
int quantity;
};
main()
{
void fun(struct book*p);
struct book book1={"Programming in C",10};
fun(&book1);
printf("%d copies\n", book1.quantity);
}
void fun(struct book*p)
{
printf("The book \" %s\" has ",p->bookname);
p->quantity -=3;
}
显示:The book "Programming in C" has 7 copies
此外,还可将结构体数组作为函数参数;还可设计结构体指针型函数,即返回的地址是指向结构体类型数据的。
struct dangdangtest
{
char name[30];
int num;
};
void change(int num)//值传递 新建一个变量接受传递的值
{
num = 1000;
}
//使用结构体作为参数 浪费内存 需要建立结构体
void change2(struct dangdangtest ddt)
{
ddt.num = 1000;
printf("\nmain=%p,%p",ddt,&ddt.num);//函数内部结构体地址
}
//函数内部改变需要地址 所以需要指针保存
void changeall(struct dangdangtest *p)
{
(*p).num = 1000;//*根据地址取出内容
}
void main5()
{
struct dangdangtest ddt;
ddt.num = 99;
sprintf(ddt.name,"adf");//初始化
printf("\nmain=%p,%p",ddt,&ddt.num);//main函数内部结构体地址
/*change(ddt.num);
printf("%d",ddt.num);99*/
/*change2(ddt);
printf("%d",ddt.num);*/
changeall(&ddt);
printf("\n%d",ddt.num);
getchar();
}
//参数对于数组来说传递的是地址 4个字节
void datatest(struct dangdangtest ddd[10])
{
printf("datatest=%d",sizeof(ddd));
}
void dtc(struct dangdangtest ddd[10])
{
ddd[4].num = 88;
sprintf(ddd[4].name,"654656");//前面有提过
printf("datatest=%d",sizeof(ddd));
}
void main()
{
struct dangdangtest ddd[10];//10个元素 36*10
struct dangdangtest *p = ddd;
printf("\n%d",sizeof(ddd));//
ddd[0].num = 90;
sprintf(ddd[0].name,"dfasdf");
/*datatest(ddd);
printf("main=%d",sizeof(ddd));*/
getchar();
}
struct book
{
char bookname[30];
int quantity;
};
main()
{
void fun(struct book*p);
struct book book1={"Programming in C",10};
fun(&book1);
printf("%d copies\n", book1.quantity);
}
void fun(struct book*p)
{
printf("The book \" %s\" has ",p->bookname);
p->quantity -=3;
}