C/C++语法:(二)字符串

1.常见ASCII码记忆

\[0:48 \]

\[A:65 \]

\[a:97 \]

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,特此注明。

posted @ 2020-09-23 20:13  AIchemistar  阅读(373)  评论(0)    收藏  举报