使用getline读取文件字符间出现空格,求目录列表处理方案
解决读取dir输出文件时字符间有空格的问题+艺术家排序方案
嘿,我来帮你搞定这个问题!首先咱们得搞清楚为啥读取后每个字符之间会有空格——这大概率是因为Windows下dir > music.txt生成的文件是UTF-16 LE编码(带BOM),而你用普通的ifstream读取时,会把每个占2字节的宽字符拆成两个独立的ASCII字符处理,空字节显示出来就是空格。接下来给你两种解决方案,顺便把移除权限日期、排序艺术家的需求一起搞定:
方案一:让dir直接输出纯文件名(最省心)
与其后期处理权限、日期这些冗余信息,不如直接让dir只输出文件名,用这个命令生成目标文件:
dir /a-d /b > music.txt
/a-d:排除目录,只显示文件/b:使用“bare”格式,只输出文件名,不带任何额外信息
这样生成的music.txt是ANSI编码,用普通getline读取就不会有空格问题,代码也更简洁:
#include "stdafx.h" #include <iostream> #include <fstream> #include <vector> #include <algorithm> #include <string> using namespace std; // 用标准库sort排序,比自己实现的更高效可靠 void AlphaSort(vector<string>& data) { sort(data.begin(), data.end()); } void PrintArray(const vector<string>& data) { for (const auto& artist : data) { cout << artist << endl; } } int main() { ifstream file("music.txt"); if (!file.is_open()) { cerr << "无法打开music.txt文件!" << endl; return 1; } vector<string> artists; string filename; while (getline(file, filename)) { // 提取艺术家名称,假设文件名格式是「艺术家 - 歌曲名.mp3」 size_t dashPos = filename.find(" - "); if (dashPos != string::npos) { // 截取分隔符前的艺术家名称 artists.push_back(filename.substr(0, dashPos)); } else { // 如果没有分隔符,就去掉文件扩展名作为艺术家名 size_t dotPos = filename.find_last_of('.'); if (dotPos != string::npos) { artists.push_back(filename.substr(0, dotPos)); } else { artists.push_back(filename); } } } // 按字母排序艺术家列表 AlphaSort(artists); // 输出结果 cout << "排序后的艺术家列表:\n"; PrintArray(artists); return 0; }
方案二:正确读取UTF-16格式的dir输出文件
如果你必须保留dir的完整输出(比如需要其他信息),那就要用宽字符流来读取UTF-16文件,代码如下:
#include "stdafx.h" #include <iostream> #include <fstream> #include <vector> #include <algorithm> #include <string> #include <locale> #include <codecvt> using namespace std; void AlphaSort(vector<string>& data) { sort(data.begin(), data.end()); } void PrintArray(const vector<string>& data) { for (const auto& artist : data) { cout << artist << endl; } } int main() { // 用wifstream读取宽字符文件 wifstream file("music.txt"); if (!file.is_open()) { cerr << "无法打开music.txt文件!" << endl; return 1; } // 设置locale以正确解析UTF-16编码(带BOM) file.imbue(locale(file.getloc(), new codecvt_utf16<wchar_t, 0x10ffff, consume_header>())); vector<wstring> wideLines; wstring wideLine; while (getline(file, wideLine)) { wideLines.push_back(wideLine); } // 把宽字符串转成普通string(方便后续处理) vector<string> lines; wstring_convert<codecvt_utf8<wchar_t>> converter; for (const auto& wline : wideLines) { lines.push_back(converter.to_bytes(wline)); } vector<string> artists; for (const auto& line : lines) { // 找到最后一个空格,提取后面的文件名部分(跳过权限、日期等信息) size_t lastSpace = line.find_last_of(' '); if (lastSpace != string::npos) { string filename = line.substr(lastSpace + 1); // 提取艺术家名称,逻辑和方案一一致 size_t dashPos = filename.find(" - "); if (dashPos != string::npos) { artists.push_back(filename.substr(0, dashPos)); } else { size_t dotPos = filename.find_last_of('.'); artists.push_back(dotPos != string::npos ? filename.substr(0, dotPos) : filename); } } } AlphaSort(artists); cout << "排序后的艺术家列表:\n"; PrintArray(artists); return 0; }
额外提示
- 我把你原来的固定大小数组改成了
vector<string>,这样就不用限制最多300个条目,更灵活还能避免数组溢出; - 直接用标准库的
std::sort来排序,比自己实现排序函数更高效、更不容易出错; - 如果你的文件名格式不是「艺术家 - 歌曲名」,可以调整提取艺术家的逻辑,比如根据特定分隔符或者位置来截取。
内容的提问来源于stack exchange,提问作者Macdaddy4sure
相关产品推荐
相关产品推荐

