• C++
  • C++字符串处理入门教程:从基础到实战

  • @ 2025-8-2 21:08:36

C++字符串处理入门教程:从基础到实战

字符串是编程中最常用的数据类型之一,尤其在处理文本、字符序列时更是不可或缺。本教程将围绕NOI编程基础中的字符串题目,从基础概念到实战案例,带你掌握C++字符串处理的核心技能。

一、C++字符串基础

1. 什么是字符串?

字符串是由零个或多个字符组成的有限序列。在C++中,我们通常使用string类来处理字符串,它比传统的字符数组更易用、更安全。

2. 字符串的定义与初始化

#include <iostream>
#include <string>  // 使用string类需要包含此头文件
using namespace std;

int main() {
    // 定义字符串的几种方式
    string s1;  // 空字符串
    string s2 = "hello";  // 直接初始化
    string s3("world");  // 构造函数初始化
    string s4(5, 'a');  // 重复字符初始化,结果是"aaaaa"
    
    cout << s2 << " " << s3 << endl;  // 输出:hello world
    return 0;
}

3. 字符串的输入输出

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s1, s2;
    
    // cin输入:遇到空格或换行停止
    cout << "请输入两个单词:";
    cin >> s1 >> s2;
    cout << "你输入的是:" << s1 << " " << s2 << endl;
    
    // getline输入:读取一整行(包括空格)
    cin.ignore();  // 清除输入缓冲区的换行符
    cout << "请输入一句话:";
    getline(cin, s1);
    cout << "你输入的是:" << s1 << endl;
    
    return 0;
}

注意:当cingetline混合使用时,需要用cin.ignore()清除缓冲区中的换行符,否则getline可能会读取到空行。

4. 字符串的基本操作

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s = "hello";
    
    // 获取字符串长度
    cout << "长度:" << s.size() << endl;  // 输出:5
    cout << "长度:" << s.length() << endl;  // 输出:5(与size()功能相同)
    
    // 字符串拼接
    s += " world";
    cout << "拼接后:" << s << endl;  // 输出:hello world
    
    // 字符串比较(与字典序比较相同)
    string a = "apple", b = "banana";
    if (a < b) {
        cout << a << " 在 " << b << " 前面" << endl;
    }
    
    // 访问字符串中的字符
    for (int i = 0; i < s.size(); i++) {
        cout << s[i] << " ";  // 逐个输出字符
    }
    cout << endl;
    
    return 0;
}

二、字符串处理实战案例

案例1:基因相关性判断

题目描述:比较两条DNA序列的相关性,计算相同碱基对占总碱基对数量的比例,若大于等于阈值则判定相关。

#include<iostream>
#include<string>
using namespace std;

int main() {
    double threshold;  // 阈值
    string a, b;       // 两条DNA序列
    
    // 输入阈值
    cin >> threshold;
    
    // 注意:cin后需要处理换行符
    cin.ignore();  // 清除输入缓冲区的换行符
    
    // 输入两条DNA序列
    getline(cin, a);
    getline(cin, b);
    
    int same_count = 0;  // 相同碱基对的数量
    // 遍历两条序列,统计相同碱基对
    for (int i = 0; i < a.size(); i++) {
        if (a[i] == b[i]) {  // 比较对应位置的碱基
            same_count++;
        }
    }
    
    // 计算比例并判断
    double ratio = 1.0 * same_count / a.size();
    if (ratio >= threshold) {
        cout << "yes" << endl;
    } else {
        cout << "no" << endl;
    }
    
    return 0;
}

代码解析

  • 关键在于正确处理输入:先输入阈值(数值),再输入两行字符串
  • 计算比例时需注意整数除法的问题,用1.0 *将结果转换为浮点数
  • 通过循环遍历两个字符串的每个字符,比较并计数相同的碱基对

案例2:石头剪刀布游戏判定

题目描述:根据两人的选择(石头、剪刀、布),判定每局的胜利者。

#include<iostream>
#include<string>
using namespace std;

int main() {
    int n;  // 游戏次数
    cin >> n;
    
    // 处理n局游戏
    for (int i = 0; i < n; i++) {
        string p1, p2;  // 玩家1和玩家2的选择
        cin >> p1 >> p2;
        
        // 判断胜负情况
        if (p1 == p2) {
            // 选择相同,平局
            cout << "Tie" << endl;
        } 
        // 玩家1获胜的情况
        else if ((p1 == "Rock" && p2 == "Scissors") || 
                 (p1 == "Paper" && p2 == "Rock") || 
                 (p1 == "Scissors" && p2 == "Paper")) {
            cout << "Player1" << endl;
        } 
        // 其他情况都是玩家2获胜
        else {
            cout << "Player2" << endl;
        }
    }
    
    return 0;
}

代码解析

  • 使用循环处理多局游戏
  • 通过多条件判断语句覆盖所有可能的情况
  • 逻辑清晰:先判断平局,再判断玩家1获胜的情况,其余则为玩家2获胜

案例3:输出亲朋字符串

