传递结构体指针
本课属于 Coddy C 学习旅程的“逻辑与流程”单元。第 47 课,共 63 课。
按值传递结构体适合读取数据,但对于较大的结构体来说效率不高,因为整个结构体都会被复制。更重要的是,你无法在函数内部修改原始结构体。这时,传递指向结构体的指针就非常重要。
当你传递指向结构体的指针,而不是结构体本身时,函数会接收到原始结构体的内存地址。这种方式有两个主要优点:效率更高(无需复制),而且函数可以修改原始数据。
接受指向结构体的指针的函数语法如下:
void functionName(struct StructureName *ptr) {
// 使用 ptr->member 的函数体
}在函数内部,你可以使用箭头运算符访问和修改结构体成员。通过指针进行的任何更改都会直接影响调用函数中的原始结构体,因此这种方式非常适合需要更新或转换结构体数据的函数。
这种技术对于编写能够处理复杂数据结构的高效 C 程序至关重要,因为它结合了指针的强大功能和结构体的组织方式。
挑战
简单创建一个 C 程序,演示如何将指向结构体的指针传递给函数,以高效地修改数据。你的程序应:
- 定义一个名为
BankAccount的struct,包含以下成员:- 一个整数
accountNumber,用于存储账户号码 - 一个大小为 30 的字符数组
ownerName,用于存储账户所有者的姓名 - 一个浮点数
balance,用于存储账户余额 - 一个整数
transactionCount,用于存储交易次数
- 一个整数
- 编写一个名为
depositMoney的函数,该函数:- 接收指向
BankAccount结构体的指针和一个浮点数金额作为参数 - 使用箭头运算符将金额加到账户余额中
- 将交易次数加 1
- 打印
Deposit successful. New balance: [balance]
- 接收指向
- 编写一个名为
withdrawMoney的函数,该函数:- 接收指向
BankAccount结构体的指针和一个浮点数金额作为参数 - 检查取款金额是否大于当前余额
- 如果余额不足,打印
Insufficient funds. Current balance: [balance] - 如果余额充足,从余额中扣除该金额,将交易次数加 1,并打印
Withdrawal successful. New balance: [balance]
- 接收指向
- 编写一个名为
displayAccount的函数,该函数:- 接收指向
BankAccount结构体的指针作为参数 - 按照以下确切格式打印账户信息:
Account Information:Account Number: [accountNumber]Owner: [ownerName]Balance: [balance]Transactions: [transactionCount]
- 接收指向
- 在 main 函数中:
- 创建一个名为
account的BankAccount变量 - 从输入中读取账户号码、所有者姓名和初始余额
- 将交易次数设为 0
- 调用
displayAccount,显示账户的初始状态 - 读取存款金额并调用
depositMoney - 读取取款金额并调用
withdrawMoney - 调用
displayAccount,显示账户的最终状态
- 创建一个名为
这个挑战展示了将指向结构体的指针传递给函数的优势。与按值传递不同,函数接收的是原始结构体的内存地址,因此可以直接修改原始数据。这种方式效率更高(无需复制),还能让函数永久修改调用函数中的结构体值。
亲手试试
#include <stdio.h>
#include <string.h>
// TODO:在这里定义 BankAccount 结构体
// TODO:在这里编写 depositMoney 函数
// TODO:在这里编写 withdrawMoney 函数
// TODO:在这里编写 displayAccount 函数
int main() {
// 读取输入
int accountNum;
char ownerName[30];
float initialBalance;
float depositAmount;
float withdrawAmount;
scanf("%d", &accountNum);
scanf("%s", ownerName);
scanf("%f", &initialBalance);
scanf("%f", &depositAmount);
scanf("%f", &withdrawAmount);
// TODO:创建 BankAccount 变量并初始化
// TODO:调用 displayAccount 显示初始状态
// TODO:将存款金额传给 depositMoney 并调用它
// TODO:将取款金额传给 withdrawMoney 并调用它
// TODO:调用 displayAccount 显示最终状态
return 0;
}这节课包含一个小测验。开始学习即可作答,并记录你的进度。
逻辑与流程中的所有课
自己练习: C 在线编译器