Files
project1/第08课-字符串与string/编程题-教师版.md

15 KiB
Raw Permalink Blame History

第8课编程题教师版

本课知识点覆盖表

核心知识点 GESP等级 对应课堂题
字符数组、字符串结束标志、单词与整行输入 三级工具 课堂1
string 长度、下标遍历、字符分类统计 三级工具 课堂2
字符串查找、替换与截取 三级工具 课堂3
字符串逆序与回文判断 三级工具 课堂4

一、课堂练习4题

课堂1两种字符串输入【适中】

题目描述: 第一行输入一个不含空格的单词,使用字符数组保存;第二行输入一个可能含空格的句子,使用字符串保存。依次输出单词长度、句子长度以及句子中的空格数量。

输入格式: 第一行输入一个不含空格的单词;第二行输入一整句话。

输出格式: 依次输出单词长度、句子长度和空格数量。

数据范围: 单词和句子长度均不超过 200。

输入样例:

GESP
I love C++

输出样例:

4 10 2

解题思路: 字符数组以 '\0' 作为结束标志;读完单词后先忽略换行,再用 getline 读取整行字符串。

参考代码:

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

int main() {
    char word[205];
    string sentence;
    cin >> word;
    cin.ignore();
    getline(cin, sentence);

    int wordLength = 0;
    while (word[wordLength] != '\0') wordLength++;

    int spaces = 0;
    for (char c : sentence) {
        if (c == ' ') spaces++;
    }
    cout << wordLength << " " << sentence.size() << " " << spaces;
    return 0;
}

易错提醒: cin 不会读入空格;getline 前要处理输入缓冲区中的换行符。

课堂2字符串分类统计【适中】

题目描述: 输入一整行字符串,统计大写字母、小写字母、数字、空格和其他字符的数量。

输入格式: 输入一整行字符串。

输出格式: 依次输出五类字符的数量。

数据范围: 字符串长度不超过 500。

输入样例:

Hi 2026!

输出样例:

1 1 4 1 1

解题思路: 使用下标遍历字符串,通过互斥分支判断字符所属类别。

参考代码:

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

int main() {
    string s;
    getline(cin, s);
    int upper = 0, lower = 0, digit = 0, space = 0, other = 0;
    for (int i = 0; i < (int)s.size(); i++) {
        char c = s[i];
        if (c >= 'A' && c <= 'Z') upper++;
        else if (c >= 'a' && c <= 'z') lower++;
        else if (c >= '0' && c <= '9') digit++;
        else if (c == ' ') space++;
        else other++;
    }
    cout << upper << " " << lower << " " << digit << " "
         << space << " " << other;
    return 0;
}

易错提醒: 字符串的合法下标为 0 到长度减 1分类时只能让一个字符进入一个计数器。

课堂3敏感词替换与截取【适中】

题目描述: 输入一个不含空格的原字符串、待查找字符串和替换字符串。将原字符串中第一次出现的待查找内容替换掉,并输出替换结果;若未找到,输出 NOT FOUND。找到时还要输出替换位置之前的前缀。

输入格式: 依次输入原字符串、待查找字符串和替换字符串,三者均不含空格。

输出格式: 找到时第一行输出替换后的字符串,第二行输出原字符串中匹配位置之前的部分;未找到时输出 NOT FOUND

数据范围: 每个字符串长度不超过 200。

输入样例:

abc123abc 123 XYZ

输出样例:

abcXYZabc
abc

解题思路:find 获得首次位置;用 replace 替换,用 substr 截取前缀。

参考代码:

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

int main() {
    string source, target, replacement;
    cin >> source >> target >> replacement;
    size_t position = source.find(target);
    if (position == string::npos) {
        cout << "NOT FOUND";
    } else {
        string prefix = source.substr(0, position);
        source.replace(position, target.size(), replacement);
        cout << source << "\n" << prefix;
    }
    return 0;
}

易错提醒: 未找到时 find 返回 string::npos,不能直接拿这个位置去替换或截取。

课堂4忽略格式的回文句【适中】

题目描述: 输入一整行字符串,忽略空格和英文字母大小写后,判断它是否为回文串。

输入格式: 输入一整行字符串。

输出格式: 是回文串输出 YES,否则输出 NO

数据范围: 字符串长度不超过 500只含英文字母和空格。

输入样例:

Never odd or even

