初级程序员在这里, 假设我想以(x,y)形式获取初始起始坐标,因此我要求用户使用特定形式"(x,y)"输入一个点。有没有办法可以识别格式并解析字符串,以便我可以获得x和y值?
答案 0 :(得分:1)
使用以下方式阅读一行文字:
char line[200]; // Make it large enough.
int x;
int y;
fgets(line, sizeof(line), stdin);
然后,使用sscanf
读取文本行中的数字。
if ( sscanf(line, "(%d,%d)", &x, &y) != 2 )
{
// Deal with error.
}
else
{
// Got the numbers.
// Use them.
}
如果您想使用iostream而不是stdio,请使用getline
代替fgets
。
答案 1 :(得分:0)
您可以使用正则表达式在输入中的任何位置查找匹配序列。
#include <iostream>
#include <string>
#include <regex>
int main() {
std::string line;
std::getline(std::cin, line);
std::regex e(R"R(\(([-+]?(?:\d*[.])?\d+)\s*,\s*([-+]?(?:\d*[.])?\d+)\))R");
std::smatch sm;
if (std::regex_search(line, sm, e)) {
auto x = std::stod(sm[1]);
auto y = std::stod(sm[2]);
std::cout << "Numbers are: " << x << ", " << y << std::endl;
}
return 0;
}
答案 2 :(得分:0)
为了解析东西,你需要一个解析器。编写解析器的方法有很多种,但通常解析器会读取令牌,并根据它的令牌决定下一步做什么。 (强调词语很重要,请查阅它们)。
在您的情况下,您不必明确引入单独的令牌实体。使用>>
运算符从输入流中读取元素即可。
你需要:
'('
','
')'
如果任何步骤失败,则整个解析失败。
您可以看到相同的基本步骤已完成三次,因此您可以为其编写一个函数。
bool expect_char(std::istream& is, char what)
{
char ch;
return is >> ch && ch == what;
}
这是因为is >> ch
在读取操作之后返回流,并且流可以被视为布尔值:true
如果上一次操作成功,则false
。
现在您可以编写解析器了:
bool get_vector (std::istream& is, int& x, int& y)
{
return expect_char(is, '(') &&
is >> x &&
expect_char(is, ',') &&
is >> y &&
expect_char(is, ')');
}
此方法有一个很好的属性,允许在数字和符号之间使用空格。
与使用sscanf
的解决方案相比,现在这可能看起来像很多东西:
bool get_numbers2 (std::istream& is, int& x, int& y)
{
std::string s;
return std::getline(in, s) &&
(std::sscanf(s.c_str(), "(%d,%d)", &x, &y) == 2);
}
但是sscanf
是:
在适当的情况下使用scanf
函数系列是可以的,但我不建议将其用于新的C ++程序员。