C++字符数组拆分:struct存储婴儿数据与std::string::copy使用问题求助
代码错误定位与修正方案
编译报错根因
std::string::copy()方法的参数逻辑为:将当前字符串对象的内容拷贝到外部提供的char*缓冲区,参数顺序是(目标char缓冲区, 拷贝长度, 拷贝起始位置)。你当前调用时把baby_datapair[n].baby_name(本身是std::string类型,不是可写入的char缓冲区)作为第一个参数传入,同时把拷贝长度写为0、起始位置写为逗号的索引值,参数类型和语义完全不匹配,因此触发编译报错。- 代码中存在多处笔误:定义的接收输入的变量是
char name[12],后续判断空输入时却写了if (neve == ""),变量名不匹配;用固定长度的char数组接长输入还容易触发缓冲区溢出,完全可以直接用std::string适配变长输入。
独立功能函数的拆分逻辑
按照单一职责边界拆分,完全满足功能隔离要求:
- 输入循环函数
readIn:只负责循环逻辑:打印输入提示、调用std::getline读取一整行输入、判断输入是否为空行触发退出、将读取到的整行文本传给拆分函数处理、处理拆分返回的错误状态、在有效录入未达最大容量时持续循环,最后返回实际录入的有效婴儿数据总数。该函数完全不实现字符串分割、数值解析的细节逻辑。 - 单行拆分存储函数
parseLine:只负责单条文本的字段解析:接收整行输入文本、待写入的baby结构体引用,内部完成逗号位置查找、姓名截取、体重数值提取、格式合法性校验,解析成功将值写入结构体后返回true,格式不符合要求返回false。
字段截取的正确实现
完全不需要使用std::string::copy()完成姓名拷贝:
- 找到逗号的索引位置
pos后,直接使用std::string::substr(0, pos)即可截取从字符串开头到逗号前的全部内容,直接赋值给结构体的baby_name字段即可,无缓冲区溢出风险。 - 体重字段的解析:截取逗号之后的子串后,直接通过
std::stof将子串开头的数字部分转换为float类型,自动忽略子串后面的"kg"单位文本即可。
参考修正代码
#include<iostream> #include<string> #include<cctype> #define M 1000 struct baby{ std::string baby_name; float weight; }; // 前置声明 int readIn(baby* baby_datapair, int max); bool parseLine(const std::string& line, baby& out_baby); int main(){ baby baby_array[M]; int valid_count = readIn(baby_array, M); std::cout << "共成功录入 " << valid_count << " 条婴儿信息\n"; return 0; } // 循环读入直到空行 int readIn(baby* baby_datapair, int max){ int n = 0; std::string input_line; while (n < max){ std::cout << "Baby" << n+1 << "'s datas (Nickname, weight in kg): "; std::getline(std::cin, input_line); // 空行触发退出 if (input_line.empty()){ std::cout << "检测到空输入,停止录入\n"; break; } // 调用拆分函数解析单行 bool parse_success = parseLine(input_line, baby_datapair[n]); if (!parse_success){ std::cout << "输入格式错误,请按照「姓名, 体重kg」的格式重新输入\n"; continue; } n++; } return n; } // 拆分单行文本为结构体字段 bool parseLine(const std::string& line, baby& out_baby){ // 找逗号位置 std::size_t comma_pos = line.find(','); if (comma_pos == std::string::npos){ return false; } // 截取姓名部分,去掉前后空白 std::string name_part = line.substr(0, comma_pos); auto name_start = name_part.find_first_not_of(" \t"); auto name_end = name_part.find_last_not_of(" \t"); if (name_start == std::string::npos){ return false; } out_baby.baby_name = name_part.substr(name_start, name_end - name_start + 1); // 截取体重部分 std::string weight_part = line.substr(comma_pos + 1); // 定位第一个数字/小数点的位置 auto weight_start = weight_part.find_first_of("0123456789."); if (weight_start == std::string::npos){ return false; } try{ out_baby.weight = std::stof(weight_part.substr(weight_start)); } catch(...){ return false; } return true; }
内容的提问来源于stack exchange,提问作者Ms Cookie
相关产品推荐
相关产品推荐

