一道算法题目(输入一行包含正整数负整数零的数据,中间以空格隔开,以0作结尾,输出这组数据中的正整数个数)

题目:

统计一组数据中的正整数个数。要求:输入一行整数,以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,有点不舒服,中途一次没自己保存,还让我重复写了好些字,还好它偶尔会自己保存一下,要不然我真没耐心再写一遍=.=

        如果有哪位同学有更好的解题思路,一定要告诉我哦,另外,我这篇博客里面的不准确不完善的知识点或者想法,如果发现了也要提早告知我,谢谢啦。

猜你喜欢

转载自blog.csdn.net/void_ink/article/details/80950087