“cout对象认为char的地址是字符串的地址,因此它打印该地址处的字符,然后继续打印后面的字符,直到遇到空字符(\0)为止。总之,如果给cout提供一个字符的地址,则它将从该字符开始打印,直到遇到空字符为止。”
#include <iostream>
int main()
{
using namespace std;
char flower[10] = "ro\0se";
cout << flower << endl;
return 0;
}
“在cout和多数C++表达式中,char数组名、指向char的指针以及用引号括起的字符串常量都被解释为字符串第一个字符的地址。”
下面的程序演示了如何使用不同形式的字符串:
#include <iostream>
#include <cstring>
int main()
{
using namespace std;
char animal[20] = "bear";
const char *bird = "wren"; //bird holds address of string. 以这种方式使用const意味着可以用bird来访问字符串,但不能修改它。
char *ps; //未初始化。
cout << animal << " and " << bird << endl;
cout << "Enter a kind of animal: ";
cin >> animal;
ps = animal; //将animal赋给ps并不会复制字符串,而只是复制地址。这样,这两个指针将指向相同的内存单元和字符串。
cout << ps << "s!\n";
cout << "Before using strcpy():\n";
cout << animal << " at " << (int *) animal << endl; //(int *)是强制类型转换。
cout << ps << " at " << (int *) ps << endl; //除了char的几乎所有基本类型都可以。
ps = new char [strlen(animal) + 1]; //get new storage.
strcpy(ps, animal); //copy string to new storage.
cout << "After using strcpy():\n";
cout << animal << " at " << (int *) animal << endl;
cout << ps << " at " << (int *) ps << endl;
delete [] ps;
return 0;
}
“请不要使用字符串常量或未被初始化的指针来接收输入。为避免这些问题,也可以使用std::string对象,而不是数组。”
“在将字符串读入程序时,应使用已分配的内存的地址。该地址可以是数组名,也可以是使用new初始化过的指针。”
“将animal赋给ps并不会复制字符串,而只是复制地址。这样,这两个指针将指向相同的内存单元和字符串。要获得字符串的副本,还需要做其他工作。首先,需要分配内存来存储该字符串,这可以通过声明另一个数组或使用new来完成。后一种方法使得能够根据字符串的长度来指定所需的空间:”
ps = new char[strlen(animal) + 1]; //get new storage.
strcpy()——
“如果数组比字符串小,strcpy()函数将字符串中剩余的部分复制到数组后面的内存字节中,这可能会覆盖程序正在使用的其他内存。要避免这种问题,请使用strncpy()。”
strncpy()——
“该函数接受3个参数,前两个与strcpy()相同,第3个参数是要复制的最大字符数。不过,要注意的是,如果该函数在到达字符串结尾之前,目标内存已经用完,则它将不会添加空字符。因此,应该这样使用该函数:”
char food[20] = "carrots";
strncpy(food, "a picnic basket filled with many goodies", 19);
food[19] = '\0';
“应使用strcpy()或strncpy(),而不是赋值操作符来将字符串赋给数组。”
“使用C++string类型更为简单:不用担心字符串会导致数组越界,并可以使用赋值操作符而不是函数strcpy()和strncpy()。”