C++string字符串初始化与使用

字符串

C风格字符串

C-风格字符串具有 一种特殊的性质:以空字符(null character)结尾,空字符被写作\0, 其ASCII码为0,用来标记字符串的结尾。例如,

char dog[8] = {'b', 'e', 'a', 'u', 'x', ' ', 'i', 'i'}; // 不是字符串
char cat[8] = {'f', 'a', 't', 'e', 's', 's', 'a', '\0'}; // 是字符串

更好的初始画字符串的方法:使用字符串常量

char bird[11] = "Mr. Cheeps"; // \0 会自动隐式添加,不必显式添加
char fish[] = "bubbles"; // 让编译器计算字符串长度

警告
在确定存储字符串所需的最短数组时,别忘了将结尾的空字符计算在内。

使用

#include<iostream>
#include<cstring> // 为了使用strlen()函数

using namespace std;

int main() {
	char cat[20] = {'a', 'b', '\0'};
	cout << strlen(cat) << endl; // 输出2,strlen()只计算可见字符,而不把空字符计算在内
	cout << sizeof(cat) << endl; // 输出20
	char dog[20] = "abc";
	cout << strlen(dog) << endl; // 输出3
	cout << sizeof(dog) << endl; // 输出20
	return 0;
}

从上述程序可以学到什么呢?
首先,sizeof运算符指出整个数组的长度:20字节,但 strlen( )函数返回的是存储在数组中的字符串的长度,而不是数组本身的长度
其次, strlen( ) 只计算可见的字符,而不把空字符计算在内。
第三,如果cosmic是字符串,则要存储该字符串,数组的长度不能短于strlen(cosmic)+1。

字符串输入

#include<iostream>

using namespace std;

int main() {
	const int len = 20;
	char name[len];
	char food[len];

	cout << "Enter your name:" << endl;
	cin >> name;
	cout << "Enter your favourite food:" << endl;
	cin >> food;
	cout << "I have some food " << food;
	cout << " for you, " << name << endl;
	return 0;
}

该程序的意图很简单:读取来自键盘的用户名和用户喜欢的甜点,
然后显示这些信息。下面是该程序的运行情况,

Enter your name:
Jack apple
Enter your favourite food:
I have some food apple for you, Jack
Process exited with status 0

我们甚至还没有对“输入甜点的提示”作出反应,程序便把它显示出 来了,然后立即显示最后一行。
cin是如何确定已完成字符串输入呢?由于不能通过键盘输入空字 符,因此cin需要用别的方法来确定字符串的结尾位置。cin使用空白 (空格、制表符和换行符)来确定字符串的结束位置,这意味着cin在 获取字符数组输入时只读取一个单词。读取该单词后,cin将该字符串 放到数组中,并自动在结尾添加空字符。

另一个问题是,输入字符串可能比目标数组长(运行中没有揭示出 来)。像这个例子一样使用cin,确实不能防止将包含30个字符的字符 串放到20个字符的数组中的情况发生。

每次读取一行字符串输入

istream中的类(如cin)提 供了一些面向行的类成员函数:getline( )和get( )。这两个函数都读取一 行输入,直到到达换行符。然而,随后getline( )将丢弃换行符,然后用空字符来替换换行符。而get( )将换行符保留在输入序列中。

  1. 面向行的输入:getline( )
    getline( )函数读取整行,它使用通过回车键输入的换行符来确定输 入结尾。要调用这种方法,可以使用cin.getline( )。该函数有两个参数。 第一个参数是用来存储输入行的数组的名称,第二个参数是要读取的字 符数。如果这个参数为20,则函数最多读取19个字符,余下的空间用于 存储自动在结尾处添加的空字符。getline( )成员函数在读取指定数目的 字符或遇到换行符时停止读取。

例如,假设要使用getline( )将姓名读入到一个包含20个元素的name 数组中。可以使用这样的函数调用:

cin.getline(name, 20); // 这将把一行读入到name数组中—如果这行包含的字符不超过19个。
  1. .面向行的输入:get( )

