如何在C++中编写遍历艺术家-专辑-歌曲的两层嵌套for循环?
C++音乐信息格式化输出问题解决
问题说明
需要编写C++程序按指定格式输出音乐类信息,已实现艺术家map的字典序遍历,但需要添加两层嵌套循环遍历每个艺术家的专辑map和每张专辑的歌曲map,同时修正原程序中数据插入的冗余逻辑。预期输出格式如下:
Coltrane, John: 4, 18:37 Giant Steps: 4, 18:37 1. Giant Steps: 4:46 3. Countdown: 2:25 6. Naima: 4:24 7. Mr. P.C.: 7:02 Lyle, Bobby: 1, 5:16 Night Breeze: 1, 5:16 5. Naima: 5:16 Puente, Tito: 1, 4:02 El Rey: 1, 4:02 5. Giant Steps: 4:02 Tjader, Cal: 1, 5:36 A Fuego Vivo: 1, 5:36 6. Naima: 5:36 Walton, Cedar: 4, 30:44 Eastern Rebellion: 1, 8:38 2. Naima: 8:38 Naima: 3, 22:06 2. This Guy's In Love With You: 8:10 4. Down In Brazil: 6:07 6. Naima: 7:49
修正后的完整代码
#include <string> #include <vector> #include <list> #include <cmath> #include <algorithm> #include <map> #include <set> #include <iostream> #include <cstdio> #include <cstdlib> #include <fstream> using namespace std; class Song { public: string title; int time; int track; }; class Album { public: map<int, Song> songs; string name; int time = 0; int nsongs = 0; // 新增:统计专辑内歌曲数量 }; class Artist { public: map<string, Album> albums; string name; int time = 0; int nsongs = 0; }; int stringToInt(string s) { int i = 0; i += ((s.c_str())[0] - '0') * 60; i += ((s.c_str())[2] - '0') * 10; i += ((s.c_str())[3] - '0'); return i; } string intToString(int i) { string s; int m, s_total; char m1, m2, s1, s2; m = i / 60; s_total = i % 60; if (m < 10) { s.push_back(m + '0'); } else { m1 = (m / 10) + '0'; m2 = (m % 10) + '0'; s.push_back(m1); s.push_back(m2); } s.push_back(':'); s1 = (s_total / 10) + '0'; s2 = (s_total % 10) + '0'; s.push_back(s1); s.push_back(s2); return s; } int main(int argc, char *argv[]) { string filename = argv[1]; ifstream fin; string title, time_str, artist_name, album_name, genre; int track; map<string, Artist> artists; fin.open(filename); while (fin >> title >> time_str >> artist_name >> album_name >> genre >> track) { // 替换下划线为空格 replace(title.begin(), title.end(), '_', ' '); replace(artist_name.begin(), artist_name.end(), '_', ' '); replace(album_name.begin(), album_name.end(), '_', ' '); int song_time = stringToInt(time_str); // 利用map的operator[]自动创建对象,简化插入逻辑 Artist& cur_artist = artists[artist_name]; cur_artist.name = artist_name; cur_artist.nsongs++; cur_artist.time += song_time; Album& cur_album = cur_artist.albums[album_name]; cur_album.name = album_name; cur_album.nsongs++; cur_album.time += song_time; Song cur_song; cur_song.title = title; cur_song.track = track; cur_song.time = song_time; cur_album.songs[track] = cur_song; } // 遍历艺术家 for (const auto& artist_pair : artists) { const Artist& artist = artist_pair.second; cout << artist.name << ": " << artist.nsongs << ", " << intToString(artist.time) << "\n"; // 遍历当前艺术家的专辑 for (const auto& album_pair : artist.albums) { const Album& album = album_pair.second; cout << " " << album.name << ": " << album.nsongs << ", " << intToString(album.time) << "\n"; // 遍历当前专辑的歌曲 for (const auto& song_pair : album.songs) { const Song& song = song_pair.second; cout << " " << song.track << ". " << song.title << ": " << intToString(song.time) << "\n"; } } } fin.close(); return 0; }
关键修改说明
- 简化数据插入逻辑:移除原程序中冗余的
find判断,利用std::map的operator[]特性,当键不存在时自动创建默认构造的对象,直接引用对象更新属性,代码更简洁高效。 - 新增专辑歌曲统计:在
Album类中添加nsongs成员变量,用于统计每张专辑的歌曲数量,匹配预期输出的格式要求。 - 实现嵌套遍历:在艺术家遍历循环内,嵌套遍历当前艺术家的
albumsmap,再在专辑循环内遍历songsmap,实现三级结构的层级输出。 - 格式对齐优化:使用4个空格的缩进对应输出的层级,确保输出格式与预期一致。
- 变量可读性优化:重命名部分变量(如
time改为time_str),避免与类成员变量冲突,提升代码可读性。
内容的提问来源于stack exchange,提问作者Ian Burns
相关产品推荐
相关产品推荐

