一、字符数组基础
1.1 声明与初始化
char arr1[10]; // 声明未初始化 char arr2[5] = {'H','e','l','l','o'}; // 完全初始化 char arr3[] = "World"; // 自动推断长度6(含\0)
1.2 关键特性
-
内存连续:每个字符占用1字节
-
结束标志:以'\0'(ASCII 0)作为终止符
-
部分初始化:未显式初始化的元素自动补'\0'
char str[10] = "Hi"; // 实际存储:['H','i','\0','\0',...,'\0']
二、字符数组操作
2.1 输入输出
char buffer[100]; cin >> buffer; // 遇到空格终止 cin.getline(buffer, 100); // 读取整行(含空格) cout<<buffer;
2.2 常用函数
#include <cstring> char text[50] = "Hello"; cout << strlen(text); // strlen计算char数组中(不计\0)的长度 strcat(text, " World"); // 拼接字符串 strcmp(text, "Test"); // 比较内容
三、string类进阶
3.1 核心优势
-
动态内存管理:自动调整存储空间
-
安全边界检查:避免缓冲区溢出
-
丰富操作接口:自带拼接、查找、替换等方法
3.2 基础操作
#include <string> string s1; // 空字符串 string s2 = "Hello"; // 直接初始化 string s3(5, 'A'); // "AAAAA" // 安全输入 getline(cin, s1); // 读取整行含空格
3.3 字符串操作
// 拼接 string msg = s2 + " " + "World"; // "Hello World" // 比较 if(s2.compare("Hello") == 0) { cout << "字符串相等"; } // 长度获取 cout << msg.length(); // 输出11
四、类型对比指南
特性 | 字符数组 | string类 |
---|---|---|
内存管理 | 静态分配,固定大小 | 动态分配,自动扩容 |
结束符 | 必须手动维护\0 | 自动管理 |
越界风险 | 高危 | 安全防护 |
函数支持 | 依赖<cstring>库函数 | 内置丰富方法 |
赋值操作 | strcpy/手动复制 | 直接=赋值 |
适用场景 | 底层开发、C兼容接口 | 常规字符串处理 |
五、典型错误警示
-
越界写入
char danger[5]; strcpy(danger, "HelloWorld"); // 缓冲区溢出!
2.错误比较
if(str == "Test") {} // string正确用法 if(arr == "Test") {} // 错误!比较地址
3.遗漏头文件
#include <string> // 必须包含头文件
六、练习
题目1:文章检错:
编写一个程序,用来判断英文名句书写是否正确。当输入正确时屏幕上就会显示”Right”,不正确就显示“Wrong” 。
输入:All for one, one for all
输出:Right
输入:all for one, one for all
输出:Wrong
参考代码:
#include <iostream>
#include <cstring>
using namespace std;
int main() {
char correct[] = "All for one, one for all";
char input[100];
cin.getline(input, 100);
if (strcmp(input, correct) == 0)
cout << "Right" << endl;
else
cout << "Wrong" << endl;
return 0;
}
题目2:整理药名
医生在书写药品名的时候经常不注意大小写,格式比较混乱。现要求你写一个程序将医生书写混乱的药品名整理成统一规范的格式,即药品名的第一个字符如果是字母要大写,其他字母小写。如将ASPIRIN、aspirin整理成Aspirin。
输入格式: 第一行一个数字n,表示有n个药品名要整理,n不超过100。 接下来n行,每行一个单词,长度不超过20,表示医生手书的药品名。药品名由字母、数字和-组成。
输出格式: n行,每行一个单词,对应输入的药品名的规范写法。
输入样例: 4
AspiRin
cisapride
2-PENICILLIN
Cefradine-6
输出样例: Aspirin
Cisapride
2-penicillin
Cefradine-6
题目3:找出第一个只出现一次的字母
给定一个只包含小写字母的字符串,请你找到第一个仅出现一次的字符。如果没有,输出no。
输入格式:一个字符串,长度小于100000
输出格式:输出第一个仅出现一次的字符,若没有则输出no
输入样例:abcabd
输出样例:c
参考代码:
#include <iostream>
#include <string>
using namespace std;
int main() {
int n;
cin >> n;
string s;
while (n--) {
cin >> s;
if (!s.empty()) {
// 处理首字母
if (islower(s[0])) s[0] = toupper(s[0]);
// 处理后续字符
for (int i = 1; i < s.size(); ++i)
if (isupper(s[i])) s[i] = tolower(s[i]);
}
cout << s << endl;
}
return 0;
}
题目4:石头剪刀布:
石头剪子布,是一种猜拳游戏。起源于中国,然后传到日本、朝鲜等地,随着亚欧贸易的不断发展它传到了欧洲,到了近现代逐渐风靡世界。简单明了的规则,使得石头剪子布没有任何规则漏洞可钻,单次玩法比拼运气,多回合玩法比拼心理博弈,使得石头剪子布这个古老的游戏同时用于“意外”与“技术”两种特性,深受世界人民喜爱。 游戏规则:石头打剪刀,布包石头,剪刀剪布。 现在,需要你写一个程序来判断石头剪子布游戏的结果。
输入格式:输入包括N+1行: 第一行是一个整数N,表示一共进行了N次游戏。1 <= N <= 100。 接下来N行的每一行包括两个字符串,表示游戏参与者Player1,Player2的选择(石头、剪子或者是布): S1 S2字符串之间以空格隔开S1,S2只可能取值在{"Rock", "Scissors", "Paper"}(大小写敏感)中。
输出格式:输出包括N行,每一行对应一个胜利者(Player1或者Player2),或者游戏出现平局,则输出Tie。
输入样例: 3
Rock Scissors
Paper Paper
Rock Paper
输出样例: Player1
Tie
Player2
参考代码:
#include <iostream>
#include <string>
using namespace std;
int main() {
int n;
cin >> n;
string a, b;
while (n--) {
cin >> a >> b;
if (a == b) {
cout << "Tie" << endl;
} else if ((a == "Rock" && b == "Scissors") ||
(a == "Scissors" && b == "Paper") ||
(a == "Paper" && b == "Rock")) {
cout << "Player1" << endl;
} else {
cout << "Player2" << endl;
}
}
return 0;
}
题目5:回文子串
给定一个字符串s1,输出所有长度为4的回文子串(保证s1的长度不小于4) 回文子串即从左往右输出和从右往左输出结果是一样的字符串,比如:abba,cccdeedccc都是回文字符串。
输入格式: 一个字符串,由字母或数字组成,长度500以内
输出格式: 输出所有长度为4的回文子串,每个子串一行 出现位置靠左的优先输出,若没有,则输出“no”
输入样例1: 1233211257
输出样例1: 2332 2112
输入样例2: cccdee
输出样例2: no
参考代码:
#include <iostream>
#include <string>
using namespace std;
bool isPalindrome(string s) {
return s[0] == s[3] && s[1] == s[2];
}
int main() {
string s;
cin >> s;
bool found = false;
for (int i = 0; i <= s.size() - 4; ++i) {
string sub = s.substr(i, 4);
if (isPalindrome(sub)) {
cout << sub << endl;
found = true;
}
}
if (!found) cout << "no" << endl;
return 0;
}