1. 可以在字符前加 'L' 获得宽字符类型 wchar_t
L'a'
2. 为了与C兼容,C++的字符串文字(literal)也会比输入的字符串多一个字符,每一个字符串文字都以编译器添加的null字符结尾:
'A' // single quote: character literal "A" // double quote: character string literal
"A" 有两个字符: A + NULL
同宽字符文字的表示方法,在字符串前加 L 可以获得宽字符串文字,宽字符串文字也是以宽 NULL 字符结尾:
L"a wide string literal"
3. 可以用空格,tab 或换行连接字符串,例如下面的写法,一行字符串就可以分成多行写:
// concatenated long string literal std::cout << "a multi-line " "string literal " "using concatenation" << std::endl;还可以这样写:
string str = "123" "456"; cout << str; // output 123456
4. 不能连接字符串和宽字符串,下面的行为将是未定义的:
// Concatenating plain and wide character strings is undefined std::cout << "multi-line " L"literal " << std::endl;
有未定义行为的程序包含错误,如果能work纯属巧合,这类错误编译器不能检测或难于检测。不能依赖于未定义的行为:程序行为可能随编译器或环境发生改变。也不能依赖于具体的平台,例如,不能假定int的size是固定的值,否则,程序将是不可移植的。
5. 可以用 \ 连接多行字符:
// ok: A \ before a newline ignores the line break std::cou\ t << "Hi" << st\ d::endl;
6. enum 定义,enum 关键字后的名称可选:
// input is 0, output is 1, and append is 2 enum open_modes {input, output, append}; open_modes x = output;
7. 在头文件里应该永远使用完全限定的类名字,不要使用using,原因是使用using会使得这些类名字无条件对其他程序可见,这是不好的。
8. 字符串类型 string, 构造函数:
string s1; // Default constructor; s1 is the empty string string s2(s1); // Initialize s2 as a copy of s1 string s3("value"); // Initialize s3 as a copy of the string literal string s4(n, 'c'); // Initialize s4 with n copies of the character 'c'
没有提供参数时,默认构造函数“默认”被调用。
9. 由于历史的原因及为了与C兼容,字符串字面值(string literal)与标准库 string 不是同一个类型。
10. C++ 支持两种形式的变量初始化:copy-initialization, direct-initialization
int ival(1024); // direct-initialization int ival = 1024; // copy-initialization
11. 内建类型变量自动初始化的值:如果在函数体外,值为0,在函数体内则为未初始化。
12. 从终端读入字符串
string s; // empty string cin >> s; // read whitespace-separated string into s cout << s << endl; // write s to the output
cin >> s 丢弃启始全部空白字符(空格,回车,tab等),直到遇到第二个空白字符,输入 “ hello world”, 将得到输出 “hello”
可以用输入输出操作符将多个读和多个写串在一起,如果输入“hello world”, 则输出“helloworld”
string s1, s2; cin >> s1 >> s2; // read first input into s1, second into s2 cout << s1 << s2 << endl; // write both strings
13. 读未知数目的字符串
string word; // read until end-of-file, writing each word to a new line while (cin >> word) cout << word << endl; // output: // This sentence回车 // This // sentence // while回车 // while // Ctrl+Z回车 // 如果到达 end-of-file, 就退出while循环 // press any key to continue...14. 使用 getline 读取整行,
string line; // read line at time until end-of-file while (getline(cin, line)) cout << line << endl; system("pause"); return 0; // 不同于cin, getline 不会忽略前导换行符号,遇到换行符号就停止读入并返回, 此newline被丢弃,因此,line 不包括换行符号。
15. string 操作
s.empty() |
Returns true if s is empty; otherwise returns false |
s.size() |
Returns number of characters in s |
s[n] |
Returns the character at position n in s; positions start at 0. |
s1 + s2 |
Returns a string equal to the concatenation of s1 and s2 |
s1 = s2 |
Replaces characters in s1 by a copy of s2 |
v1 == v2 |
Returns true if v1 and v2 are equal; false otherwise |
!=, <, <=, >, and >= |
Have their normal meanings |
17. 字符串可以直接赋值:
// st1 is an empty string, st2 is a copy of the literal string st1, st2 = "The expense of spirit"; st1 = st2; // replace st1 by a copy of st2赋值较难高效地实现,是因为赋值涉及到一系列操作:删除 st1 已有的存储内容,为存储st2的复制字符分配空间,然后复制。
18. string 和 string 字面值可以相加,但是 + 操作符的至少一个操作数必须是string,不能两个都是 string literal.
string s1("hello"); string s2("world"); string s3 = s1 + ", " + s2 + "\n";
string s1 = "hello"; string s2 = "world"; string s3 = s1 + ", "; // ok: adding a string and a literal string s4 = "hello" + ", "; // error: no string operand string s5 = s1 + ", " + "world"; // ok: each + has string operand string s6 = "hello" + ", " + s2; // error: can't add string literals
s5 的赋值是ok的,因为 + 操作符号结合顺序从左到右,(s1 + ",") 返回string对象,可以再次与 literal "world"相加
string s5 = (s1 + ", ") + "world";
s6 的赋值错误,有以下改法:
string s6 = "hello" ", " + s2;
string s6 = "hello" + (", " + s2);
string s6 = string("hello") + ", " + s2;
之所以不能用 +
连接两个字符串字面值, 是因为,字符串字面值是字符数组(一个const char [N]
,N
为字符串长度加 1 (null 终止符)), 绝大多数情况下,数组被转换为指向起始元素的指针。所以表达式"Hello" + ",world"
是试图将两个const char*
相加,指针相加是无意义的。
19. 运算符左右两边式子的 计算顺序, C++只对一下四个操作符号有规定,其他是没有规定的,编译器可以先计算左边的,也可以先计算右边的。
(1)&&
(2)
||
(3)
? :
(4)
,
20. 用下标subscript操作符[]取字符串中的元素,index的类型应该是 string::size_type,index不能超过s.size() - 1,
string str("some string"); for (string::size_type ix = 0; ix != str.size(); ++ix) cout << str[ix] << endl;
21. 对于字符串中的单个字符的一系列函数:
isalnum(c) |
true if c is a letter or a digit. |
isalpha(c) |
true if c is a letter. |
iscntrl(c) |
true if c is a control character. |
isdigit(c) |
true if c is a digit. |
isgraph(c) |
true if c is not a space but is printable. |
islower(c) |
true if c is a lowercase letter. |
isprint(c) |
true if c is a printable character. |
ispunct(c) |
true if c is a punctuation character. |
isspace(c) |
true if c is whitespace: space, tab, vertical tab, return, newline, formfeed |
isupper(c) |
TRue if c is an uppercase letter. |
isxdigit(c) |
true if c is a hexadecimal digit. |
tolower(c) |
If c is an uppercase letter, returns its lowercase equivalent; otherwise returns c unchanged. |
toupper(c) |
If c is a lowercase letter, returns its uppercase equivalent; otherwise returns c unchanged. |
返回string中标点符号数:
string s("Hello World!!!"); string::size_type punct_cnt = 0; // count number of punctuation characters in s for (string::size_type index = 0; index != s.size(); ++index) if (ispunct(s[index])) ++punct_cnt; cout << punct_cnt << " punctuation characters in " << s << endl;
Concatenate two string literals
C++ Primer