范围for循环(Range-based for loop)总结
本文最后更新于 34 天前,其中的信息可能已经有所发展或是发生改变。

一、核心语法格式

for (元素类型 变量名 : 容器) {
    // 循环体
}

记忆口诀for (类型 名字 : 容器)


二、三种使用方式对比

写法用途能否修改原数据效率
for (char c : s)只读遍历,创建副本❌ 不能较低(有拷贝开销)
for (char& c : s)可修改遍历,引用原数据✅ 能高(无拷贝)
for (const char& c : s)只读遍历,引用原数据❌ 不能高(无拷贝)

三、在蓝桥杯中的经典应用场景

1. 统计字符频率(必会!)

unordered_map<char, int> mp;
string s = "hello";
for (char c : s) {
    mp[c]++;  // 一行搞定统计
}

2. 遍历并处理字符串

// 转为大写
string s = "hello";
for (char& c : s) {  // 要用引用!
    c = toupper(c);
}

3. 遍历vector/数组

vector<int> nums = {1, 2, 3, 4, 5};
int sum = 0;
for (int num : nums) {
    sum += num;
}

4. 遍历map

unordered_map<string, int> scores = {{"Alice", 90}, {"Bob", 85}};
for (auto& pair : scores) {  // pair是键值对
    cout << pair.first << ": " << pair.second << endl;
}

四、与普通for循环的对比

场景:遍历字符串统计元音字母

普通for循环(C++98风格):

int count = 0;
for (int i = 0; i < s.length(); i++) {
    char c = s[i];
    if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
        count++;
    }
}

范围for循环(C++11风格):

int count = 0;
for (char c : s) {
    if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
        count++;
    }
}

优点

  • ✅ 代码更简洁
  • ✅ 不用处理下标,避免越界
  • ✅ 意图更明确(”遍历每个元素”)

缺点

  • ❌ 拿不到当前下标
  • ❌ 不能控制遍历步长(如i+=2)

五、蓝桥杯速记模板

模板1:字符串处理

// 只读遍历
for (char c : str) {
    // 处理c
}

// 修改遍历  
for (char& c : str) {
    c = 处理(c);
}

模板2:容器遍历

// vector遍历
for (auto& num : vec) {
    // 处理num
}

// map遍历
for (auto& [key, value] : mp) {  // C++17结构化绑定
    // 处理key和value
}
// 或
for (auto& pair : mp) {
    // pair.first是key, pair.second是value
}

模板3:二维数组

vector<vector<int>> matrix;
for (auto& row : matrix) {  // row是vector<int>&
    for (int& num : row) {  // 遍历每行
        // 处理num
    }
}

六、易错点提醒

❌ 错误写法1:需要下标时用范围for

string s = "hello";
for (char c : s) {
    cout << "字符" << c << "的下标是?";  // 拿不到下标!
}

✅ 正确做法:用普通for

for (int i = 0; i < s.length(); i++) {
    cout << "下标" << i << "的字符是" << s[i];
}

❌ 错误写法2:遍历时删除元素

vector<int> vec = {1, 2, 3, 4, 5};
for (int num : vec) {
    if (num == 3) {
        // 不能在范围for循环中删除!
        // vec.erase(...)  // 错误!
    }
}

✅ 正确做法:用迭代器

for (auto it = vec.begin(); it != vec.end(); ) {
    if (*it == 3) {
        it = vec.erase(it);
    } else {
        ++it;
    }
}

七、选择使用哪种循环的建议

场景推荐使用原因
只需遍历元素,不要下标范围for循环简洁明了
需要下标普通for循环方便获取i
需要修改元素范围for循环 + 引用简洁且高效
只读不修改范围for循环 + const引用高效安全
需要控制步长(如隔一个)普通for循环方便控制i+=2
遍历时可能增删元素迭代器循环安全,不会失效

八、实战速查表

// 1. 字符串统计(最常用!)
for (char c : s) { mp[c]++; }

// 2. 修改字符串
for (char& c : s) { c = toupper(c); }

// 3. 只读高效遍历
for (const char& c : s) { /* 只读操作 */ }

// 4. 遍历vector计算
int sum = 0;
for (int num : nums) { sum += num; }

// 5. 遍历map
for (auto& [k, v] : mp) { cout << k << ":" << v; }  // C++17
for (auto& p : mp) { cout << p.first << ":" << p.second; }  // 通用

九、记忆技巧

一句话总结

“用引用&才能改,不用&是拷贝,const引用最优选,只读场景效率高”

速记口诀

范围for真方便,遍历容器很简单
char c : s遍历字符串,auto&遍历更通用
要修改就用引用&,只读就用const&
没下标需求就用它,代码简洁又安全

最终建议

对于蓝桥杯等算法竞赛:

  1. 优先使用范围for循环,代码更简洁
  2. 需要下标时用普通for循环
  3. 默认用for (auto& x : container),需要时再加const
  4. 记住mp[c]++这个统计频率的神器组合

掌握了这个语法,你的代码会变得更加简洁优雅!加油!💪

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