有什么特别的方法可以在 C++ 中使用 getline 作为字符串数据类型来读取 540 个字符的字符串吗?

Is there any particular way to use getline for string data type in C++ for reading in a string of say 540 characters?

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

给定字符串没有输出。

    #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;
    }

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

==6962== Conditional jump or move depends on uninitialised value(s)
==6962==    at 0x40117D: isPiSong(std::string, std::deque<int, std::allocator<int> >) (Whosebug-31686882.cpp:19)
==6962==    by 0x401670: main (Whosebug-31686882.cpp:77)
==6962== 
==6962== Use of uninitialised value of size 8
==6962==    at 0x401173: isPiSong(std::string, std::deque<int, std::allocator<int> >) (Whosebug-31686882.cpp:19)
==6962==    by 0x401670: main (Whosebug-31686882.cpp:77)
==6962== 
==6962== Invalid read of size 4
==6962==    at 0x401173: isPiSong(std::string, std::deque<int, std::allocator<int> >) (Whosebug-31686882.cpp:19)
==6962==    by 0x401670: main (Whosebug-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> >) (Whosebug-31686882.cpp:19)
==6962==    by 0x401670: main (Whosebug-31686882.cpp:77)

第 19 行是这个:

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

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

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

一旦标志设置为零,它就不能再改变,所以在某些时候,你会 return false。那么,为什么不直接 return 呢?所以不是 flag = 0,而是 return 0.

你先数字母的个数,然后当你到达下一个space时,你检查它。如果你给这个字符串:"abc a abcd xxxxxxxxxxxxxxxx" 会怎样?等等,让我测试一下:

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

只有我在最后一个x后面加一个space,程序才能正确检测到错误:

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

解决方案:一旦检测到第一个 isalpha 字符,设置一些 n = numbers[ctr++] - 1(检查后,还有数字)。然后对于每个后续的 isalpha 做 n-- 并检查它之前是否为零(即 "if (n--) {...}"。如果它是 -> return 0。如果不是,继续直到 space。space 测试然后将检查 n 是否已达到零(这意味着,恰好 numbers[ctr++] isalphas 已被跳过)。如果没有 -> return 0.

最后你必须决定做什么,如果数字双端队列已用完但输入如下。