C/C++语法:(二)字符串
1.常见ASCII码记忆
2.char字符串及定义方式
其实就是字符数组末尾加上一个字符 '\0',因此长度比字符数组的长度多1. 另外'\0'和空格并不是同一个东西,二者的ASCII码不一样.
所以这东西其实不是很好用,建议直接用C++的string就完事辣.
字符串的初始化方式:
char a1[] = {'C', '+', '+', '\0'}; //注意这个末尾的0必须要添加
char a2[] = "C++"; //末尾自动添加0
C中字符串的细节实在是太多了,比如:
char a1[] = {'c','+','+'};
char a2[] = {'B','+','+','\0'};
char a3[] = "C++";
如果打印输出\(a1\),会惊奇地发现\(a2\)也被打印了,这是因为编译器实现字符数组的储存为栈式结构,由于\(a1\)末尾并没有添加空字符\(0\),因此它一定会继续打印直到遇到'\(\0\)'. 所以建议不要用这个麻烦东西了,c++中的string大法正在呼唤你.
不过说是这么说,有些学校机试压根就不让你用C++呢,而且如果用string做题超时了,那也就只能卑微使用char数组了.
3.char字符串输入
char s[100];
scanf("%s", s);
以上scanf输入在遇到空格、回车、文件终止时才会停止接受输入,例如:
输入abc def,因为碰到了空格,最后只有abc会被接收.如果想接收一整行可以使用以下几种方法:
char s[100];
fgets(s, 100, stdin);
//第2个参数表示最多读入多少
//注意fgets会读入回车,因此字符串长度很可能会多1,做题时要注意过滤回车,加个s[i] != '\n'条件
char s[100];
cin.getline(s, 100);
string s;
getline(cin ,s); //用于c++中的string
需要额外注意的是char数组在输入时遇到空格回车一定会停下来,即使用的是cin也会停下来. 想读一整行只能用getline.
4.char字符串输出
char s[100];
scanf("%s", s);
printf("%s\n", s);
puts(s); //puts在输出字符串之后换行
5.char字符串常用函数
以下几个函数位于<string.h/库中:
#include <string.h>
char s[100];
scanf("%s", s);
...
cout << strlen(s) << endl; //求字符串长度,并不包括'\0',是多长就是多长
cout << strcmp(s1, s2) << endl; //比较大小,s1>s2输出1,小为-1,等为0
strcpy(a ,b); //把字符串b赋值给a
y总のtrick:strlen(s)内部实现其实也就是遍历字符数组,考虑以下代码:
for (int i = 0; i < strlen(s); i ++)
cout << s[i] << endl;
看上去是\(O(n)\),实际上有两重循环,所以或许差不多是\(O(n^2)\),在某些情况下,很可能就会超时了,代码可优化为以下形式:
for (int i = 0, len = strlen(s); i < len; i ++)
cout << s[i] << endl;
6.C++中的string
有了string,就忘了char数组吧 ——沃兹基硕德(\(2088\))
string s1;
string s2 = s1; //再也不用strcpy了
string s3 = (10, 'c'); //s3的内容为10个c
//以下会报错!因为右边是两个普通字符串不是string
string s4 = "hello" + "world";
//以下仍然会报错,因为两个普通字符串先进行运算了
string s5 = "hello" + "," + s3;
string的输入与输出:
string s1, s2;
cin >> s1; //受到中间的空格限制,遇到空格就停止了
getline(cin, s1); //读入一整行,中间有空格也可
//scanf("%s", &s1); 错误写法,不能用scanf读入
cout << s1 << endl;
printf("%s\n", s1.c_str()); //允许用printf输出,但需要转换
puts(s1.c_str());
若想输出string中的每个元素,可以就把他当作是普通数组输出,也可以用下面的方式:
for (char c: s) cout << c << endl;
for (auto c : s) cout << c << endl;
但是这个c并不会影响s,也就是说并不能通过赋值c来改变字符串s的值. 但是也不是没有办法的:
for (char &c : s) c = 'a';
for (auto &c : s) c = 'a';
7.string的常用函数:
string s1;
string s2;
cout << s1.length() << endl;
cout << s1.size() << endl; //不同于strlen,s1.size的复杂度为 O(1)
//string之间可以直接运算,和strcmp说再见
if (s1 == s2)
...
if (s1 > s2)
...
//删除string的最后一个字符,一般用于删除末尾的空格
s1.pop_back();
//返回string的最后一个元素
s1.back();
//以上两个函数都在c++11里
//substring 应该不用解释了吧
s1.substring(0, 3); //[0, 3)
8.stringstream
stringstream相当于把字符串处理成类似于cin的东西,所以我们可以利用它来得到任意我们想要的字符串格式.
#include <sstream>
using namespace std;
int main(){
string s;
getline(cin, s);
stringstream ssin(s); //初始化
string str;
while(ssin >> str) //可以用这种方法读入一行句子的每一个单词
...
return 0;
}
char数组也有类似的函数:
#include <cstdio>
using namespace std;
int main(){
char s[10001];
fgets(s, 10000, stdin);
int a, b;
char str[1000];
double c;
sscanf(s, "%d%s%d%lf", &a, str, &b, &c);
printf("%d\n%s\n%d\n%lf\n");
}
//输入123 yxc 123 1.32
//输出为
//123
//yxc
//123
//1.32
本文算法思想源于Acwing,特此注明。