1 字符与整数之间的关系
在 C++中单个字符是使用 ASCII 进行编码的,因此 C++中的单字符又称为 ASCII 字符或 ASCII 码。每个常用字符都对应着 0 ~ 127 之间的一个整数,二者之间是可以相互转换的。例如 'a' 对应的数字是 97,'A' 对应的数字是 65。
#include <bits/stdc++.h>
using namespace std;
int main() {
cout << (int)'a' << endl;
cout << (char)97 << endl;
return 0;
}常用的
ASCII值:
A ~ Z是65 ~ 90,a ~ z是97 ~ 122,0 ~ 9是48 ~ 57。
提示:字符可以参与运算,运算时字符按对应的整数处理。
2 字符数组
由单个字符组成的数组称为字符数组。如果字符数组的最后一个元素是 '\0' 那么这个字符数组就是字符串。
我们可以使用字符串来初始化字符数组,需要注意的是,每个字符串的结尾会暗含一个 '\0' 字符,因此字符数组的长度至少要比字符串的长度多
char s[10], ss[10][100];
char s1[] = {'z', 'z', 's', 'z'};
char s2[] = {'z', 'z', 's', 'z', '\0'};
char s3[] = "zzsz";
char s4[4] = "zzsz"; // 错误2.1 字符数组的输入输出
- 读入时:
cin和scanf以空格或是回车作为字符串的结尾 - 输出时:
cout和printf以'\0'作为字符串的结尾
#include <cstdio>
using namespace std;
int main() {
char s[1000];
// 输入 let's go
scanf("%s", s);
printf("%s\n", s); // 输出:let's
return 0;
}读入时可以指定字符串存储的起始地址:scanf("%s", s + 1);。需要注意的时,这时输出不能这样写 printf("%s\n", s); (什么也不输出,因为 s[0] = '\0')而应该这样写 printf("%s\n", s + 1); 。
如何读入一行带空格或者是回车换行的字符串呢?
fgetscpp#include <cstdio> using namespace std; int main() { // 输入 let's go char s[1000]; // gets函数在新版C++中被移除了,因为不安全。 // 可以用fgets代替,但注意fgets不会删除行末的回车字符 fgets(s, 1000, stdin); printf("%s\n", s); // 输出:let's go 加两个回车 return 0; }getcharcpp#include <cstdio> using namespace std; int main() { // 输入 let's go char s[1000]; int n = 0; while ((s[n++] = getchar()) != '\n'); // 读到回车换行结束 s[n] = '\0'; // 将换行符转化为字符串结尾字符 printf("%s\n", s); return 0; }
2.2 字符数组的常用操作
以下函数需要引入头文件:
#include <cstring>strlen(str):求字符串的长度strcmp(a, b):按字典序比较两个字符串的大小,a > b返回1,a < b返回-1,a == b返回0。strcpy(a, b):将字符串b复制给从a的首地址开始的字符数组。strncpy(a, b, n):将字符串b的前个字符复制给从 a的首地址开始的字符数组。strcat(a, b):将字符串b拼接到a的末尾。strstr(a, b):判断b是否是a的子串,如果是,返回b在a中首次出现 的地址,否则,返回NULL(空地址)
2.3 遍历字符数组
#include <cstdio>
#include <cstring>
using namespace std;
int main() {
char s[100] = "hello world!";
int n = strlen(s);
for (int i = 0; i < n; i++) {
printf("%c\n", s[i]);
}
return 0;
}3 标准库类型:string
标准库提供了一种可变长的字符序列 string,比字符数组更加好用。需要引入头文件:
#include <string>3.1 定义和初始化
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1; // 默认初始化为空字符串
string s2 = s1; // s2是s1的副本,注意s2只是与s1的值相同,并不指向同一段地址
string s3 = "Hello"; // s3是该字符串字面值的副本
string s4(3, 'a'); // s4的内容是 "aaa"
return 0;
}3.2 string的输入和输出
string的输入和输出使用的是cin和cout,不能使用scanf和printf。getline可以读入一行cpp#include <iostream> #include <string> using namespace std; int main() { // 输入 let's go string s; getline(cin, s); cout << s << endl; return 0; }
3.3 string的常用操作
两个常用函数:
empty:判断string是否为空,为空返回true。size:返回string的长度。length:返回string的长度。
string 按字典序比较大小:
- 直接使用
>、<、>=、<=、!=、==。
string 加法:
string a = "hello", b = "world\n";
string c = a + b;
c += a;
string d = c + '\n';
string s = c + "hello" + "world\n"; // 正确
string str = "hello" + "world\n" + c; // 错误当把 string 对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符的两侧的运算对象至少有一个是 string。
3.4 将string当成字符数组
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "hello world";
for (int i = 0; i < s.size(); i ++ )
cout << s[i] << endl;
// 增强 for 循环
for (char c : s) cout << c << endl;
// 修改 s 的每一个字符
for (char &c : s) c = 'c';
cout << s << endl;
return 0;
}3.5 string数组
string strs[10];
strs[0] = "you";
strs[1] = "are";
strs[2] = "hero";4 习题讲解
4.1 YBT 1129:统计数字字符个数
- 考察点:基础知识,ASCII 值
#include <bits/stdc++.h>
using namespace std;
const int N = 260;
char s[N];
int main() {
int n =0;
while ((s[n++] = getchar()) != '\n');
s[--n] = '\0';
int cnt = 0;
for (int i = 0; i < n; i++) {
if (s[i] >= '0' && s[i] <= '9') cnt++;
}
cout << cnt << endl;
return 0;
}4.2 YBT 1146:判断字符串是否为回文
- 考察点:字符串遍历
#include <bits/stdc++.h>
using namespace std;
int main() {
char s[1010];
cin >> s;
int len = strlen(s);
bool flag = true;
for (int i = 0, j = len - 1; i < len; i++, j--) {
if (s[i] != s[j]) {
flag = false;
break;
}
}
if (flag) cout << "yes" << endl;
else cout << "no" << endl;
return 0;
}4.3 YBT 2046:替换字母
- 考察点:带空格字符串的读入
#include <bits/stdc++.h>
using namespace std;
int main() {
char s[250];
int n = 0;
while ((s[n++] = getchar()) != '\n') ;
s[n] = '\0';
char o, p;
scanf("%c %c", &o, &p); // 注意这里的输入格式
for (int i = 0; s[i] != '\0'; ++i) {
if (s[i] == o) {
printf("%c", p);
} else {
printf("%c", s[i]);
}
}
return 0;
}4.4 YBT 2047:过滤空格
- 考察点:空格处理
#include <bits/stdc++.h>
using namespace std;
int main() {
char s[250];
while (scanf("%s", s) != -1) {
printf("%s ", s);
}
return 0;
}4.5 YBT 2049:字符串判等
- 考察点:大小写字符的转换,ASCII 值
#include <bits/stdc++.h>
using namespace std;
int main() {
char s[250], s2[250];
int len = 0, len2 = 0;
char c;
while (c = getchar()) {
if (c == '\n') break;
if (c == ' ') continue;
if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
s[len++] = c;
}
s[len] = '\0';
while (c = getchar()) {
if (c == '\n') break;
if (c == ' ') continue;
if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
s2[len2++] = c;
}
s2[len2] = '\0';
if (strcmp(s, s2) == 0) {
puts("YES");
} else {
puts("NO");
}
return 0;
}4.6 YBT 2050:字串包含
- 考察点:字符串的常用函数
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1, s2;
cin >> s1 >> s2;
if (s1.length() < s2.length()) {
swap(s1, s2);
}
s1 = s1 + s1;
if (s1.find(s2) != s1.npos) {
cout << "true" << endl;
} else {
cout << "false" << endl;
}
return 0;
}4.7 YBT 1143:最长最短单词
- 考察点:string
#include <bits/stdc++.h>
using namespace std;
int main() {
string s;
getline(cin, s);
int tmp = 0, maxx = -1e9, minn = 1e9, minidx = 0, maxidx = 0;
s += ' ';
for (int i = 0; i < s.size(); i++) {
if (s[i] != ' ' && s[i] != ',' && s[i] != '.')
tmp++;
else if (tmp > 0) {
if (tmp > maxx) {
maxx = tmp;
maxidx = i - tmp;
}
if (tmp < minn) {
minn = tmp;
minidx = i - tmp;
}
tmp = 0;
}
}
for (int i = maxidx; i <= maxx + maxidx - 1; i++)
cout << s[i];
cout << endl;
for (int i = minidx; i <= minidx + minn - 1; i++)
cout << s[i];
cout << endl;
return 0;
}4.8 YBT 1839:谁拿了最多奖学金
- 考察点:字符串,整数等混合读入问题
#include <iostream>
using namespace std;
const int N = 110;
char name[N][25], info[N][2];
int grade[N][2], paper[N];
int main() {
int n; scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%s %d %d %c %c %d", name[i], &grade[i][0], &grade[i][1], &info[i][0], &info[i][1], &paper[i]);
}
int total = 0, maxv = -1, idx = -1;
for (int i = 0; i < n; i++) {
int p = 0;
if (grade[i][0] > 80 && paper[i] >= 1) p += 8000;
if (grade[i][0] > 85 && grade[i][1] > 80) p += 4000;
if (grade[i][0] > 90) p += 2000;
if (grade[i][0] > 85 && info[i][1] == 'Y') p += 1000;
if (grade[i][1] > 80 && info[i][0] == 'Y') p += 850;
total += p;
if (p > maxv) {
maxv = p;
idx = i;
}
}
printf("%s\n%d\n%d\n", name[idx], maxv, total);
return 0;
}4.9 x 进制转 10 进制
题目描述
给一个小整数 A,B,
输入格式
第一行一个整数
第二行一个字符串
输出格式
输出仅包含一个整数,表示答案。
样例 #1
样例输入 #1
16
7B样例输出 #1
123提示
【数据规模和约定】
保证目标数在十进制下不超过
参考代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
int r; cin >> r;
char x[50];
cin >> x;
int ans = 0;
for (int i = 0; i < strlen(x); i++) {
int t = x[i] >= 'A' && x[i] <= 'Z' ? x[i] - 'A' + 10 : x[i] - '0';
ans = ans * r + t;
}
cout << ans << endl;
return 0;
}4.10 10 进制转 x 进制
题目描述
给定一个十进制整数 A,B ... 表示。
输入格式
第一行一个整数
第二行一个整数
输出格式
输出仅包含一个整数,表示答案。
样例 #1
样例输入 #1
1000
2样例输出 #1
1111101000提示
【数据规模和约定】
保证
参考代码
#include<cmath>
#include<iostream>
using namespace std;
int a[100000000];
void f(int x, int r) {
// a 数组存储进制转换后的每一位
char c[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
int idx = 0;
while (x != 0) {
a[idx++] = x % r;
x /= r;
}
idx--;
for (int i = idx; i >= 0; i--) {
if (a[i] < 10) cout << a[i];
else cout << c[a[i] - 10];
}
}
int main()
{
int r, x;
cin >> x >> r;
f(x, r);
return 0;
}