输出样例:

YES

解题思路: 先构造一个无空格、全小写的新字符串,再用左右下标向中间比较。

参考代码:

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

int main() {
    string s, cleaned;
    getline(cin, s);
    for (char c : s) {
        if (c != ' ') cleaned += (char)tolower(c);
    }
    bool palindrome = true;
    int left = 0, right = (int)cleaned.size() - 1;
    while (left < right) {
        if (cleaned[left] != cleaned[right]) {
            palindrome = false;
            break;
        }
        left++;
        right--;
    }
    cout << (palindrome ? "YES" : "NO");
    return 0;
}

易错提醒: 比较前必须统一大小写;空字符串和单字符都属于回文串。

二、课后作业3题

课后1字符串长度【简单】

题目描述: 输入一个不含空格的字符串,输出它的长度。

输入格式: 输入一个不含空格的字符串。

输出格式: 字符串长度。

数据范围: 字符串长度为 1200。

输入样例:

orange

输出样例:

6

解题思路: 使用字符串的 size 获取长度。

参考代码:

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

int main() {
    string s;
    cin >> s;
    cout << s.size();
    return 0;
}

易错提醒: 长度是字符个数,最后一个字符的下标是长度减 1。

课后2统计指定字符【简单】

题目描述: 输入一个不含空格的字符串和一个字符,统计该字符出现次数。

输入格式: 输入一个字符串和一个待统计字符。

输出格式: 指定字符出现次数。

数据范围: 字符串长度不超过 200。

输入样例:

banana a

输出样例:

3

解题思路: 遍历字符串,字符相等时计数。

参考代码:

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

int main() {
    string s;
    char target;
    int count = 0;
    cin >> s >> target;
    for (char c : s) {
        if (c == target) count++;
    }
    cout << count;
    return 0;
}

易错提醒: 字符使用单引号概念,字符串使用双引号概念。

课后3字符串逆序【简单】

题目描述: 输入一个不含空格的字符串,将它逆序输出。

输入格式: 输入一个不含空格的字符串。

输出格式: 逆序后的字符串。

数据范围: 字符串长度不超过 200。

输入样例:

GESP

输出样例:

PSEG

解题思路: 从最后一个下标向 0 倒序输出。

参考代码:

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

int main() {
    string s;
    cin >> s;
    for (int i = (int)s.size() - 1; i >= 0; i--) cout << s[i];
    return 0;
}

易错提醒: 倒序循环变量应使用有符号整数,否则减到 0 以下时可能出错。

三、扩展练习7题

扩展1大小写交替转换【基础综合】

题目描述: 输入一个不含空格的字符串,把大写字母转成小写、小写字母转成大写,其他字符保持不变。

输入格式: 输入一个不含空格的字符串。

输出格式: 转换后的字符串。

数据范围: 字符串长度不超过 200。

输入样例:

AbC123xY

输出样例:

aBc123Xy

解题思路: 遍历并按 ASCII 范围判断,分别调用大小写转换函数。

参考代码:

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

int main() {
    string s;
    cin >> s;
    for (char &c : s) {
        if (c >= 'A' && c <= 'Z') c = (char)tolower(c);
        else if (c >= 'a' && c <= 'z') c = (char)toupper(c);
    }
    cout << s;
    return 0;
}

易错提醒: 数字和符号不要改变。

扩展2删除指定字符【基础综合】

题目描述: 输入一整行字符串和一个字符,删除字符串中所有该字符后输出结果。

输入格式: 第一行输入一整行字符串;第二行输入待删除字符。

输出格式: 删除后的字符串。

数据范围: 原字符串长度不超过 500。

输入样例:

a cat and a hat
a

输出样例:

 ct nd  ht

解题思路: 构造新字符串,只加入不等于目标的字符。

参考代码:

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

int main() {
    string s, answer;
    char target;
    getline(cin, s);
    cin >> target;
    for (char c : s) {
        if (c != target) answer += c;
    }
    cout << answer;
    return 0;
}

易错提醒: 删除字符后空格仍需保留。

扩展3单词数量【中等】

题目描述: 输入一整行英文句子,单词之间可能有多个空格,统计单词数量。

输入格式: 输入一整行英文句子。

输出格式: 单词数量。

数据范围: 句子长度不超过 500只含英文字母和空格。

输入样例:

  I   love Cpp

输出样例:

