【问题标题】:Is there any particular way to use getline for string data type in C++ for reading in a string of say 540 characters?有没有什么特别的方法可以在 C++ 中使用 getline 作为字符串数据类型来读取 540 个字符的字符串?
【发布时间】:2015-07-28 20:54:17
【问题描述】:

我必须阅读这个字符串: efBZw WH EDC EVOh qjfzJ oXkXL QUHXWMl kXRSIyGHb TxQkBWhPI yPTJEZ KyYfFQR ZQvYBPUmZ bkuKbRBWW mjJ WRgIBFNM ojGP XbkJNUhXF SeZVBZ SooFP XXE VIebym gOXP pDXRQ

给定字符串没有输出。

    #include <iostream>
    #include <string>
    #include <ctype.h>
    #include <deque>

    using namespace std;

    int isPiSong(string str,deque<int> numbers){
        int noOfwords = 0, noOfletters = 0, ctr = 0;
        int flag = 1;
        for(std::string::iterator it = str.begin(); it != str.end(); ++it) {

            if(*it != ' ' && flag){
                if(isalpha(*it))
                noOfletters++;
            }
            else{
                if(noOfletters != numbers[ctr++])
                    flag = 0;
                noOfletters = 0;
            }

        }
        return flag;
    }

    int main()
    {
        deque<int> numbers;
              // 31415926535897932384626433833
        numbers.push_back(3);
        numbers.push_back(1);
        numbers.push_back(4);
        numbers.push_back(1);
        numbers.push_back(5);
        numbers.push_back(9);
        numbers.push_back(2);
        numbers.push_back(6);
        numbers.push_back(5);
        numbers.push_back(3);
        numbers.push_back(5);
        numbers.push_back(8);
        numbers.push_back(9);
        numbers.push_back(7);
        numbers.push_back(9);
        numbers.push_back(3);
        numbers.push_back(2);
        numbers.push_back(3);
        numbers.push_back(8);
        numbers.push_back(4);
        numbers.push_back(6);
        numbers.push_back(2);
        numbers.push_back(6);
        numbers.push_back(4);
        numbers.push_back(3);
        numbers.push_back(3);
        numbers.push_back(8);
        numbers.push_back(3);
        numbers.push_back(3);

        int T, flag;
        cin>>T;

        string* pisong = new string[T];

        for(int i = 0; i < T; i++){
           getline(cin>>ws, pisong[i]); //cin >> ws gets rid of leading whitespace 
                                       //first so that getline won't think that it's already                         //reached the end of the line
                                      //It doesn't seem to take the above input string
        }

        for(int i = 0; i < T; i++){
            flag = isPiSong(pisong[i],numbers);
            if(flag){
                cout<<"It's a pi song."<<endl;
            }else{
                cout<<"It's not a pi song."<<endl;
            }
        }
        delete [] pisong;
        return 0;
    }

【问题讨论】:

  • 您好,欢迎来到 Stack Overflow!要获得好的答案,您需要使用更多信息更新您的问题。 “不能将上述字符串作为输入”不是问题的描述。请阅读thisthis

标签: string c++11 limit getline


【解决方案1】:

你想安装 valgrind 并使用它。它立即揭示了这个问题:

==6962== Conditional jump or move depends on uninitialised value(s)
==6962==    at 0x40117D: isPiSong(std::string, std::deque<int, std::allocator<int> >) (stackoverflow-31686882.cpp:19)
==6962==    by 0x401670: main (stackoverflow-31686882.cpp:77)
==6962== 
==6962== Use of uninitialised value of size 8
==6962==    at 0x401173: isPiSong(std::string, std::deque<int, std::allocator<int> >) (stackoverflow-31686882.cpp:19)
==6962==    by 0x401670: main (stackoverflow-31686882.cpp:77)
==6962== 
==6962== Invalid read of size 4
==6962==    at 0x401173: isPiSong(std::string, std::deque<int, std::allocator<int> >) (stackoverflow-31686882.cpp:19)
==6962==    by 0x401670: main (stackoverflow-31686882.cpp:77)
==6962==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==6962== 
==6962== 
==6962== Process terminating with default action of signal 11 (SIGSEGV)
==6962==  Access not within mapped region at address 0x0
==6962==    at 0x401173: isPiSong(std::string, std::deque<int, std::allocator<int> >) (stackoverflow-31686882.cpp:19)
==6962==    by 0x401670: main (stackoverflow-31686882.cpp:77)

第 19 行是这一行:

if(noOfletters != numbers[ctr++])

ctr 每增加一个空格。一旦数字双端队列用尽(即 ctr > 长度),您将在双端队列中获得非法访问。所以,要么你必须在某个时候将 ctr 重置为零,要么你必须检查 ctr 是否不会太大。

另外还有很大的改进空间。

一旦标志设置为零,它就不能再改变,所以在某些时候,你会返回 false。那么,为什么不立即返回呢?所以不要使用 flag = 0,而是返回 0。

您首先计算字母的数量,然后当您到达下一个空格时,您检查它。如果你给这个字符串:“abc a abcd xxxxxxxxxxxxxxxx”怎么办?等等,让我测试一下:

It's a pi song. [abc a abcd xxxxxxxxxxxxxxxx]

仅当我在最后一个 x 后添加一个空格时,程序才能正确检测到错误:

It's not a pi song. [abc a abcd xxxxxxxxxxxxxxxx ]

解决方案:一旦检测到第一个 isalpha 字符,设置一些 n = numbers[ctr++] - 1 (检查后是否还有数字)。然后对后面的每个 isalpha 执行 n-- 并检查它之前是否为零(即“if (n--) {...}”。如果是 -> 返回 0。如果不是,继续直到空格。空格然后 test 将检查 n 是否达到零(这意味着正好 numbers[ctr++] isalphas 已被跳过)。如果不是 -> 返回 0。

最后你必须决定要做什么,如果数字双端队列用尽但输入跟随。

【讨论】:

  • 谢谢!我现在正在尝试。并且在问题的测试用例中给出了字符串类型输入的字数不超过29字。因此,我对双端队列中的最终情况不小心。
  • 软件开发的第一条规则:永远不要相信你的输入。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-17
  • 1970-01-01
  • 1970-01-01
  • 2018-05-16
相关资源
最近更新 更多