substr 函数

C++ substr 函数学习路径

substr 是 C++ 中用来截取字符串子串的重要函数。

一、substr 基础概念

函数原型

string substr(size_t pos = 0, size_t len = npos) const;

参数说明

· pos:开始位置(从0开始计数)

· len:要截取的长度(可选,默认到字符串末尾)

返回值

返回一个新的字符串,包含从 pos 开始的 len 个字符

二、学习路径与练习题

阶段1:基础用法(1-2天)

练习1:截取名字

#include <iostream>
#include <string>

int main() {
    std::string fullName = "Liu You Yi";
    
    // 截取姓氏(前3个字符)
    std::string lastName = fullName.substr(0, 3);
    std::cout << "姓氏: " << lastName << std::endl;
    
    // 截取名字"You Yi"(从位置4开始到末尾)
    std::string firstName = fullName.substr(4);
    std::cout << "名字: " << firstName << std::endl;
    
    return 0;
}

练习2:提取文件扩展名

#include <iostream>
#include <string>

int main() {
    std::string filename = "document.pdf";
    
    // 找到点号的位置
    size_t dotPos = filename.find('.');
    
    // 检查是否找到并截取扩展名
    if(dotPos != std::string::npos) {
        std::string extension = filename.substr(dotPos + 1);
        std::cout << "文件扩展名: " << extension << std::endl;
    } else {
        std::cout << "没有找到扩展名" << std::endl;
    }
    
    return 0;
}

阶段2:中级应用(2-3天)

练习3:分割字符串

#include <iostream>
#include <string>
#include <vector>

int main() {
    std::string date = "2023-08-15";
    std::vector<std::string> parts;
    size_t start = 0;
    size_t end = date.find('-');
    
    // 循环分割字符串
    while(end != std::string::npos) {
        parts.push_back(date.substr(start, end - start));
        start = end + 1;
        end = date.find('-', start);
    }
    // 添加最后一部分
    parts.push_back(date.substr(start));
    
    // 输出结果
    std::cout << "年: " << parts[0] << std::endl;
    std::cout << "月: " << parts[1] << std::endl;
    std::cout << "日: " << parts[2] << std::endl;
    
    return 0;
}

练习4:提取URL各部分

#include <iostream>
#include <string>

int main() {
    std::string url = "https://www.example.com:8080/path/to/page";
    
    // 提取协议(https)
    size_t protocolEnd = url.find("://");
    std::string protocol = url.substr(0, protocolEnd);
    
    // 提取域名和端口
    size_t domainStart = protocolEnd + 3;
    size_t pathStart = url.find('/', domainStart);
    std::string domainAndPort = url.substr(domainStart, pathStart - domainStart);
    
    // 提取路径
    std::string path = url.substr(pathStart);
    
    std::cout << "协议: " << protocol << std::endl;
    std::cout << "域名和端口: " << domainAndPort << std::endl;
    std::cout << "路径: " << path << std::endl;
    
    return 0;
}

阶段3:进阶应用(3-5天)

练习5:实现简单文本高亮

#include <iostream>
#include <string>

std::string highlightText(const std::string& text, const std::string& keyword) {
    std::string result;
    size_t pos = 0;
    size_t keywordPos = text.find(keyword);
    
    while(keywordPos != std::string::npos) {
        // 添加关键词前的文本
        result += text.substr(pos, keywordPos - pos);
        // 添加高亮关键词
        result += "[" + text.substr(keywordPos, keyword.length()) + "]";
        // 更新位置
        pos = keywordPos + keyword.length();
        keywordPos = text.find(keyword, pos);
    }
    // 添加剩余文本
    result += text.substr(pos);
    
    return result;
}

int main() {
    std::string content = "C++ is a powerful language. C++ is fast.";
    std::string highlighted = highlightText(content, "C++");
    
    std::cout << "高亮结果:\n" << highlighted << std::endl;
    return 0;
}

练习6:密码隐藏显示

#include <iostream>
#include <string>

std::string hidePassword(const std::string& password, int showChars = 2) {
    if(password.length() <= showChars) {
        return password; // 太短不隐藏
    }
    
    // 显示前showChars个字符,其余用*代替
    return password.substr(0, showChars) + 
           std::string(password.length() - showChars, '*');
}

int main() {
    std::string password = "mySecret123";
    
    std::cout << "完整密码: " << password << std::endl;
    std::cout << "隐藏后: " << hidePassword(password) << std::endl;
    std::cout << "显示3个字符: " << hidePassword(password, 3) << std::endl;
    
    return 0;
}

三、常见错误及解决方法

错误1:位置超出范围

std::string str = "hello";
// std::string sub = str.substr(10, 2); // 抛出异常!

// 正确做法:先检查长度
if(str.length() > 10) {
    std::string sub = str.substr(10, 2);
}

错误2:忘记检查find结果

std::string email = "test@example";
size_t atPos = email.find('@');
// std::string domain = email.substr(atPos + 1); // 如果没找到@会出错

// 正确做法
if(atPos != std::string::npos) {
    std::string domain = email.substr(atPos + 1);
}

错误3:混淆参数顺序

std::string date = "2023-08-15";
// std::string month = date.substr(5, 2); 
// 正确:从位置5截取2个字符
// std::string wrong = date.substr(2, 5); 
// 语义错误(虽然语法正确)

四、综合练习

练习7:提取CSV文件数据

#include <iostream>
#include <string>
#include <vector>

std::vector<std::string> parseCSVLine(const std::string& line) {
    std::vector<std::string> fields;
    size_t start = 0;
    size_t end = line.find(',');
    
    while(end != std::string::npos) {
        fields.push_back(line.substr(start, end - start));
        start = end + 1;
        end = line.find(',', start);
    }
    fields.push_back(line.substr(start));
    
    return fields;
}

int main() {
    std::string csvLine = "Liu You Yi,14,Beijing,C++ Programming";
    std::vector<std::string> data = parseCSVLine(csvLine);
    
    std::cout << "姓名: " << data[0] << std::endl;
    std::cout << "年龄: " << data[1] << std::endl;
    std::cout << "城市: " << data[2] << std::endl;
    std::cout << "兴趣: " << data[3] << std::endl;
    
    return 0;
}

五、学习建议

1.循序渐进:从简单截取开始,逐步尝试复杂的分割和处理

2.多调试:使用cout输出中间结果,观察substr的行为

3.结合find:大多数实际应用中substr都是和find一起使用

4.边界检查:始终检查位置是否有效,避免程序崩溃

记住:substr 是处理字符串的强大工具,掌握它能让你的文本处理能力大大提升!加油练习!

posted @ 2025-05-31 09:44  爱吃泡面的皮卡  阅读(822)  评论(0)    收藏  举报