3

解题思路: 当当前位置是字母,且它是首字符或前一个字符为空格时,说明一个新单词开始。

参考代码:

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

int main() {
    string s;
    getline(cin, s);
    int count = 0;
    for (int i = 0; i < (int)s.size(); i++) {
        if (s[i] != ' ' && (i == 0 || s[i - 1] == ' ')) count++;
    }
    cout << count;
    return 0;
}

易错提醒: 不能用空格数加一,因为句首、句尾和连续空格都会造成错误。

扩展4查找所有位置【中等】

题目描述: 输入原字符串和一个字符,输出该字符出现的所有位置,位置从 1 开始;若没有出现,输出 NONE

输入格式: 输入一个不含空格的字符串和一个待查找字符。

输出格式: 所有出现位置或 NONE

数据范围: 字符串长度不超过 500。

输入样例:

mississippi s

输出样例:

3 4 6 7

解题思路: 完整遍历而不提前结束,每次匹配都输出当前位置加一。

参考代码:

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

int main() {
    string s;
    char target;
    cin >> s >> target;
    int count = 0;
    for (int i = 0; i < (int)s.size(); i++) {
        if (s[i] == target) {
            if (count) cout << " ";
            cout << i + 1;
            count++;
        }
    }
    if (count == 0) cout << "NONE";
    return 0;
}

易错提醒: 题目要求所有位置,不能找到第一个后使用 break

扩展5连续字符压缩【中等】

题目描述: 输入一个仅含英文字母的字符串,将连续相同字符压缩为“字符加次数”。即使只出现一次,也要输出次数。

输入格式: 输入一个仅含英文字母且不含空格的字符串。

输出格式: 压缩后的字符串。

数据范围: 字符串长度为 1500。

输入样例:

aaabbcaaaa

输出样例:

a3b2c1a4

解题思路: 记录当前连续段的字符和长度;遇到不同字符时输出上一段,最后补输出末段。

参考代码:

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

int main() {
    string s;
    cin >> s;
    char current = s[0];
    int count = 1;
    for (int i = 1; i < (int)s.size(); i++) {
        if (s[i] == current) {
            count++;
        } else {
            cout << current << count;
            current = s[i];
            count = 1;
        }
    }
    cout << current << count;
    return 0;
}

易错提醒: 循环结束后最后一段尚未输出,必须单独处理。

扩展6最长回文前缀【略难】

题目描述: 输入一个不含空格的字符串,找出从第一个字符开始的最长回文子串并输出。

输入格式: 输入一个不含空格的字符串。

输出格式: 最长回文前缀。

数据范围: 字符串长度为 1200。

输入样例:

abacdf

输出样例:

aba

解题思路: 从整个字符串长度开始递减,检查前缀两端是否对称;第一个成功的就是最长答案。

参考代码:

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

int main() {
    string s;
    cin >> s;
    for (int length = (int)s.size(); length >= 1; length--) {
        bool palindrome = true;
        for (int left = 0, right = length - 1; left < right;
             left++, right--) {
            if (s[left] != s[right]) {
                palindrome = false;
                break;
            }
        }
        if (palindrome) {
            cout << s.substr(0, length);
            break;
        }
    }
    return 0;
}

易错提醒: 检查的是从下标 0 开始的前缀,不是任意位置的回文子串。

扩展7两串是否由相同字母组成【略难】

题目描述: 输入两个只含小写字母的字符串,判断它们是否包含完全相同的字母及出现次数,字符顺序可以不同。

输入格式: 输入两个只含小写字母且不含空格的字符串。

输出格式: 满足条件输出 YES,否则输出 NO

数据范围: 每个字符串长度不超过 500。

输入样例:

listen silent

输出样例:

YES

解题思路: 使用长度为 26 的计数数组;遍历第一个字符串时加一,遍历第二个时减一,最后全部为零才匹配。

参考代码:

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

int main() {
    string a, b;
    cin >> a >> b;
    int count[26] = {0};
    for (char c : a) count[c - 'a']++;
    for (char c : b) count[c - 'a']--;
    bool same = true;
    for (int i = 0; i < 26; i++) {
        if (count[i] != 0) {
            same = false;
            break;
        }
    }
    cout << (same ? "YES" : "NO");
    return 0;
}

易错提醒: 只比较字符串长度不够,必须比较每个字母的出现次数。