C++中无法将string变量赋值给结构体char数组成员的问题求助
问题修复方案
核心问题拆解与修复
- 函数名不匹配:声明的
modifyRecord和定义的modifyingRecord不一致,直接导致编译失败,把定义的函数名改成modifyRecord即可。 - getline输入吞空问题:用
cin >>读取数字后,输入缓冲区会残留换行符,后续getline会直接读取这个空行。需要把cin.ignore()放在getline之前,清空缓冲区的换行符。 - strcpy参数错误:
strcpy的第二个参数需要const char*类型,不能直接传std::string对象,得用str.c_str()获取C风格字符串指针。 - 文件定位错误:直接用
tempNum作为seekg的偏移量完全错误,每个Product记录占sizeof(Product)字节,要定位到第N条记录,偏移量应该是tempNum * sizeof(Product)(注意如果记录编号从1开始,要减1,比如输入1对应第0个偏移)。
修正后的完整代码
#include<iostream> #include<fstream> #include<string> #include<cstring> #include<limits> #pragma warning(disable : 4996) using namespace std; const int NAME_SIZE = 40; struct Product { long number; char name[NAME_SIZE]; double price; int quantity; }; void modifyRecord(fstream&); void createFile(fstream&); // 补充函数声明,避免编译报错 int main() { fstream inventoryFile; // 调整open参数:二进制读写模式,文件不存在则创建 inventoryFile.open("inventory.dat", ios::binary | ios::in | ios::out); if (inventoryFile) { // 判断文件是否为空,避免重复写入初始数据 inventoryFile.seekg(0, ios::end); if (inventoryFile.tellg() == 0) { createFile(inventoryFile); cout << "Inventory File created.\n"; } else { cout << "Inventory File opened.\n"; } // 重置文件指针到开头 inventoryFile.seekg(0); } else { cout << "Error: Cannot open file." << endl; return 1; } modifyRecord(inventoryFile); inventoryFile.close(); return 0; } void createFile(fstream& inventoryFile) { Product milk; milk.number = 15478; strcpy(milk.name, "Whole Milk"); milk.price = 2.99; milk.quantity = 30; inventoryFile.write(reinterpret_cast<char*>(&milk), sizeof(milk)); } void modifyRecord(fstream& inventoryFile) { string str; int tempNum = 0; Product prod; cout << "\nEnter Record Index (start from 0): "; cin >> tempNum; // 定位到对应记录的起始位置 inventoryFile.seekg(tempNum * sizeof(Product), ios::beg); // 先读取原有记录,保留未修改的字段值 inventoryFile.read(reinterpret_cast<char*>(&prod), sizeof(Product)); cout << "\nEnter New Product Number: \n"; cin >> prod.number; cout << "\nEnter New Product Name: \n"; // 先忽略之前cin留下的所有换行符 cin.ignore(numeric_limits<streamsize>::max(), '\n'); getline(cin, str); // 用strncpy替代strcpy,避免数组溢出,手动补结束符 strncpy(prod.name, str.c_str(), NAME_SIZE - 1); prod.name[NAME_SIZE - 1] = '\0'; cout << "\nEnter New Price: \n"; cin >> prod.price; cout << "\nEnter New Quantity: "; cin >> prod.quantity; // 回到记录起始位置,覆盖写入更新后的数据 inventoryFile.seekp(tempNum * sizeof(Product), ios::beg); inventoryFile.write(reinterpret_cast<char*>(&prod), sizeof(Product)); cout << "Record updated successfully.\n"; }
额外优化说明
- 用
strncpy替代strcpy,避免输入的产品名称过长导致数组溢出,提升安全性。 - 添加了文件是否为空的判断,避免每次打开文件都覆盖初始记录。
- 读取原有记录后再修改,确保未修改的字段保留原有值(原代码新建
prod变量时,未赋值的字段会是随机值,写入后会破坏原有数据)。
内容的提问来源于stack exchange,提问作者user20078963
相关产品推荐
相关产品推荐

