- 大纲要求
- 字符类型和字符数组
- sscanf从字符串格式化输入
- 找第一个只出现一次的字符">例题, 找第一个只出现一次的字符
- 验证子串">例题,验证子串
- 删除单词后缀">例题,删除单词后缀
- 单词的长度">例题,单词的长度
- 单词翻转">例题,单词翻转
大纲要求
•【2】字符数组与字符串的关系
•【2】字符数组的综合应用
•【2】string类定义、相关函数引用
•【3】string类的综合应用
字符类型和字符数组
// 字符类型char c;int a[N];double a[N];bool a[N];// 字符数组char s[N];char s[N][N];/*.#...#...#..#.....*/// 界定符'a' 字符 ' '"a" 字符串 "abc" "" " "a[0] = '\n';cout << a[0];#include <bits/stdc++.h>using namespace std;int main(){cout << sizeof ('a') << '\n';cout << sizeof ("a") << '\n';return 0;}/*12*/字符占一个字节,“a”会增加一个字节,用来存放字符串结束符'\0',所以占2字节
// 字符串读入#include <cstdio>using namespace std;char s[110];int main(){scanf("%s", s);printf("%s\n", s);int len = strlen(s);printf("%d\n", len);return 0;}
// string类#include <iostream>using namespace std;int main(){string s;cin >> s;cout << s << '\n';return 0;}
// 读入一整行// ab cd ed#include <iostream>using namespace std;int main(){string s;getline(cin, s);cout << s << '\n';return 0;}
// string类的字符串处理函数#include <iostream>#include <cstring>using namespace std;int main(){string s;s = "abcdef";cout << s << '\n';cout << s.size() << '\n'; //输出字符串大小cout << s.substr(2) << '\n'; //截取子串,是位置2开始往后所有cout << s.substr(2, 3) << '\n'; //从位置2开始,截取三位return 0;}
// 字符串长度char s[110];scanf("%s", s);int len = strlen(s); // 字符数组,对应 strlenstring s;cin >> s;int len = s.size(); // string,对应 .size()
// string::operator+=#include <iostream>#include <string>int main (){std::string name ("John");std::string family ("Smith");name += " K. "; // c-stringname += family; // stringname += '\n'; // characterstd::cout << name;return 0;}
// string::substr#include <iostream>#include <string>int main (){std::string str="We think in generalities, but we live in details.";// (quoting Alfred N. Whitehead)std::string str2 = str.substr (3,5); // "think"std::size_t pos = str.find("live"); // position of "live" in strstd::string str3 = str.substr (pos); // get from "live" to the endstd::cout << str2 << ' ' << str3 << '\n';return 0;}
// insert#include<iostream>using namespace std;int main(){string s="to be question";string s2="the ";s.insert(6, s2); // to be (the )questioncout << s << '\n';return 0;}
// c_str(),string 转 char*#include<iostream>using namespace std;int main(){string s("Please split this sentence into tokens");char *cstr = new char[s.size()+1];strcpy (cstr, s.c_str());printf("%s\n", cstr);return 0;}
// 二维字符数组,如何有效读入的问题#include <iostream>#include <cstdio>using namespace std;const int N = 110;char s[N][N];int n, m;int main(){cin >> n >> m;for (int i = 0; i < n; i++) scanf("%s", s[i]);for (int i = 0; i < n; i++) printf("%s\n", s[i]);return 0;}/*.....#####.####..###.#..*/// 如何是下面的写法,是容易被输入数据坑的for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)scanf("%c", &s[i][j]);// 虽然我们提前知道了每一行每一列有多少个数字,但是这种操作经常被坑// 原因是,测试数据,可能每一行的后面有一个空格,一个我们看不见的空格// 你的代码里,会把这个空格当成一个字符读入。然后,自然读入的数据就不准确了for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)cin >> s[i][j];// 这样倒是可以解决问题,但这并不如上面一层循环更靠谱,尤其当数据量特别大的时候

