有什么特别的方法可以在 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.
最后你必须决定做什么,如果数字双端队列已用完但输入如下。
我必须读入这个字符串:
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.
最后你必须决定做什么,如果数字双端队列已用完但输入如下。