isdigit() c++, probably simple question, but stuck - c++

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').

Related

Why does toupper function return an ASCII instead of a char? [duplicate]

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 #.

How to read unknown number of inputs?

I am learning C++ using the book C++ Primer.
In Section 1.4.3, the following example code about reading the unknown number of inputs is given.
#include <iostream>
int main()
{
int sum = 0, value = 0;
// read until end-of-file, calculating a running total of all values read
while (std::cin >> value)
sum += value; // equivalent to sum = sum + value
std::cout << "Sum is: " << sum << std::endl;
return 0;
}
According to the book, if we give an input of 3 4 5 6, the output will be Sum is: 18
But when I try this on my computer(Windows 10 with MinGW), The code does not end. It just keeps on asking for input even if I enter a newline. It works only when I enter a non-int input like f.
Is this expected? If yes, is there any code that stops after inputting a newline?
I am quite new to c++ and I have already learned python, so getting stuck so early on is quite frustrating.
Thanks and regards.
You need to terminate your input by an End-Of-File-character (i.e. CTRL-Z on Windows, CTRL-D on Mac/Unix), not just by an End-Of-Line (i.e. Enter).
A simple Enter is interpreted as white space, which will be simply ignored by operator>> when reading into an integral data type.
CTRL-Z / End-Of-File, in contrast, makes any operator>> fail with an error.
See also this SO answer.
Note: Entering f will also terminate your loop, since f is not considered a valid integral number; Hence, std::cin >> value with value being of type int and an input like f will fail as well. To be more accurate: operator>> actually returns a reference to the input stream, but if reading in a value fails, failbit is set on the stream, and then interpreting the stream object in a boolean expression (implicitly calling basic_istream::operator bool()) returns false; So maybe the author of the book did not want to explain these details at the respective section in the book :-)
Is this expected?
Yes, as operator>> ignores leading whitespace by default, which includes line breaks.
If yes, is there any code that stops after inputting a newline?
Use std::cin.getline() or std::getline() instead of operator>>. You can then use operator>> with a std::istringstream to parse values from each line, eg:
#include <iostream>
#include <string>
#include <sstream>
int main()
{
std::string line;
int sum, value;
do
{
std::cout << "Enter a set of numbers, or a blank line to exit: ";
if (!std::getline(std::cin, line) || line.empty())
break;
// read until end-of-line, calculating a running total of all values read
std::istringstream iss(line);
sum = 0;
while (iss >> value)
sum += value; // equivalent to sum = sum + value
std::cout << "Sum is: " << sum << std::endl;
}
while (true);
return 0;
}
Live Demo
Is this expected?
Yes, Thats what while (std::cin >> value) does. See this answer for more explanations: How is "std::cin>>value" evaluated in a while loop?
is there any code that stops after inputting a newline?
No, as >> simply ignore a white space(also #StephanLechner mentioned it)
What you can do instead is:
Just give a condition; if it satisfies just break the loop. you
can also provide a console out to make it more understandable to the
user. For example:
std::cout << "Enter value to sum or press -1 to exit" << std::endl;
while (std::cin >> value && value != -1) // if value == -1, loop stops.
{
sum += value;
}
You can simply terminate by the end of character:
CTRL-Z on Windows
CTRL-D on Mac/Unix

Using toupper on char returns the ascii number of the char, not the character?

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 #.

C++ stringstream, if word is numeric, divide by two

I am fairly new to programming and have to create a program which reads the prompt: "I have 8 dollars to spend." It then needs to print out with each word on a separate line, and then if any of the strings is numeric, it needs to be divided by 2. Therefore it should end up printing out as:
I
have
4
dollars
to
spend.
I have managed to do everything, except finding the numeric value and dividing it by 2. So far I have this:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
string prompt;
string word;
cout << "Prompt: ";
getline(cin, prompt);
stringstream ss;
ss.str(prompt);
while (ss >> word)
{
cout << word << endl;
}
return 0;
}
After looking through various other posts, I cannot manage to get this to work. I'm assuming its an if/else statement within the while loop along the lines of, if numeric, set int num to num / 2 then cout << num << endl;, else cout << word << endl;, but I can't figure it out.
Thanks in advance.
You can use the stringstream class, which handles conversions between strings and other data types, to attempt to convert a given string to a number. If the attempt is successful, you know
The stringstream object allows you to treat a string as though it is a stream similar to cin or cout.
Incorporate this into your while loop, like so:
while (ss >> word)
{
int value = 0;
stringstream convert(word); //create a _stringstream_ from a string
//if *word* (and therefore *convert*) contains a numeric value,
//it can be read into an _int_
if(convert >> value) { //this will be false if the data in *convert* is not numeric
cout << value / 2 << endl;
}
else
cout << word << endl;
}
The strtol (C++11 version that works on std::string directly: std::stol) function is really good for testing whether a string holds a number, and if so, what the numeric value is.
Or you could continue using iostreams like you have been... try extracting a number (int or double variable), and if that fails, clear the error bit and read a string.
I dont have 50 rep so I cant comment, thats why I'm writing it as answer.
I think you can check it character by character, using Ascii value of each char, & if there are ascii values representing numbers between two spaces(two \n in this case as you've already seperated each word), then you have to divide the number by 2.

Is there a TryParse equivalent in C++ (gcc)?

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) ...