题目描述:将字符串转换为亲朋字符串,规则是:每个字符为原字符串中相邻两个字符的ASCII值之和,最后一个字符为最后一个字符与第一个字符的ASCII值之和。

#include<iostream>
#include<string>
using namespace std;

int main() {
    string str;
    // 读取输入字符串(可能包含空格,所以用getline)
    getline(cin, str);
    
    string result = "";  // 存储结果
    int len = str.size();  // 字符串长度
    
    // 处理前len-1个字符
    for (int i = 0; i < len - 1; i++) {
        // 计算当前字符与下一个字符的ASCII值之和,转换为字符
        char c = str[i] + str[i + 1];
        result += c;  // 添加到结果字符串
    }
    
    // 处理最后一个字符:最后一个字符与第一个字符的ASCII值之和
    char last = str[len - 1] + str[0];
    result += last;
    
    // 输出结果
    cout << result << endl;
    
    return 0;
}

代码解析

  • 利用字符的ASCII值进行计算,直接相加即可得到新字符的ASCII值
  • 注意循环的边界条件:处理到倒数第二个字符
  • 单独处理最后一个特殊字符

案例4:配对碱基链

题目描述:根据DNA单链的碱基序列,输出其互补链(A与T配对,G与C配对)。

#include<iostream>
#include<string>
using namespace std;

int main() {
    string dna;
    // 读取输入的碱基链
    cin >> dna;
    
    // 遍历每个碱基,输出其互补碱基
    for (int i = 0; i < dna.size(); i++) {
        switch (dna[i]) {
            case 'A':  // A与T配对
                cout << 'T';
                break;
            case 'T':  // T与A配对
                cout << 'A';
                break;
            case 'G':  // G与C配对
                cout << 'C';
                break;
            case 'C':  // C与G配对
                cout << 'G';
                break;
        }
    }
    cout << endl;
    
    return 0;
}

代码解析

  • 使用switch语句处理四种碱基的配对关系
  • 也可以使用if-else语句实现相同功能
  • 逐个处理每个字符并输出结果,无需额外存储整个结果字符串

案例5:字符替换

题目描述:将字符串中所有指定的字符替换为另一个给定的字符。

#include<iostream>
#include<string>
using namespace std;

int main() {
    string str;
    char old_char, new_char;
    
    // 输入字符串、被替换字符、替换字符
    cin >> str >> old_char >> new_char;
    
    // 遍历字符串,替换指定字符
    for (int i = 0; i < str.size(); i++) {
        if (str[i] == old_char) {
            // 如果当前字符是要替换的字符,则输出新字符
            cout << new_char;
        } else {
            // 否则输出原字符
            cout << str[i];
        }
    }
    cout << endl;
    
    return 0;
}

代码解析

  • 遍历字符串中的每个字符,判断是否需要替换
  • 可以直接输出结果,也可以先构建新字符串再输出
  • 注意输入格式:三个参数之间用空格分隔

三、字符串处理常见技巧

  1. 字符与ASCII码转换

    char c = 'A';
    int ascii = c;  // 得到ASCII码值65
    char new_c = ascii + 32;  // 转换为小写字母'a'
    
  2. 大小写转换

    // 大写转小写:加32
    char lower_c = upper_c + 32;
    // 小写转大写:减32
    char upper_c = lower_c - 32;
    
    // 更通用的方法(使用cctype库)
    #include <cctype>
    char lower_c = tolower(upper_c);
    char upper_c = toupper(lower_c);
    
  3. 字符串遍历方法

    // 方法1:下标遍历
    for (int i = 0; i < str.size(); i++) {
        cout << str[i];
    }
    
    // 方法2:范围for循环(C++11及以上)
    for (char c : str) {
        cout << c;
    }
    
  4. 字符串查找与替换

    // 查找子串
    string str = "hello world";
    size_t pos = str.find("world");  // 查找"world"的位置
    if (pos != string::npos) {
        cout << "找到子串,位置:" << pos << endl;
    }
    
    // 替换子串
    str.replace(pos, 5, "there");  // 从pos位置开始,替换5个字符为"there"
    cout << str << endl;  // 输出:hello there
    

四、练习题推荐

根据难度递增,推荐以下练习题:

  1. ★ 基础题

    • 统计数字字符个数:遍历字符串,统计0-9的字符数量
    • 小写转大写:将字符串中所有小写字母转为大写
  2. ★☆ 进阶题

    • 找第一个只出现一次的字符:记录每个字符出现次数,找到第一个次数为1的字符
    • 字符串判等:判断两个字符串是否完全相同
  3. ★★ 挑战题

    • 密码翻译:实现凯撒密码,将字母按指定位数偏移
    • 验证子串:判断一个字符串是否是另一个字符串的子串

通过这些练习,你可以逐步掌握C++字符串处理的各种技巧,为更复杂的编程问题打下基础。记住,编程能力的提升离不开大量的实践,多写多练才能熟练掌握这些知识。

0 条评论

目前还没有评论...