所以我有一个像这样的字符串(所有正int,方括号中没有空格):
"[(1,2),(10,4),(5,12),... ]"
我想像这样提取int:1,2,10,4,5,12。 我现在使用以下代码,它不处理int> = 10
std::istringstream coor(coorstring);
std::vector<int> num;
char c;
while (coor.get(c)){
if (isdigit(c)){
unsigned int a = c - '0';
if (a<max) {num.push_back(a);}
}
}
例如,我的当前输出为1,2,1,0,4...
而不是1,2,10,4...
我很好奇需要修改什么来获得我想要的输出(不使用正则表达式)?顺便说一句,不是使用int vector,而是将这些坐标存储在c ++中以便以后用于绘制图形的好数据结构是什么?
答案 0 :(得分:1)
我会定义一些自定义operator>>
提取运算符来处理这个问题:
typedef std::pair<int, int> point;
typedef std::vector<point> points;
std::istream& operator>>(std::istream &in, point &out)
{
char ch1, ch2, ch3;
if (in >> ch1 >> out.first >> ch2 >> out.second >> ch3)
{
if ((ch1 != '(') || (ch2 != ',') || (ch3 != ')'))
in.setstate(std::ios_base::failbit);
}
return in;
}
std::istream& operator>>(std::istream &in, points &out)
{
point pt;
char ch;
if (!(in >> ch))
return in;
if (ch != '[')
{
in.setstate(std::ios_base::failbit);
return in;
}
ch = in.peek();
do
{
if (ch == std::istream::traits_type::eof())
{
in.setstate(std::ios_base::failbit);
break;
}
if (ch == ']')
{
in.ignore(1);
break;
}
if (ch != '(')
{
in.setstate(std::ios_base::failbit);
break;
}
if (!(in >> pt))
break;
out.push_back(pt);
ch = in.peek();
if (ch == ',')
{
in.ignore(1);
ch = in.peek();
}
}
while (true);
return in;
}
std::istringstream iss(coorstring);
points coords;
iss >> coords;
答案 1 :(得分:0)
只需使用字符串拆分:
std::string s = "[(1,2),(10,4),(5,12),... ]";
std::string delimiter = ",";
while ((pos = s.find(delimiter)) != std::string::npos) {
token = s.substr(0, pos);
// deal with the data here
s.erase(0, pos + delimiter.length());
}
它应输出相当规则的数据,所有这些数据都知道:
"[(1", "2)", "(10", "4)", etc...
答案 2 :(得分:0)
您可以使用std::ignore(1000, '(')
跳过所有内容,直到(并包括)下一个开头括号,然后使用运算符>>
读取第一个坐标,逗号和第二个坐标。
此外,我建议使用数据结构pair
来表示一对坐标:
int main() {
std::istringstream coor("[(1,2),(10,4),(5,12),... ]");
std::vector<pair<int,int>> coordinates;
for(;;) {
coor.ignore(std::numeric_limits<std::streamsize>::max(), '(');
int x,y;
char c;
if (!(coor >> x >> c >> y)) {
break;
}
coordinates.push_back(pair<int,int>(x,y));
}
for (auto coordinate : coordinates) {
cout << coordinate.first << "/" << coordinate.second << endl;
}
}
请注意,此解决方案不检查输入字符串的语法,因此它也会接受输入而没有任何右括号或没有括号。但如果语法通过其他方式得到保证,那么它至少是一个简单的解决方案。
答案 3 :(得分:0)
不完全是解决方案,但此时您应该听到的内容:
除了已经存在的工具和功能之外,当您遇到任何问题时,请从以下开始:您自己如何做到这一点?您在脑海中处理了哪些步骤,从纸上的符号到点等概念?如果你遇到一个完全不知道怎么读这个的人,你会怎么解释给他?
另外,请考虑子问题。也许开始一种方法将类似(8,1)的东西转换成一个点然后连接东西。不要害怕编写几十个单独的函数,将一个东西转换成另一个函数。使用不存在的函数然后编写它们。以下是一些可能有助于您学习的代码:
struct Point;
void remove_symbol(string& input, const char symbol);
Point parse_point(const string& input); //"(8,1)" -> Point on that coordinates
vector<string> delimit_by(const string& input, const char delimiter);
没有故意提供实现 - 尝试编写所有这些实现并再次询问它是否无效。一些基本的提示,即使这可能不是最优雅的代码:您可以通过string::length()
和[] -operator迭代整数的内容,就像数组一样,您可以通过以下方式将事物追加到字符串中+ =(由于费用昂贵,但开始时很容易)。
(使用STL可能有直接的方法来做这些事情,但是自己编写它们会在开始时给你一些经验,而且你不能知道所有的STL。只要确保了解更多关于STL的信息。 STL从长远来看。)
答案 4 :(得分:0)
简单的两个* -pass算法,产生一个std :: vector / point
s:
std::string s = "[(1,2),(10,4),(5,12),... ]";
std::replace_if( s.begin(), s.end(), []( char c ) { return !std::isdigit( c ); }, ' ' );
std::istringstream ss( s );
int x, y;
while (ss >> x >> y)
points.emplace_back( point( x, y ) );
您可以按照自己喜欢的方式声明point
,例如:
struct point
{
int x, y;
point(): x(), y() { }
point( int x, int y ): x(x), y(y) { }
};
* 取决于stringstream构造函数,它可能会再次传递。该算法明确地通过两次。