char acStr[] = "aaaaa";//这个是字符数组,只含有5个字符
char *pcStr = "aaaaa";//这个是字符串,含有6个字符,即5个a加一个结束符'\0'
输出的结果 strlen()长度都是5, 所以即便是字符串,最后取长度的时候,也不考虑\0: strlen()计算字符串长度,忽略结束符 \0
char *p = "hello";
char *q = "world";
char o[] = "hello";
cout<<"hello"<<strlen(p)<<endl; //5
cout<<"world"<<strlen(q)<<endl; //5
cout<<"o[]"<<strlen(o)<<endl; //5
cout<<strlen("hello")<<endl; //5
1. 字符串实际要比字符数组多一个空间 用来存放结束符 \0
char *p = "hello";
char *q = "world"; //比如world实际上存放了6个字符位, 5个字符+'\0'
但是求长度, 返回的值仍然是5: 并不考虑 结束符\0的位
cout<<"hello"<<strlen(p)<<endl;
cout<<"world"<<strlen(q)<<endl;
2. 字符数组是不用存放\0位的,所以分配的字符位数 只要给 strlen(p)就行了, 不需要+1:
a[0] = new char[strlen(p)];
a[1] = new char[strlen(q)];
用字符数组和字符指针变量都可实现字符串的存储和运算。 但是两者是有区别的。在使用时应注意以下几个问题:
1. 字符串指针变量本身是一个变量,用于存放字符串的首地址。而字符串本身是存放在以该首地址为首的一块连续的内存空间中并以‘\0’作为串的结束。字符数组是由于若干个数组元素组成的,它可用来存放整个字符串。
2. 对字符数组作初始化赋值,必须采用外部类型或静态类型,如: static char st[]={“C Language”};而对字符串指针变量则无此限制,如: char *ps="C Language";
3. 对字符串指针方式 char *ps="C Language";可以写为: char *ps; ps="C Language";而对数组方式:
static char st[]={"C Language"};
不能写为:
char st[20];st={"C Language"};
而只能对字符数组的各元素逐个赋值。
从以上几点可以看出字符串指针变量与字符数组在使用时的区别,同时也可看出使用指针变量更加方便。前面说过,当一个指针变量在未取得确定地址前使用是危险的,容易引起错误。但是对指针变量直接赋值是可以的。因为C系统对指针变量赋值时要给以确定的地址。因此,
char *ps="C Langage";
或者 char *ps;
ps="C Language";都是合法的。
C++提供两种字符串的表示方法:c风格的字符串和标准c++引入的string类类型。建议使用string类。
1. C风格字符串
字符串存储在一个字符数组中,一般通过一个char *类型指针操纵它。然而,系统内部实际上是存储在一个字符串数组中,然后,st指向数组的第一个元素:
Char *st=”hello world”;
常用指针的算术运算来遍历c风格的字符串,每次指针增加1,直到空字符为止:
While(*st++){…}
当包含:#include<cstring.h>
//返回长度
Int strlen(const char *);
//比较两字符串是否相等
Int strcmp(const char*,const char *);
//以下两个的使用方式不清楚
//第二个字符拷贝至第一个
Char *strcpy(char *,const char *);
//第二个字符接至第一个后面
Char *strcat(char*,const char *);
C风格字符串的长度可以是0,有两种方式:
Char *pc1=0;
Char *pc=””;
一个测试程序:
#include<iostream.h>
// without ".h",eagerly learn to know why
#include<cstring>
main(){
// temp setting avoids chaning the value of p;
//and p can`t be constant,for it will be resetted by function strcat();
char *p="Hello world!",*temp=p;
const char *q="Nice to see you!";
cout<<p<<q<<endl;
cout<<*p<<","<<*(q+1)<<endl;
p=temp;
cout<<"p is made by:\n";
for(int i=0;i<strlen(p);i++)
cout<<*temp++<<endl;
}
2. 字符串类型
C++标准库对此进行支持。
使用string类,必须包含头文件:
#include<string>
String st(“Hello world”);
//返回长度(不包含空字符)
St.size();
String st2;
//检查是否是空
St2.empty()=true or false;
//复制两个字符串
String st3(st);
St2=st3;//simple
//比较是否相等
If(st2==st3){….}
//两个字符串连接成第三个字符串
String s1(“hello,”);
String s2(“world!”);
String s3=s1+s2;
//或者,直接加到s1
S1+=s2;
//可以把一个c风格的字符串转换成string类对象
Const char *pc=”a try”;
String s1=pc;//ok
//但,反向的转换不能自动执行
Char *str=s1;//error
为实现这种转换必须显示调用名为c_str()
//几乎正确的
char *str=s1.c_str();
但为了防止字符数组被程序直接处理,c-str()返回的一个指向常量数组的指针:const char*,str被定义为非常量指针,所以违例。正确是:
Const char *str=s1.c_str();//ok
String 类型支持通过下标操作符号访问单个字符。
一个例子:
l const 限定修饰符
for( int index=0;index<512;index++)
第一个问题是可读性,即512是什么意思?第二个问题是可维护性,如多处修改会陷入麻烦。
Const int bufsize=512;
For(int index=0;index<bufsize;index++)
Const类型限定符提供了一个解决方案,把一个对象(变量)转换成一个常量(constant)。在程序中任何改变这个值的企图都将导致编译错误,因此,被称为只读的。
而且常量定义后必须初始化,因为不能修改。