Reputation: 1
Beginner programmer here, Say I want to obtain initial starting coordinates in the form (x,y), so I ask the user to enter in a point using the specific form "(x,y)". Is there a way that I could recognize the format and parse the string so that I could obtain the x and y values?
Upvotes: 0
Views: 55
Reputation: 206627
Read a line of text using:
char line[200]; // Make it large enough.
int x;
int y;
fgets(line, sizeof(line), stdin);
Then, use sscanf
to read the numbers from the line of text.
if ( sscanf(line, "(%d,%d)", &x, &y) != 2 )
{
// Deal with error.
}
else
{
// Got the numbers.
// Use them.
}
If you want to use iostreams instead of stdio, use getline
instead of fgets
.
Upvotes: 1
Reputation: 119877
In order to parse stuff you need a parser. There are many ways to write a parser, but generally parsers read tokens and decide what to do next based on which token it is. (Emphasized words are important, look them up).
In your case you don't have to explicitly introduce a separate token entity. Reading elements from the input stream with the >>
operator will do.
You need to:
'('
','
')'
If any step fails, the entire parsing fails.
You can see the same basic step is done three times, so you can write a function for it.
bool expect_char(std::istream& is, char what)
{
char ch;
return is >> ch && ch == what;
}
This works because is >> ch
returns the stream after the read operation, and the stream can be viewed as a boolean value: true
if the last operation succeeded, false
otherwise.
Now you can compose your parser:
bool get_vector (std::istream& is, int& x, int& y)
{
return expect_char(is, '(') &&
is >> x &&
expect_char(is, ',') &&
is >> y &&
expect_char(is, ')');
}
This method has a nice property that blanks are allowed between the numbers and the symbols.
Now this may look like a lot of stuff to type compared to the solution that uses 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);
}
But sscanf
is:
It's OK to use the scanf
functions family where appropriate, but I don't recommend it for new C++ programmers.
Upvotes: 0
Reputation: 2279
You can use regex to find the matching sequence anywhere in the input.
#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;
}
Upvotes: 0