欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++primer第五版 编写一段程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分

程序员文章站 2022-05-29 12:25:27
...

 这是一个关于字符串处理的简单程序,但是里面有一些细节是值得关注的。先附上程序:

// primer_3_2_3.cpp : Defines the entry point for the application.
// 编写一段程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分

#include "stdafx.h"
#include <iostream>
#include <string>
#include <cctype>
using namespace std;

int main()
{
	string str1;  //str1用来接收输入的字符串
	string str2("\0");  //str2用来存储处理后的字符串
	cout << "input a string:" << endl;
	while(getline(cin,str1))   //不断读取字符串
	{
		for(int i=0;i<str1.size();i++)  //遍历字符串的每一个元素
		{
			if(!ispunct(str1[i]))  //如果该元素不为标点符号
				str2+=str1[i];  //将该元素赋给str2
		}
		cout << str2 << endl;  //输出处理后的字符串
		str2="\0";  //将str2清空
		cout << "input a string:" << endl;
		string temp;  //如果不加这行及下一行代码,会导致getline将提示语“input a string”读进来
		getline(cin,temp);
	}
	system("pause");
	return 0;
}

再附上运行效果

C++primer第五版 编写一段程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分

1. 为了让程序能不断处理字符串,而不是每次只处理一个字符串就结束工作,我将读字符串的代码写进了while循环的判断条件里面。

2. 我使用了两个string对象,一个用来接收用户输入的原始字符串,一个用来存储按元素依次判断后的字符。其实用一个字符串加移位操作应该也能达到目的,但是我认为这样做会比较复杂。

3. string temp;  getline(cin,temp);  这两行代码可能有点莫名其妙,但如果不加这两行代码,会导致getline将提示语“input a string”读进来,即它的作用就是消耗掉提示语。

4. 在输入了一串字符串后,我们需要敲两次回车才能输出结果,原因就在于getline是按行读取,会将第一个回车读进来,如果没有第二个回车,getline(cin,str)还会等待输入。

这里我们可以简单测试一下

在while循环体最前面加一句 cout << "getline is over!" << endl; 如下

while(cin>>str1)   //不断读取字符串
	{
		cout << "getline is over!" << endl;
		for(int i=0;i<str1.size();i++)  //遍历字符串的每一个元素

然后运行,得到结果

C++primer第五版 编写一段程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分

看第一个输入,紧跟循环体的getline is over! 是在敲两个回车后才打印出来,可见之前getline(cin,str1)确实是在等待输入;然后又测试了换行之后继续输入,再次敲回车能打印结果,这也再次印证了getline的读取方式。

当然,如果我们将getline(cin,str1)改为cin>>str1,就不必那么麻烦了,直接输入完成后敲回车即可打印结果,即

	while(cin>>str1)   //不断读取字符串

但是cin读到空格处就结束了,因此如果是读一个单词,可以用cin,但是如果要读一行,还是得用getline。效果如下

C++primer第五版 编写一段程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分

另外,其实书上的意思是希望能用范围for语句来实现遍历,但是我用的VC6.0,而范围for是c++11的标准,vc6.0不支持此种用法,还有某些较低的vs版本也不支持此种用法。不过在此可以把范围for语句的用法写出来供大家参考(正确性还待验证哈)。

for(auto &c:str1)
{
	if(!ispunct(c))  //如果该元素不为标点符号
		str2+=c;  //将该元素赋给str2
}

最后,ispunct(c)函数是cctype头文件中的函数,当c是标点符号时为真(即c不是控制字符、数字、字母、可打印空白中的一种)。cctype中还有很多常用的函数,现在列在下面,可按需取用

cctype头文件中的函数

isalnum(c)              当c是字母或数字时为真

isalpha(c)               当c是字母时为真

iscntrl(c)                 当c是控制字符时为真

isdigit(c)                 当c是数字时为真

isgraph(c)               当c不是空格但可以打印时

islower(c)               当c是小写字母时为真

isprint(c)                 当c是可打印字符时为真(即c是空格或c具有可视形式)

ispunct(c)               当c是标点符号时为真(即c不是控制字符、数字、字母、可打印空白中的一种)

isspace(c)              当c是空白时为真(即c是空格、横向制表符、纵向制表符、回车符、换行符、进纸符中的一种)

isupper(c)               当c是大写字母时为真

isxdigit(c)                当c是十六进制数字时为真

tolower(c)               如果c是大写字母,输出对应的小写字母,否则原样输出c

toupper(c)               如果c是小写字母,输出对应的大写字母,否则原样输出c