《好学的C++ 第2版》 第7章 字符串--分析文本

文本字符串存储:每个字符加上一个'\0'的ascii码。所以一个文本字符串也就是一连串字节,每个字节是0~255的一个数值。键盘输入或屏幕输出时,会发生数值跟字符之间的转换。(国际标准unicode编码使用了一个以上的字节 来表示每个字符。)

由于源代码保存在文本文件里,而文本字符是以数值形式存储的。因此计算机来处理源代码时,处理的其实就是这些连串的数值,按照另一套精确的规则进行另一种形式的数值运算、数据求值和决策判断。(!!!最开始的第一版编译器只能用机器码来编写!!!而老编译器又可以用来编写新编译器,就这样波浪发展,复杂的编译器当然不用机器码编写啦!)

字符串实际是基类型为char(一字节宽的整形)的数组。

char str[20] = "how long?";  //未初始化的成员,是否全局情况就是0,局部情况就是垃圾?

字符串以'\0'(即数值0)为结尾。

char s[] = "const"; //未指定长度,会被分配8个字节空间(包括容纳'\0'),s是常量 //it:指定长度不足会截断?

char* s = "variable"; //s是变量,可以被重新赋值指向别处。it:所以可以分声明const char* s;这样s就不可变了。

 

字符串处理函数:

strcpy(s1,s2)         //s2复制到s1

strcat(s1,s2)         //s2追加到s1

strncpy(s1,s2,n)    //最多复制n个,不包括'\0'   //s2是常量字符串并且里头有'\0',会怎么样?

strncat(s1,s2,n)     //最多追加n个,不包括'\0'。追加起点是s1中第一个'\0'所在位置

strlen(s)               //s的长度,不包括'\0'

strtok(src_str,delims)  // 用字符delims分割src_str,返回第一个子串的指针

strtok(NULL, delims)   //返回已知源串(strtok上次调用所指定的src_str)里的下一个子串的指针。没有子串可返回就将返回NULL

 

c++不会为了能保存整个字符串做任何事,这得码农保证。

char s[80]; //指定了长度但没初始化,c++还是为它保留了80个字节

当代码中出现常量字符串,c++会为之分配空间并返回其地址,即字符串被求值为一个地址。

 

#include <iostream>

#include <cstring>   //strcpy等函数在这里头

#define STR_LEN = 100;

using namespace std;

char* str[STR_LEN];

cin.getline(str, STR_LEN-1); //读入一行(读到'\n'即结束),最多读入STR_LEN-1个字符。(it)应该不会自动补上'\0'

转义字符'\b'是退格

输入流操作符(>>)会进行自动类型转换

cin.getline表明getline是cin这个对象的一个成员函数。对象是其成员函数的作用对象。

cin>>val;  //获取第一个空白符(空格 制表符 换行符)之前的数据,(it)尝试转化为var类型数据赋给var。空白符之后的数据还留在输入流里等待下一个输入操作把它取走。如果直接输入空白符,cin会一直等待输入。较好的方法是设置默认值并提示输入者。

cin.getline之后再用cin>>经常会出问题,原因是二者对待换行符的做法不同。因此在同一个程序里最好只用一种。

#include <cstdlib>  //有atof atoi等函数

#include <cctype>  //有toupper tolower等函数

C字符串: c及c++里以'\0'为结束标志的字符串(char*类型)

类似Basic,C++较新版本里提供了string类型(其实是STL提供的一个类,只有很老的C++版本才不支持STL),从而不用再考虑字符串长度这种繁琐易错的东西。#include <string>可激活此支持。(注意激活C字符串的是<cstring>,strcpy等老函数需要它) 类似于cin和cout,可以选择using namespace std,否则就要std::string这样使用这个类。 it:<string>属于c++标准库而不属于c标准库。另外,c的标准库(例如<ctype.h>)在c++中另有实现(例如<cctype>)

string a, b, c;                //声明

string a("so"),b("easy"); //初始化

a = "so"; b = "easy";  //初始化

string a = "so";          //声明加初始化

a可以重新复制而不用担心容纳不了:

a = "fking beauty is nature.";

string类型可以进行比较、值传递、合并:

int ret = (a == b);

string b = a;

string c = a+b;

string d = a + " hate " +b;

但是!但是!以下语句无法通过编译,虽然加号支持string和C字符串之间的合并,但是不支持两个C字符串之间的合并。(字符串字面值属于C字符串)

使用>>为string变量赋值也是只能读到第一个空白符之前的内容;不过用getline时无需担心string放不下一行了。

string addr;

getline(cin, addr);

访问string对象里的单个字符:

for(int i = 0;i < addr.size;i++) cout << addr[i] << endl;

 

小结捡漏:

字符串的当前长度与为该串保留的存储空间长度是两个概念。前者取决于'\0'的位置,后者取决于声明时指定的长度。

strcpy与strcat等函数可改变字符串的长度。不过如果超出空间,就可能覆盖了其他变量的数据区域,导致难以查找的错误。

cin.getline函数的第二个入参lenmax给出被复制到字符串中去的字符的最大个数包括'\0',因此最多复制lenmax-1个字符。

string类是定义在STL库里的。

 

posted @ 2017-04-02 22:46  fFaXzz  阅读(171)  评论(0编辑  收藏  举报