题目:
统计一组数据中的正整数个数。要求:输入一行整数,以0作为输入数据的结尾。输出一个值,为该行数据的正整数个数。
样例输入:
-2 -1 0 1 2 3 0
样例输出:
3
分析:
这个题是在一个群里同学分享的,刚开始看这道题的时候,我觉得很简单,以为就是个判断语句。然后群里有人讨论说,原本是用for循环读数据,读到0就停止,但是遇到了问题:如果0不只是在末尾,假如数据的中间也存在0的话,就会提前结束数据,没法做出正确判断。
于是有人说:可以创建一个数组来接收数据,这样就不用担心中间的0了,但是也有问题,不能很好地定义数组的大小。
下面是我的一个想法:读取数据的时候以string类型来接收,然后遍历字符串找空格,截断字符串,再把字符串转为int型,最后做判断计算正整数个数。
代码:
#include<iostream>
#include<string>
using namespace std;
int main()
{
int num = 0; //num存储正整数个数
int istr = 0; //istr存储转换过的int值
string str; //str接收输入的数据
getline(cin,str); //接收一行用户输入数据
for (int end = 0;end!=(-1);) //变量end存储查找到的空格位置,-1时为无,退出循环
{
int top = end; //top为上一个空格位置
end = str.find(' ', end + 1); //查找当前空格位置
string _str = str.substr(top, end - top); //_str存储当前截取的字符串
//捕获stoi()函数可能出现的异常
try
{
istr = stoi(_str); //string 转 int
if (istr > 0) //如果是正整数,num++
{
num++;
}
}
catch (std::invalid_argument&) {
cout << "数据不合法" << endl;
}
catch (std::out_of_range&) {
cout << "数据过大" << endl;
}
catch (...) {
cout << "出现异常" << endl;
}
}
if (istr == 0) //如果末尾是0 则输出正整数个数
{
cout << num;
}
else //如果末尾不是0,则提示格式错误
{
cout << "数据格式有误!";
}
return 0;
}
笔记:
写代码的过程中遇到了不少问题,复习了一遍string类的各种方法(以下是代码中用到的一些方法):
1,接收一行数据:
c++中有很多接收数据的方法,每种都有不同的功能。
(1)cin>>
直接接收用户输入,字符数值字符串都可以读取,会自动判断类型。遇到空格回车tab会结束。
(2)cin.get(char ch)
接收字符,参数为char型,可以接收空格回车tab。
注意:接收其他字符需要按下该字符之后按回车,而接收回车只需要直接按下回车。
(3)cin.get(char* chs,int size)
接收字符串,可以包含空格tab,遇到回车结束。参数为(char*,int)。
(4)cin.getline(char* chs,int size,char end)
类似cin.get(),可以包含空格tab,遇到字符end结束。
注意:end默认为'\n',其次,与cin.get()的不同点是cin.getline()会消除结束符end(如回车'\n')。
(5)getline(istream cin,string st)
接收一行字符串,可以包含空格tab,遇到回车结束。
因为没有数组限制(使用的是string),而且可以接收空格,因此我就选用了这个方法接收字符串。
2,string类的一些方法
(1)int find(char c, int pos = 0) const;//从pos开始查找字符c在当前字符串的位置。
(2)string substr(int pos = 0,int n = npos) const;//返回pos开始的n个字符组成的字符串。
(3)int stoi(string str)//返回str对应的int值,转换失败或超出范围会抛异常。
3,try{}catch{}
原本我是没使用过c++的异常处理的,但是这次程序遇到情况,如果输入的数据无法转换为int。
比如输入abc,这时 stoi()函数会抛异常,我就试着按照java的规则写了一个try catch,居然成功了。
这是原始代码:
//捕获stoi()函数可能出现的异常
try
{
istr = stoi(_str); //string 转 int
if (istr > 0) //如果是正整数,num++
{
num++;
}
}
catch (exception e) {
cout << "数据格式有误!" << endl;
}
然后我又看了一下c++的异常捕获,修改了这部分代码(准确捕获异常,更加完善合理):
//捕获stoi()函数可能出现的异常
try
{
istr = stoi(_str); //string 转 int
if (istr > 0) //如果是正整数,num++
{
num++;
}
}
catch (std::invalid_argument&) {
cout << "数据不合法" << endl;
}
catch (std::out_of_range&) {
cout << "数据过大" << endl;
}
catch (...) {
cout << "出现异常" << endl;
}
总结:
通过一个小小的题目,就学到了这么多东西,而且发现了自身的这么多不足,c++真的太博大精深了,永远也学不完的!
这是我的第一篇博客哦,以后会越来越多的!好好学习天天向上!
吐槽一下这个编辑器,不能ctrl+z,有点不舒服,中途一次没自己保存,还让我重复写了好些字,还好它偶尔会自己保存一下,要不然我真没耐心再写一遍=.=
如果有哪位同学有更好的解题思路,一定要告诉我哦,另外,我这篇博客里面的不准确不完善的知识点或者想法,如果发现了也要提早告知我,谢谢啦。