C++从文件读取姓名并按字母序冒泡排序:sortData函数两处待完善部分求解
解决你的C++冒泡排序与姓名排序问题
首先,先帮你搞定sortData函数里的两处疑问,顺便梳理下代码里其他影响运行的小问题,让整个程序能正常跑起来~
1. 完善sortData函数的两处关键优化
你的冒泡排序框架是对的,但这两处补充能让排序更高效,也符合你标记的待完善点:
优化1:减少内层循环的无效比较
冒泡排序每完成一轮外层循环,都会把当前最大的元素“推”到数组末尾,所以后续循环不需要再碰已经排好序的末尾元素。因此内层循环的终止条件应该改成b < counter - 1 - a,而不是固定的counter-1,这样能避免重复比较有序元素。
优化2:添加有序标记提前终止循环
如果某一轮内层循环里没有发生任何交换,说明整个数组已经是有序的了,没必要继续后续循环。我们可以加一个bool swapped标志来实现这个逻辑,提升排序效率。
修改后的sortData函数:
void sortData(string text[], int counter) { string temp; bool swapped; // 新增:标记本轮是否发生交换 for (int a = 0; a < counter; a++) { swapped = false; // 每轮开始前重置标记 // 内层循环优化:只比较未排序的部分 for (int b = 0; b < counter - 1 - a; b++) { if (text[b] > text[b + 1]) { temp = text[b + 1]; text[b + 1] = text[b]; text[b] = temp; swapped = true; // 发生交换则标记为true } } // 如果本轮无交换,说明数组已完全有序,直接退出循环 if (!swapped) { break; } } }
2. 修复主函数中的核心错误
你的main函数里有两个影响程序运行的问题:
- 你尝试打开不存在的
"fName.txt",实际应该把读取到的fName和lName合并成完整姓名数组,再传入sortData排序。 getData用!zFile.eof()作为循环条件会导致多读一行(因为eof标志是读取失败后才会触发),改成直接用getline的返回值判断更可靠。
修改后的getData函数
int getData(ifstream& zFile, string txt[]) { int counter = 0; // 直接用getline的返回值判断是否读取成功 while (getline(zFile, txt[counter])) { counter++; } return counter; }
修改后的main函数
int main() { ifstream zFile1; ifstream zFile2; zFile1.open("firstname.txt"); zFile2.open("lastname.txt"); fileCheck(zFile1,"firstname.txt"); fileCheck(zFile2,"lastname.txt"); string fName[100], lName[100]; int fcounter = getData(zFile1, fName); int lcounter = getData(zFile2, lName); // 确保名和姓的数量一致(简单容错) int totalNames = min(fcounter, lcounter); string fullNames[100]; // 合并名和姓为完整姓名 for (int a = 0; a < totalNames; a++) { fullNames[a] = fName[a] + " " + lName[a]; cout << "Original Name: " << fullNames[a] << endl; } cout << endl << "After sorting alphabetically:" << endl; // 对完整姓名数组排序 sortData(fullNames, totalNames); // 输出排序结果 for (int a = 0; a < totalNames; a++) { cout << fullNames[a] << endl; } zFile1.close(); zFile2.close(); return 0; }
3. 完整修正后的代码
整合所有修改后的完整代码:
#include<iostream> #include<string> #include<fstream> #include<algorithm> // 用于min函数 using namespace std; void fileCheck(ifstream& zFile, string filen); int getData(ifstream& zFile, string txt[]); void sortData(string text[], int counter); int main() { ifstream zFile1; ifstream zFile2; zFile1.open("firstname.txt"); zFile2.open("lastname.txt"); fileCheck(zFile1,"firstname.txt"); fileCheck(zFile2,"lastname.txt"); string fName[100], lName[100]; int fcounter = getData(zFile1, fName); int lcounter = getData(zFile2, lName); int totalNames = min(fcounter, lcounter); string fullNames[100]; for (int a = 0; a < totalNames; a++) { fullNames[a] = fName[a] + " " + lName[a]; cout << "Original Name: " << fullNames[a] << endl; } cout << endl << "After sorting alphabetically:" << endl; sortData(fullNames, totalNames); for (int a = 0; a < totalNames; a++) { cout << fullNames[a] << endl; } zFile1.close(); zFile2.close(); return 0; } void fileCheck(ifstream& zFile, string filen) { if (!zFile.is_open()) { cout << filen << " not found" << endl; exit(1); } } int getData(ifstream& zFile, string txt[]) { int counter = 0; while (getline(zFile, txt[counter])) { counter++; } return counter; } void sortData(string text[], int counter) { string temp; bool swapped; for (int a = 0; a < counter; a++) { swapped = false; for (int b = 0; b < counter - 1 - a; b++) { if (text[b] > text[b + 1]) { temp = text[b + 1]; text[b + 1] = text[b]; text[b] = temp; swapped = true; } } if (!swapped) { break; } } }
额外小建议
- 新手阶段用
using namespace std;没问题,但大型项目里尽量避免,防止命名冲突。 - 固定大小的数组可以换成
vector<string>,这样能灵活处理任意数量的姓名,不会因为超过100条而出错。 - 合并姓名时可以加个判断,避免名或姓为空时出现多余空格。
内容的提问来源于stack exchange,提问作者Nadx
相关产品推荐
相关产品推荐