我们来试试另一种方法。istream类有另一个名为get( )的成员函数, 该函数有几种变体。其中一种变体的工作方式与getline( )类似,它们接 受的参数相同,解释参数的方式也相同,并且都读取到行尾。但get并 不再读取并丢弃换行符,而是将其留在输入队列中。假设我们连续两次 调用get( ):

cin.get(name, 10);
cin.get(name2, 10);

由于第一次调用后,换行符将留在输入队列中,因此第二次调用时 看到的第一个字符便是换行符。因此get( )认为已到达行尾,而没有发现 任何可读取的内容。如果不借助于帮助,get( )将不能跨过该换行符。
幸运的是,get( )有另一种变体。使用不带任何参数的cin.get( )调用 可读取下一个字符(即使是换行符),因此可以用它来处理换行符,为 读取下一行输入做好准备。也就是说,可以采用下面的调用序列:

cin.get(name, 10);
cin.get();
cin.get(name2, 10);

另一种使用get( )的方式是将两个类成员函数拼接起来(合并),如 下所示:

cin.get(name, 10).get();

为什么要使用get( ),而不是getline( )呢?首先,老式实现没有 getline( )。其次,get( )使输入更仔细。例如,假设用get( )将一行读入数 组中。如何知道停止读取的原因是由于已经读取了整行,而不是由于数 组已填满呢?

混合输入字符串和数字

#include<iostream>

using namespace std;

int main() {
  int n;
  cin >> n;
  char address[10];
  cin.getline(address, 10);
  return 0;
}

用户根本没有输入地址的机会。问题在于,当cin读取年份,将回 车键生成的换行符留在了输入队列中。后面的cin.getline( )看到换行符 后,将认为是一个空行,并将一个空字符串赋给address数组。解决之道 是,在读取地址之前先读取并丢弃换行符。这可以通过几种方法来完 成,其中包括使用没有参数的get( )和使用接受一个char参数的get( ),如 前面的例子所示。可以单独进行调用:

#include<iostream>

using namespace std;

int main() {
  int n;
  cin >> n;
  cin.get(); // or cin.get(ch)
  char address[10];
  cin.getline(address, 10);
  return 0;
}

基于string类库的字符串

要使用string类,必须在程序中包含头文件string。string类位于名称 空间std中,因此您必须提供一条using编译指令,或者使用std::string来 引用它。

在很多方面,使用string对象的方式与使用字符 数组相同。

  • 可以使用C-风格字符串来初始化string对象。
  • 可以使用cin来将键盘输入存储到string对象中。
  • 可以使用cout来显示string对象。
  • 可以使用数组表示法来访问存储在string对象中的字符

赋值、拼接和附加

使用string类时,某些操作比使用数组时更简单。例如,不能将一 个数组赋给另一个数组,但可以将一个string对象赋给另一个string对 象

可以将C-风格字符串或string对象与 string对象相加,或将它们附加到string对象的末尾。

string类的其他操作

在C++新增string类之前,程序员也需要完成诸如给字符串赋值等工 作。对于C-风格字符串,程序员使用C语言库中的函数来完成这些任 务。头文件cstring(以前为string.h)提供了这些函数。例如,可以使用 函数strcpy( )将字符串复制到字符数组中,使用函数strcat( )将字符串附 加到字符数组末尾:

strcpy(arr1, arr2); // copy arr2 to arr1
strcat(arr1, arr2); // append arr2 to arr1

比较

#include<iostream>
#include<string> // 使string类库可用
#include<cstring> // C-style string函数库可用
int main() {
	char arr1[10];
	char arr2[10] ="abc";
	string s1;
	string s2 = "abc";

	s1 = s2;
	strcpy(arr1, arr2);

	s1 += s2;
	strcat(arr1, arr2);

	int len1 = s1.size();
	int len2 = strlen(arr1);
	return 0;
}

string类I/O

可以使用cin和运算符<<来将输入存储到string对象 中,使用cout和运算符<<来显示string对象,其句法与处理C-风格字符串 相同。但每次读取一行而不是一个单词时,使用的句法不同

#include<iostream>
#include<string> // 使string类库可用
#include<cstring> // C-style string函数库可用
int main() {
	char arr[20];
	string s;

	cin.getline(arr, 20);
	getline(cin, s);
	return 0;
}

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值