Is there a equivalent of TryParse in C++(gcc) ?
I would like to parse a string which may contain (+31321) and store it as long. I know phone numbers are stored as strings and string matched but for my needs , I would like to store them as long and sometimes they might contain pluses (+). What would parse it in C++?
The trouble with strtoul() and family there is no real way to test for failure.
If it fails to parse then it returns 0 without setting errno (which is only set on overflow).
boost lexical cast
#include <boost/lexical_cast.hpp>
int main()
{
try
{
long x = boost::lexical_cast<long>("+1234");
std::cout << "X is " << x << "\n";
}
catch(...)
{
std::cout << "Failed\n";
}
}
Doing it using streams
int main()
{
try
{
std::stringstream stream("+1234");
long x;
char test;
if ((!(stream >> x)) || (stream >> test))
{
// You should test that the stream into x worked.
// You should also test that there is nothing left in the stream
// Above: if (stream >> test) is good then there was content left after the long
// This is an indication that the value you were parsing is not a number.
throw std::runtime_error("Failed");
}
std::cout << "X is " << x << "\n";
}
catch(...)
{
std::cout << "Failed\n";
}
}
Using scanf:
int main()
{
try
{
char integer[] = "+1234";
long x;
int len;
if (sscanf(integer, "%ld%n", &x, &len) != 1 || (len != strlen(integer)))
{
// Check the scanf worked.
// Also check the scanf() read everything from the string.
// If there was anything left it indicates a failure.
throw std::runtime_error("Failed");
}
std::cout << "X is " << x << "\n";
}
catch(...)
{
std::cout << "Failed\n";
}
}
+31321 can be parsed as a long with the usual stream extraction operators.
#include <iostream>
#include <sstream>
int main()
{
std::istringstream s("+31321");
long n;
s >> n;
std::cout << n << '\n';
}
demo: http://ideone.com/4rmlp
Although parsing an actual phone number (with parentheses, dashes, extensions, etc) may not be as simple.
In fact, before convert the string into a number, the numbers should be "normalized" to a common format. This requires removing all symbols, and replace them with proper representation.
But you must be very care about representing telephone numbers (that are NOT numbers: they are not subjected to regular arithmetic) as string: Number beginning with one or more zeroes are not the same as the ones with the zeroes removed:
00 is the typical replacement for +, but a number without the 00 (or +) in front should be prefixed by 00c where c is the country code.
You need to do some pre-processing to come to a uniform string representation, before converting, otherwise you risk to "alias" different things.
the input extraction operator >> (i hope it's an acceptable name) applies and returns a stream&, that has a bool operator, meaning the extraction has been succesfully attempted. For instance, from the Cubbi answer:
...
std::istringstream s("+31321");
long n;
if (s >> n)
std::cout << n << '\n';
....
This will succed, of course, given the appropriate content of s.
Somewhat different (easier but not type safe) also the scanf family has practical tools available in c++ as well c. You could of course write the example this way:
...
long n;
if (sscanf("+31321", "%d", &n) == 1)
std::cout << n << '\n';
...
A subset of regular expressions make this rather powerful: for instance to match a comma separed multi fields with left space trimming:
if (sscanf("a,b,c", " [^,], [^,], [^,]", a,b,c) == 3) ...
Related
int main()
{
char hmm[1000];
cin.getline(hmm, 1000);
cout << hmm << endl; //this was to test if I could assign my input to the array properly
for (int sayac = 0; hmm[sayac] != '#'; sayac++) {
if (!isdigit(hmm[sayac])) {
if (islower(hmm[sayac]))
cout << toupper(hmm[sayac]);
else if (isupper(hmm[sayac]))
cout << tolower(hmm[sayac]);
else
cout << hmm[sayac];
}
}
"Write a program that reads keyboard input to the # symbol and that echoes the input
except for digits, converting each uppercase character to lowercase, and vice versa.
(Don’t forget the cctype family.) "
I'm doing this exercise from the primer book. But when I run it, it returns the ascii order of the char, not the uppercase/lowercase version of the character. Couldn't figure out the problem. Can someone tell my why please?
(I may have other problems about the exercise, please don't correct them if I have. I want to fix it on my own (except the problem I explained), but I can't check the other ones as I have this problem.
When writing
std::cout << toupper('a');
the following happen:
int toupper(int ch) is called, and returns an integer whose value is 'A' (0x41).
std::basic_ostream::operator<<(std::cout, 0x41) is called, that is the int (2) overload since an int was provided.
Overall, it prints "65".
As a solution, you can cast back your upper case to a char:
std::cout << static_cast<char>(toupper('a'));
It's a question of representation. There is no difference between a character and that character's numeric value. It's all in how you choose to display it. For example, the character 'a' is just a constant with a value equal to the character's numeric value.
The problem you are having is that std::toupper and std::tolower return an int rather than a char. One reason for that is that they handle EOF values, which are not necessarily representable by char. As a consequence, std::cout see you are trying to print an int and not a char. The standard behavior for streaming an int is to print the number. The solution is then to cast your result to char to force the value to be interpreted as a character. You can use something like std::cout << static_cast<char>(std::toupper(hmm[sayac]));.
Try the following :
#include <cctype>
#include <iostream>
int main()
{
char hmm[1000];
std::cin.getline(hmm, 1000);
std::cout << hmm << std::endl; //this was to test if I could assign my input to the array properly
for (int sayac = 0; hmm[sayac] != '#'; sayac++) {
if (!std::isdigit(hmm[sayac])) {
if (std::islower(hmm[sayac]))
std::cout << static_cast<char>(std::toupper(hmm[sayac]));
else if (isupper(hmm[sayac]))
std::cout << static_cast<char>(std::tolower(hmm[sayac]));
else
std::cout << hmm[sayac];
}
}
}
You should also consider using an std::string instead of an array of char of arbitrary length. Also, take note that you have undefined behavior if the input string does not contain #.
int main()
{
char hmm[1000];
cin.getline(hmm, 1000);
cout << hmm << endl; //this was to test if I could assign my input to the array properly
for (int sayac = 0; hmm[sayac] != '#'; sayac++) {
if (!isdigit(hmm[sayac])) {
if (islower(hmm[sayac]))
cout << toupper(hmm[sayac]);
else if (isupper(hmm[sayac]))
cout << tolower(hmm[sayac]);
else
cout << hmm[sayac];
}
}
"Write a program that reads keyboard input to the # symbol and that echoes the input
except for digits, converting each uppercase character to lowercase, and vice versa.
(Don’t forget the cctype family.) "
I'm doing this exercise from the primer book. But when I run it, it returns the ascii order of the char, not the uppercase/lowercase version of the character. Couldn't figure out the problem. Can someone tell my why please?
(I may have other problems about the exercise, please don't correct them if I have. I want to fix it on my own (except the problem I explained), but I can't check the other ones as I have this problem.
When writing
std::cout << toupper('a');
the following happen:
int toupper(int ch) is called, and returns an integer whose value is 'A' (0x41).
std::basic_ostream::operator<<(std::cout, 0x41) is called, that is the int (2) overload since an int was provided.
Overall, it prints "65".
As a solution, you can cast back your upper case to a char:
std::cout << static_cast<char>(toupper('a'));
It's a question of representation. There is no difference between a character and that character's numeric value. It's all in how you choose to display it. For example, the character 'a' is just a constant with a value equal to the character's numeric value.
The problem you are having is that std::toupper and std::tolower return an int rather than a char. One reason for that is that they handle EOF values, which are not necessarily representable by char. As a consequence, std::cout see you are trying to print an int and not a char. The standard behavior for streaming an int is to print the number. The solution is then to cast your result to char to force the value to be interpreted as a character. You can use something like std::cout << static_cast<char>(std::toupper(hmm[sayac]));.
Try the following :
#include <cctype>
#include <iostream>
int main()
{
char hmm[1000];
std::cin.getline(hmm, 1000);
std::cout << hmm << std::endl; //this was to test if I could assign my input to the array properly
for (int sayac = 0; hmm[sayac] != '#'; sayac++) {
if (!std::isdigit(hmm[sayac])) {
if (std::islower(hmm[sayac]))
std::cout << static_cast<char>(std::toupper(hmm[sayac]));
else if (isupper(hmm[sayac]))
std::cout << static_cast<char>(std::tolower(hmm[sayac]));
else
std::cout << hmm[sayac];
}
}
}
You should also consider using an std::string instead of an array of char of arbitrary length. Also, take note that you have undefined behavior if the input string does not contain #.
I am currently studying C++ by watching bucky's C++ tutorial.
In the tutorial he shows how to use function overloading
but the variables values of a and b are fixed in his tutorial video.
I'm wondering what happens if the user needs to input something (decimal or whole number)
and how to make the program identify whether the input data is an int or an float.
here is the code in the tutorial video:
#include <iostream>
using namespace std;
void printnumber(int x){
cout << "I am printing an integer " <<x << endl;
}
void printnumber(float x){
cout << "I am printing an float: " << x << endl;
}
int main(){
int a = 54;
float b= 32.4896;
printnumber(a);
printnumber(b);
}
While here is the code I created:
#include <iostream>
using namespace std;
int a;
float b;
void printnumber(int x){
cout << "I am printing an integer " <<x << endl;
}
void printnumber(float x){
cout << "I am printing an float: " << x << endl;
}
int main(){
cout << "enter a whole number or a number with decimal: ";
cin >> ; //what will i put here?
printnumber(a);
printnumber(b);
}
This is not as trivial as one would think. One way could be to read the input as a string, and see if the string contains a decimal-point (which would cause problems on locales where the decimal-point is a comma instead).
Another solution is to read as a string, then try to convert it to a floating point value, and if that fails then convert it to an integer.
I would recommend the last method.
Or for simplicity's sake, just instruct the user to input an integer followed by a floating point value:
int a;
std::cout << "Enter an integer value: ";
std::cin >> a;
float b;
std::cout << "Enter a floating point value: ";
std::cin >> b;
Then hope that the user actually enters correct values.
You do not get the data until runtime, so you can't know the type at compile time, which is when the function overload is determined. Thus, you need to make some decision at runtime.
I suggest you look up my most favorite C++ book of all time, Advanced C++ Programming Styles and Idioms by Jim Coplien. Pay careful attention to the letter/envelop idiom, which describes how to accomplish what you want.
It may be overkill for this simple example, but it's worth learning since you are hunting for knowledge.
You will get a std::string back from cin which you will need to convert to the appropriate type once you detect if it has a dot or not.
std::string user_input;
cout << "enter a whole number or a number with decimal: ";
cin >> user_input;
if(user_input.find('.') != std::string::npos){
// we found a float (probably)
// uses boost library to make stuff easier
printNumber(boost::lexical_cast<float>(user_input));
}else{
printNumber(boost::lexical_cast<int>(user_input));
}
instead of boost::lexical_cast you can also use std::stringstream
std::stringstream ss;
ss << user_input;
if(user_input.find('.') != std::string::npos){
// we found a float (probably)
float f;
ss >> f;
printNumber(f);
}else{
int i;
ss >> i;
printNumber(i);
}
Joachim is right that this isn’t trivial. The “proper” way to do this is to use a parser.
Writing such a parser isn’t too hard – it just needs to check that the number is in the right format, by trying to read it as either type and retrying if it doesn’t work. A “cleaner” solution is to use a formal parsing framework such as Boost.Spirit.Qi.
Here’s a straightforward (but somewhat convoluted) solution:
int main() {
std::string value;
std::cin >> value;
std::size_t end;
int intval = std::stoi(value, &end);
if (end == value.size())
printnumber(intval);
else
printnumber(std::stof(value));
}
This checks that std::stoi converted the whole string rather than just parts of it.
Notice that this solution is not very robust since it does no proper error checking. In a real application I would strongly recommend going the Boost.Qi way because it makes the code simpler and more robust, but it requires some deeper C++ knowledge.
For reference, the “proper” solution using a parsing framework would look something like this:
struct printer : boost::static_visitor<void> {
template <typename T>
void operator ()(T const& value) const { printnumber(value); }
};
int main() {
std::string value;
std::cin >> value;
namespace qi = boost::spirit::qi;
auto begin = std::begin(value);
auto const end = std::end(value);
boost::variant<int, float> result;
bool success = qi::parse(begin, end, (qi::int_ >> !qi::lit('.')) | qi::float_, result);
if (not success or begin != end)
std::cerr << "Something went wrong\n";
else
apply_visitor(printer{}, result);
}
I'm having trouble with isdigit. I read the documentation, but when I cout << isdigit(9), I get a 0. Shouldn't I get a 1?
#include <iostream>
#include <cctype>
#include "Point.h"
int main()
{
std::cout << isdigit(9) << isdigit(1.2) << isdigit('c');
// create <int>i and <double>j Points
Point<int> i(5, 4);
Point<double> *j = new Point<double> (5.2, 3.3);
// display i and j
std::cout << "Point i (5, 4): " << i << '\n';
std::cout << "Point j (5.2, 3.3): " << *j << '\n';
// Note: need to use explicit declaration for classes
Point<int> k;
std::cout << "Enter Point data (e.g. number, enter, number, enter): " << '\n'
<< "If data is valid for point, will print out new point. If not, will not "
<< "print out anything.";
std::cin >> k;
std::cout << k;
delete j;
}
isdigit() is for testing whether a character is a digit character.
If you called it as isdigit('9'), it would return nonzero.
In the ASCII character set (which you are likely using), 9 represents the horizontal tab, which is not a digit.
Since you are using the I/O streams for input, you don't need to use isdigit() to validate the input. The extraction (i.e., the std::cin >> k) will fail if the data read from the stream is not valid, so if you are expecting to read an int and the user enters "asdf" then the extraction will fail.
If the extraction fails, then the fail bit on the stream will be set. You can test for this and handle the error:
std::cin >> k;
if (std::cin)
{
// extraction succeeded; use the k
}
else
{
// extraction failed; do error handling
}
Note that the extraction itself also returns the stream, so you can shorten the first two lines to be simply:
if (std::cin >> k)
and the result will be the same.
isdigit() takes an int which is the representation of the character. Character 9 is (assuming you're using ASCII) the TAB character. Character 0x39 or '9' (not 9) is the actual character representing the digit 9.
The digit characters are integer codes 0x30 through 0x39 (or 48 through 57) in ASCII - I reiterate that since ASCII is not a requirement of the ISO C standard. Hence the following code:
if ((c >= 0x30) && (c <= 0x39))
which I've seen before, is not a good idea for portability since there is at least one implementation that uses EBCDIC under the covers - isdigit is the best option in all situations.
isdigit() works on characters, not ascii values, which you are currently passing. Try using isdigit('9').
So I am currently learning C++ and decided to make a program that tests my skills I have learned so far. Now in my code I want to check if the value that the user enters is a double, if it is not a double I will put a if loop and ask them to reenter it. The problem I have is how do I go about checking what type of variable the user enters, ex- if a user enters a char or string, I can output an error message. Here is my code:
//cubes a user entered number
#include <iostream>
using namespace std;
double cube(double n); //function prototype
int main()
{
cout << "Enter the number you want to cube: "; //ask user to input number
double user;
cin >> user; //user entering the number
cout << "The cube of " << user << " is " << cube(user) << "." << endl; //displaying the cubed number
return 0;
}
double cube (double n) //function that cubes the number
{
return n*n*n; // cubing the number and returning it
}
Edit: I would have to say I just started and don't have the slightest of clue about your code, but I will check out your link. By the way, I haven't learned how to work with templates yet,I am learning about dealing with data, only Chapter 3 in my C++ Primer Plus 5th edition.
Safe C++ Way
You can define a function for this using std::istringstream:
#include <sstream>
bool is_double(std::string const& str) {
std::istringstream ss(str);
// always keep the scope of variables as close as possible. we see
// 'd' only within the following block.
{
double d;
ss >> d;
}
/* eat up trailing whitespace if there was a double read, and ensure
* there is no character left. the eof bit is set in the case that
* `std::ws` tried to read beyond the stream. */
return (ss && (ss >> std::ws).eof());
}
To assist you in figuring out what it does (some points are simplified):
Creation of a input-stringstream initialized with the string given
Reading a double value out of it using operator>>. This means skipping whitespace and trying to read a double.
If no double could be read, as in abc the stream sets the fail-bit. Note that cases like 3abc will succeed and will not set the fail-bit.
If the fail-bit is set, ss evaluates to a zero value, which means false.
If an double was read, we skip trailing whitespace. If we then are at the end of the stream (note that eof() will return true if we tried to read past the end. std::ws does exactly that), eof will return true. Note this check makes sure that 3abc will not pass our check.
If both cases, right and left of the && evaluate to true, we return true to the caller, signaling the given string is a double.
Similar, you check for int and other types. If you know how to work with templates, you know how to generalize this for other types as well. Incidentally, this is exactly what boost::lexical_cast provides to you. Check it out: http://www.boost.org/doc/libs/1_37_0/libs/conversion/lexical_cast.htm.
C Way One
This way has advantages (being fast) but also major disadvantages (can't generalized using a template, need to work with raw pointers):
#include <cstdlib>
#include <cctype>
bool is_double(std::string const& s) {
char * endptr;
std::strtod(s.c_str(), &endptr);
if(endptr != s.c_str()) // skip trailing whitespace
while(std::isspace(*endptr)) endptr++;
return (endptr != s.c_str() && *endptr == '\0');
}
strtod will set endptr to the last character processed. Which is in our case the terminating null character. If no conversion was performed, endptr is set to the value of the string given to strtod.
C Way Two
One might thing that std::sscanf does the trick. But it's easy to oversee something. Here is the correct way to do it:
#include <cstdio>
bool is_double(std::string const& s) {
int n;
double d;
return (std::sscanf(s.c_str(), "%lf %n", &d, &n) >= 1 &&
n == static_cast<int>(s.size()));
}
std::sscanf will return the items converted. Although the Standard specifies that %n is not included in that count, several sources contradict each other. It's the best to compare >= to get it right (see the manpage of sscanf). n will be set to the amount of the processed characters. It is compared to the size of the string. The space between the two format specifiers accounts for optional trailing whitespace.
Conclusion
If you are a beginner, read into std::stringstream and do it the C++ way. Best not mess with pointers until you feel good with the general concept of C++.
There is no suitable way to check if a string really contains a double within the standard library. You probably want to use Boost. The following solution is inspired by recipe 3.3 in C++ Cookbook:
#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;
double cube(double n);
int main()
{
while(true)
{
cout << "Enter the number you want to cube: ";
string user;
cin >> user;
try
{
// The following instruction tries to parse a double from the 'user' string.
// If the parsing fails, it raises an exception of type bad_lexical_cast.
// If an exception is raised within a try{ } block, the execution proceeds
// with one of the following catch() blocks
double d = lexical_cast <double> (user);
cout << "The cube of " << d << " is " << cube(d) << "." << endl;
break;
}
catch(bad_lexical_cast &e)
{
// This code is executed if the lexical_cast raised an exception; We
// put an error message and continue with the loop
cout << "The inserted string was not a valid double!" << endl;
}
}
return 0;
}
double cube (double n)
{
return n*n*n;
}
sscanf can do what you want; it returns the number of arguments properly processed. This should get you started:
//cubes a user entered number
#include <iostream>
#include <cstdio>
using namespace std;
double cube(double n); //function prototype
int main()
{
cout << "Enter the number you want to cube: "; //ask user to input number
string user;
cin >> user; //user entering the number
// Convert the number to a double.
double value;
if(sscanf(user.c_str(), "%lf", &value) != 1)
{
cout << "Bad! " << user << " isn't a number!" << endl;
return 1;
}
cout << "The cube of " << user << " is " << cube(user) << "." << endl; //displaying the cubed number
return 0;
}
double cube (double n) //function that cubes the number
{
return n*n*n; // cubing the number and returning it
}
Other methods posted in other answers have their advantages and disadvantages. This one has issues with trailing characters and isn't "C++"-y.
I would have to say I just started and don't have the slightest of clue about your code, but I will check out your link. By the way, I haven't learned how to work with templates yet,I am learning about dealing with data, only Chapter 3 in my C++ Primer Plus 5th edition.
You can fall back on C and use strtod
You program reads in a string and then passes it to a function that attempts to convert the string into double.
bool is_double(const char* strIn, double& dblOut) {
char* lastConvert = NULL;
double d = strtod(strIn, &lastConvert);
if(lastConvert == strIn){
return false;
} else {
dblOut = d;
return true;
}
}