C++字符串
一、C风格字符串
字符串实际上是使用 null 字符 \0 终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。
声明和初始化一个字符串:
char str[] = "......"
用来操作以null结尾的字符串:
序号 | 函数&目的 |
---|---|
1 | **strcpy(s1, s2); ** 复制字符串 s2 到字符串 s1。 |
2 | strcat(s1, s2); 连接字符串 s2 到字符串 s1 的末尾。 |
3 | strlen(s1); 返回字符串 s1 的长度。 |
4 | strcmp(s1, s2); 如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回值小于 0;如果 s1>s2 则返回值大于 0。 |
5 | strchr(s1, ch); 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。 |
6 | strstr(s1, s2); 返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。 |
二、cin 是 C++ 封装的一个类对象
cin / cout 并不在C++的关键字列表中,并不是 C++ 的关键字。
实际上cin / cout 是C++在头文件**中封装的类对象,cin 是 istream类对象,cout是ostream类对象,其输入输出操作符 cin>>** 和 cout**<<** 也是通过重载机制赋予的输入输出功能。
三、对字符数组的输入方法(char str[N]):
1、cin使用空白字符作为一次输入的结尾,并忽略该空字符。
int main(void)
{
char line[10];
cout << "input what you want:";
cin >> line; // 可以尝试输入 "123 456"
cout << "what you input is:" << line << endl; // 只能输出 "123"
return 0;
}
/* 输出:
input what you want:123 456
what you input is:123
*/
这种情况下一次只能完成一个单词的输入,其后的单词都会被忽略掉。
2、使用 getline() / get() 函数完成面向行的输入
getline() / get()函数都可以接收一行字符串输入,并以回车作为输入的结尾。区别就是 getline 会在输入结束后丢弃最后的换行符,而 get 则会在输入队列中保留最后的换行符。
1)cin.getline()
cin.getline(line, nums,delim)
cin.getline() 的第一个参数是目标数组,第二个参数是数组长度.
第三个参数delim的作用是指定用作分界符的字符(没有这个参数的版本将以换行符为分界符)。
遇到分界符后,当前字符串的输入将停止,即使还未读取最大数目的字符。因此在默认情况下,这种分界符的方式或者到达输入的指定数目都将停止读取输入。和默认情况一样 get() 将分界符留在输入队列中,而 getline() 不保留。
以 delim 指定的字符作为一次字符串输入的结束,其后的在 nums-1 范围内的输入会保留在输入队列中作为下一个字符串的开始。
可以通过 cin.getline(line, nums, (optional)delim) 实现调用:从输入队列中获取 nums-1 个字符到 line 中,因为字符串的最后一个字符是 ‘\0’。如果输入的长度超出 nums-1 个,则 getline 和 get 将把余下的字符留在输入队列中,另外 getline 还会设置失效位,并关闭后面的输入(即后面的所有输入将不可用),此时可以用 cin.clear() 清除标准位就可以恢复后面的输入。
cout << "input what you want:" << endl;
cin.getline(line1, 10); // 可以尝试输入 "123 456 789" ('\n') 含有11个字符
// cin.clear();
cin.getline(line2, 10); // 不可用,直接退出
cin.getline(line3, 10); // 不可用,直接退出
cout << "input what you want:" << endl;
cin.getline(line1, 10); // 可以尝试输入 "123 456 789" ('\n') 含有11个字符
cin.clear(); // 清除标志位
cin.getline(line2, 10); // 可用,输出 "89",这是上一步输入队列中的字符
cin.getline(line3, 10); // 可用,你输入啥输出啥
2)cin.get()
cin.get(line, nums, (optional)*delim*)
get 函数会在输入队列中保留最后的换行符。注意是输入队列,也就是在一个 get()
函数完成输入后,会在输入缓存中保留组后的换行符,如果不做处理在下次运行 get() 时会出问题。
cin.get(line1, 10); // 可以尝试输入 "123" ('\n'), 此时回车符将会留在输入队列中
cin.get(line2, 10); // 可以尝试输入 "456",可以发现 line1 输入完后,这步直接被“跳过了”
可以使用下面这种方式避免这种情况:
cin.get(line2, 10).get();
\\ 或者
cin.get(line2, 10);
get();
3、数字与字符串的混合输入问题
使用 cin 输入一个整数后,最后的回车符会留在输入队列中,类似于get,这会对后续的 getline 和 get 输入产生影响,因为 getline / get 看到换行符后会认为是一个空行,然后会把空字符赋给后面的字符串.
cin >> a;
cin >> b;
cin.getline(s, 5); // 得到换行符,直接赋空值
此时可以使用在后面添加 cin.get() 或者 (cin >> b).get() 的方式来解决这个问题
cin >> a;
(cin >> b).get();
cin.getline(s, 7);
四、对 string 对象的输入方法
使用 cin<<str 的语法来将输入存储到 string 对象中与字符数组的操作是一样的。不同的是当每次读取一行而不是一个单词时使用的语法是不同的。
int main(void)
{
string str;
cout << "input what you want:" << endl;
getline(cin, str);
cout << "what you input is:" << endl;
cout << str << endl;
}
/* 测试用例
input what you want:
123 456 789
what you input is:
123 456 789
*/
注意:这里的面向行的输入是 g e t l i n e ( c i n , s t r ) \textcolor{red}{注意:这里的面向行的输入是 getline(cin, str)} 注意:这里的面向行的输入是getline(cin,str)
这里没有使用句点表示法,这表明这个 getline 不是类方法。他将 cin 作为参数,指出到哪里去查找输入。另外也没有指出字符串长度的参数,因为 string 对象将根据字符串的长度自动调整自己的大小。
五、C++ 字符串常用操作总结
由单引号括起来的一个字符被称作 char 型字面值,双引号括起来的零个或多个字符则构成字符串型字面值。
1、常用功能汇总
s.insert(pos, args) | 在 pos 之前插入 args 指定的字符 |
---|---|
s.erase(pos, len) | 删除从 pos 开始的 len 个字符。如果 len 省略,则删除 pos 开始的后面所有字符。返回一个指向 s 的引用。 |
s.assign(args) | 将 s 中的字符替换为 args 指定的字符。返回一个指向 s 的引用。 |
s.append(args) | 将 args 追加到 s 。返回一个指向 s 的引用。args 必须是双引号字符串 |
s.replace(range, args) | 将 s 中范围为 range 内的字符替换为 args 指定的字符 |
s.find(args) | 查找 s 中 args 第一次出现的位置 |
s.rfind(args) | 查找 s 中 args 最后一次出现的位置 |
to_string(val) | 将数值 val 转换为 string 并返回。val 可以是任何算术类型(int、浮点型等) |
stoi(s) / atoi© | 字符串/字符 转换为整数并返回 |
stof(s) / atof(s) | 字符串/字符 转换为浮点数并返回 |
s.substr(pos, n) | 从索引 pos 开始,提取连续的 n 个字符,包括 pos 位置的字符 |
reverse(s2.begin(), s2.end()) | 反转 string 定义的字符串 s2 (加头文件 ) |
2、定义一个字符串
使用标准库类型 string 声明并初始化一个字符串,需要包含头文件 string。
string s1; // 初始化一个空字符串
string s2 = s1; // 初始化s2,并用s1初始化
string s3(s2); // 作用同上
string s4 = "hello world"; // 用 "hello world" 初始化 s4,除了最后的空字符外其他都拷贝到s4中
string s5("hello world"); // 作用同上
string s6(6,'a'); // 初始化s6为:aaaaaa
string s7(s6, 3); // s7 是从 s6 的下标 3 开始的字符拷贝
string s8(s6, pos, len); // s8 是从 s6 的下标 pos 开始的 len 个字符的拷贝
使用 = 的是拷贝初始化,使用 () 的是直接初始化。当初始值只有一个时,两者都可。当初始值有多个时一般来说要使用直接初始化.
3、读写 string 操作
(1)输入时遇到空格或回车键将停止。但需要注意的是只有按下回车键时才会结束输入执行,当按下空格后还能继续输入,但最终存到字符串中的只是第一个空格之前输入的字符串(开头的空白除外,程序会自动忽略开头的空白的),空格操作可以用来同时对多个字符串进行初始化。
(2)如果希望在最终读入的字符串中保留空格,可以使用 getline 函数。
4、查询字符串信息、索引
可以用 empty size/length 查询字符串状态及长度,可以用下标操作提取字符串中的字符。
cout << s1.empty() << endl; // s1 为空返回 true,否则返回 false
cout << s1.size() << endl; // 返回 s1中字符个数,不包含空字符
cout << s1.length() << endl; // 作用同上
5、拼接、比较等操作
s1+s2 // 返回 s1 和 s2 拼接后的结果。加号两边至少有一个 string 对象,不能都是字面值
s1 == s2 // 如果 s1 和 s2 中的元素完全相等则它们相等,区分大小写
s1 != s2
<, <=, >, >= // 利用字符的字典序进行比较,区分大小写
6、cctype 头文件(判断字符类型:大/小写字母、标点、数字等)
cctype 头文件中含有对 string 中字符操作的库函数
isalnum(c) // 当是字母或数字时为真
isalpha(c) // 当是字母时为真
isdigit(c) // 当是数字是为真
islower(c) // 当是小写字母时为真
isupper(c) // 当是大写字母时为真
isspace(c) // 当是空白(空格、回车、换行、制表符等)时为真
isxdigit(c) // 当是16进制数字是为真
ispunct(c) // 当是标点符号时为真(即c不是 控制字符、数字、字母、可打印空白 中的一种)
isprint(c) // 当时可打印字符时为真(即c是空格或具有可见形式)
isgraph(c) // 当不是空格但可打印时为真
iscntrl(c) // 当是控制字符时为真
tolower(c) // 若c是大写字母,转换为小写输出,否则原样输出
toupper(c) // 类似上面的