C++ for循环问题:点唱机程序仅打印首张专辑原因排查
哈哈,这个问题我当初刚学循环的时候也踩过类似的坑!咱们一步步拆解为什么会出现这两种奇怪的情况,再给你说正确的处理方式~
第一种情况:把int i声明在第二层for循环里
假设你的代码大概是这样的:
// 遍历所有专辑 for (auto& album : albums) { // 遍历当前专辑的歌曲,每次进入这个循环都重新声明i并初始化为0 for (int i = 0; i < album.getSongs().size(); ++i) { cout << i + 1 << ". " << album.getSongs()[i].getTitle() << endl; } }
这里的问题很直接:每次进入内层循环(处理单张专辑的歌曲)时,i都会被重新定义并赋值为0。也就是说,处理第一张专辑时,i从0开始数到专辑歌曲数-1;处理第二张专辑时,又从头把i设为0,所以第二张专辑的歌曲又从1开始编号,而不是接着上一张的末尾数,这就是你说的“处理完一张专辑i会重置为0”的原因。
第二种情况:把int i声明在所有for循环外面
如果代码改成这样:
int i = 0; // 遍历所有专辑 for (auto& album : albums) { // 用外层的i来遍历当前专辑的歌曲 for (; i < album.getSongs().size(); ++i) { cout << i + 1 << ". " << album.getSongs()[i].getTitle() << endl; } }
这时候的坑藏在循环逻辑里。咱们举个例子:假设第一张专辑有3首歌,第一次内层循环时,i从0走到2(因为i < 3),循环结束后i变成3。接下来处理第二张专辑,内层循环的条件是i < 第二张专辑的歌曲数——如果第二张专辑只有2首歌,那3 < 2不成立,内层循环直接跳过;就算第二张专辑有5首歌,你用album.getSongs()[i]访问的是索引3的位置,但当前专辑的歌曲索引是从0开始的,这不仅会导致后面的专辑不打印,还可能直接触发数组越界崩溃!本质上你搞错了“计数编号”和“数组索引”的用途,用累计的计数去当独立数组的索引,逻辑完全不对。
正确的做法:用全局计数变量,遍历每首歌时自增
你需要的是一个跨所有循环的计数变量,专门用来给所有歌曲连续编号,而不是用它来做数组索引。代码应该是这样的:
// 初始化歌曲编号为1,从1开始计数 int songCount = 1; // 遍历每一张专辑 for (auto& album : albums) { // 遍历当前专辑里的每一首歌 for (auto& song : album.getSongs()) { // 打印编号和歌曲信息 cout << songCount << ". " << song.getTitle() << " - " << song.getArtist() << endl; // 编号自增,准备下一首歌 songCount++; } }
如果一定要用迭代器(你题目里提到用迭代器为歌曲编号),写法也类似:
int songCount = 1; // 专辑迭代器 for (auto albumIt = albums.begin(); albumIt != albums.end(); ++albumIt) { // 歌曲迭代器 for (auto songIt = albumIt->getSongs().begin(); songIt != albumIt->getSongs().end(); ++songIt) { cout << songCount << ". " << songIt->getTitle() << endl; songCount++; } }
这样不管有多少张专辑,每首歌都会按顺序从1开始连续编号,不会出现重置或者跳过的问题。
内容的提问来源于stack exchange,提问作者Newbie2018
相关产品推荐
相关产品推荐