【扩展阅读】C++中字符串的结尾标志 \0
\0是C++中字符串的结尾标志,存储在字符串的结尾,它虽然不计入串长,但要占一个字节的内存空间。在百度百科中查看\0词条,会有这样一句话:c/c++中规定字符串的结尾标志为'\0'。有人可能认为,在C语言里(C++会不同),'\0'并不是字符型,而是int型。在这里,我们姑且和百度词条作者保持一致,认为\0与'\0'是等价的。由于不同处理器的位数不同,'\0'并不一定是8位的00000000。实际上,由于不同处理器的位数不同,sizeof(int)返回的结果也都不同,而sizeof(char)返回结果一般是1,对8位机来说,一个字节由8位组成,16位机一个字节由16位组成,我们通常用的电脑通常是32位的,即一个字节由32位组成,现在已经是64位机了。CPU一般是以字节为单元进行读取的。但是一般情况下大家还是认同1Byte等于8bit的说法,因为这是构成的最小位数。'\0'是转义字符,意思是告诉程序,这不是数字0。'\0'和0两者基本上可以通用,例如: string[i] != '\0'和string[i] != 0是一样的。不过'\0'的类型是char型,而0是int类型,所以在大多数计算机上,sizeof(0) = 4而sizeof('\0') = 1,这在特殊情况下不可通用。另外扩展一下,'\0'与'0'也是不同的,他们都是字符,但是他们的ASCII码是不同的:'\0' ASCII码值为0,'0' 也可以写成'\0x30' ASCII码值为48。在C语言中没有专门的字符串变量,通常用一个字符数组来存放一个字符串。字符串总是 以'\0'作为串的结束符。因此当把一个字符串存入一个数组时,也把结束符 '\0'存入数组,并以此作为该字符串是否结束的标志。有了'\0'标志后, 就不必再用字符数组的长度来判断字符串的长度了。'\0'就是 字符串结束标志。比如说,把一个字符串赋值给数组:char str1[] = {"Welcome!"}。实际上数组str1在内存中的实际存放情况为: 'W' 'e' 'l' 'c' 'o' 'm' 'e' '!' '\0'。这后面的'\0'是由C编译系统自动加上的。所以在用字符串赋初值时一般无须指定数组的长度, 而由系统自行处理。 把字符数组str1中的字符串拷贝到字符数组str2中。串结束标志'\0'也一同拷贝。
// ASCII码相关的东西,可以百度// 观察大小写的规律,会相互转化// 会数字1和字符'1'的转化#include <bits/stdc++.h>using namespace std;const int N = 110;char s[N];int cnt[30];int main(){scanf("%s", s); // they are lowercasefor (int i = 0; s[i]; i++)cnt[s[i] - 'a']++;for (int i = 0; i < 26; i++) cout << cnt[i] << ' ';puts("");return 0;}

sscanf从字符串格式化输入
#include <bits/stdc++.h>using namespace std;const int N = 30;char s[] = "Saturday March 25 1989";char month[N], weekday[N];int year, day;int main(){sscanf(s, "%s %s %d %d", weekday, month, &day, &year);printf("%d %s %d\n", day, month, year);return 0;}
// CSP-J2021 T3网络连接// 读入数据用sscanf就相当的妙// 而我赛场上,只会用字符串,一点一点拆。。 差距显然#include <bits/stdc++.h>using namespace std;int a, b, c, d, e;char s[] = "192.168.1.1:8080";int main(){sscanf(s, "%d.%d.%d.%d:%d", &a, &b, &c, &d, &e);printf("%d.%d.%d.%d:%d\n", a, b, c, d, e);return 0;}
例题, 找第一个只出现一次的字符
#include <bits/stdc++.h>using namespace std;const int N = 1e5 + 10;char s[N];int vis[30];int main(){scanf("%s", s);int len = strlen(s);for (int i = 0; i < len; i++)vis[s[i] - 'a']++;bool flag = false;for (int i = 0; i < len; i++){if (vis[s[i] - 'a'] == 1){flag = true;printf("%c\n", s[i]);break;}}if (!flag) printf("no\n");return 0;}
例题,验证子串
//string s;//s.find()#include <bits/stdc++.h>using namespace std;int main(){string s1, s2;cin >> s1 >> s2;int ans = 0;if (s1.find(s2) != -1) ans = 1;else if (s2.find(s1) != -1) ans = -1;if (ans == 1) cout << s2 << " is substring of " << s1 << endl;else if (ans == -1) cout << s1 << " is substring of " << s2 << endl;else cout << "No substring" << endl;return 0;}
例题,删除单词后缀
// string s;// s.erase(len - 2)// 使用char s[40];// 匹配后缀成功后,利用s[len-2] = '\0'进行截断
例题,单词的长度
// 第一种方法,直接手搓// getline(cin, s);// 然后遍历,碰到空格算一个单词// 要注意输出的格式#include <bits/stdc++.h>using namespace std;int main(){string s;getline(cin, s);bool flag = false;for (int i = 0, len = s.size(); i < len; i++){while (s[i] == ' ') i++;if (flag) printf(",");flag = true;int j = i;int cnt = 0;while (j < len && s[j] != ' ') j++;printf("%d", j - i);i = j - 1;}puts("");return 0;}// 第二种方法// 使用while (cin >> s),更好编写// 不过要注意一下格式控制的小技巧// 本地调试要使用freopen#include <bits/stdc++.h>using namespace std;int main(){//freopen("1.in", "r", stdin);string s;bool flag = false;while (cin >> s){if (flag) cout << ',';flag = true;int len = s.size();cout << len;}puts("");return 0;}
例题,单词翻转
//getline(cin, s);//比较麻烦,构造一个一个单词出来,然后翻转//使用while (cin >> s)//会两个点,格式错误,调不出来

