So far, this is my code:
while(bet > remaining_money || bet < 100)
{
cout << "You may not bet lower than 100 or more than your current money. Characters are not accepted." << endl;
cout << "Please bet again: ";
cin >> bet;
}
It works fine but I'm trying to figure out how to make it loop if the user inputs anything that isn't a number as well.
When I press a letter or say a symbol/sign, the code just breaks.
Using the function
isdigit()
This function returns true if the argument is a decimal digit (0–9)
Don't forget to
#include <cctype>
I would use std::getline and std::string to read the whole line and then only break out of the loop when you can convert the entire line to a double.
#include <string>
#include <sstream>
int main()
{
std::string line;
double d;
while (std::getline(std::cin, line))
{
std::stringstream ss(line);
if (ss >> d)
{
if (ss.eof())
{ // Success
break;
}
}
std::cout << "Error!" << std::endl;
}
std::cout << "Finally: " << d << std::endl;
}
A good way of doing this is to take the input as a string. Now find the length of the string as:
int length = str.length();
Make sure to include string and cctype. Now, run a loop that checks the whole string and sees if there is a character that is not a digit.
bool isInt = true;
for (int i = 0; i < length; i++) {
if(!isdigit(str[i]))
isInt = false;
}
If any character is not a digit, isInt will be false. Now, if your input(a string) is all digits, convert it back to an integer as:
int integerForm = stoi(str);
Store integerForm in your array.
Related
I need to make a program which converts all letters to uppercase.
But first I need to get an input from the user. And I need to check if there are characters that are not space or alphabet.
This is what I tried.
#include <iostream>
#include <cctype>
using namespace std;
int main()
{
string s;
cout << "Enter a string: ";
while (getline(cin, s)){
for (int i = 0; i<s.length(); i++){
if ((isspace(s[i]) || isalpha(s[i]))){
for (int i = 0; i < s.length(); i++){
s[i] = toupper(s[i]);
}
cout << s << endl;
return 1;
}
cout << "Invalid string. Please input only alphabets or space character. " << endl << "Enter a string: ";
}
}
//if the input value is valid convert and print
return 0;}
This program successfully make error messages to pure numbers and pure question marks. But the problem is if there are invalid characters and valid characters mixed in the input, it cannot distinguish it.
For example, if input is "Hi?", the program thinks its a valid input. But with questions marks, the string should be invalid.
I think the for statement is the problem. How can I solve this?
I've made a few changes to deal with the break out conditions in your loops without changing the structure of your program too much.
Here's one example how you could get it to work. Comments in the code.
#include <cctype>
#include <iostream>
#include <string>
int main() {
std::string s;
while(std::cout << "Enter a string: " && std::getline(std::cin, s)) {
bool valid = true; // will stay true unless at least one char is invalid
for(char& ch : s) { // use a range-based for loop
// ch is now a reference to the char in the string
// convert to unsigned char - these functions are not safe
// otherwise:
if(std::isspace(static_cast<unsigned char>(ch)) ||
std::isalpha(static_cast<unsigned char>(ch)))
{
ch = std::toupper(static_cast<unsigned char>(ch));
continue; // continue to check the next character
}
std::cout << "Invalid character ('" << ch << "') in string.\n"
"Please input only alphabets or space character.\n";
valid = false; // to let the user enter a new string
break; // no need to check more characters, the string is invalid
}
if(valid) break; // break out only if all characters are valid
}
if(std::cin)
std::cout << "The valid string is now " << s << '\n';
}
A similar program could use algorithms from <algorithm> to do the check and the transformation of the string to uppercase.
Example:
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
int main() {
std::string s;
// the manual loop replaced by a simple algorithm that checks if any
// character in the string is invalid by using a lambda, here called
// "is_invalid":
auto is_invalid = [](unsigned char ch) {
return !(std::isspace(ch) || std::isalpha(ch));
};
while(std::cout << "Enter a string: " &&
std::getline(std::cin, s) &&
std::any_of(s.begin(), s.end(), is_invalid))
{
std::cout << "Invalid character in string.\n"
"Please input only alphabets or space character.\n";
}
if(std::cin) {
// transform the valid string to uppercase using another lambda.
// the lambda is here only to make the chars into unsigned chars
// to make the use of std::toupper safe
auto to_upper = [](unsigned char ch) { return std::toupper(ch); };
std::transform(s.begin(), s.end(), s.begin(), to_upper);
std::cout << "The valid string is now " << s << '\n';
}
}
I need to insert a character into a string at every instance of that character. For example if my string was, "This is a test" and my character was 's' then my output would need to look like this: "Thiss iss a tesst"
any idea why this isn't working? Here's what I have so far. I am not supposed to add any extra preprocessor instructions or anything, just using what's here I need to figure this out.
#include <iostream>
#include <string>
using namespace std;
int main(){
string userString;
char userChar;
cin >> userString;
cin >> userChar;
for (int i = 0; i < userString.size(); i++){
if(userString.at(i) == userChar){
userString.insert(userString.begin() + i, userChar);
}
}
cout << userString;
return 0;
Update:
Here's the solution I worked out.
#include <iostream>
#include <string>
using namespace std;
int main(){
string userString;
char userChar;
cout << "enter a string" << endl;
getline(cin, userString);
cout << "enter a character" << endl;
cin >> userChar;
for (int i = userString.size()-1; i >= 0; i--){
if(userString.at(i) == userChar){
userString.insert(userString.begin() + i, userChar);
}
}
cout << userString;
return 0;
}
I don't know why you want to go through the string backwards. Anyway. Your problem is that once you insert a character at some position, your loop will encounter the inserted character again in the next iteration and insert another. Ad infinitum.
#include <cstddef> // std::size_t, the correct type for indexes and sizes of objects in mem
#include <string>
#include <iostream>
int main()
{
std::cout << "Enter a string: ";
std::string userString; // define variables as close
std::getline(std::cin, userString);
std::cout << "Enter a character: ";
char userChar; // to where they're used as possible
std::cin >> userChar;
for (std::size_t i{}; i < userString.size(); ++i) {
if (userString[i] == userChar) { // no need to use std::string::at() 1)
userString.insert(userString.begin() + i, userChar);
++i; // advance the index to not read the same character again.
}
}
std::cout << userString << '\n';
}
1) since it is allready sure that the index will be in a valid range.
Your first solution probably ends up looping infinitely if you ever find one of the chosen character because you always insert one more copy ahead and keeps finding the same char ever after.
std::basic_string has a find function. It's always better to use code offered by a library than self made code. Here's my proposed solution:
std::string& duplicate_char(std::string& str, char val)
{
using std::string;
auto pos = str.find(val); // finds first index of character val or npos if unsuccessful
while (pos != string::npos)
{
str.insert(pos, 1, val); // insert at pos one character val
pos = str.find(val, pos + 2); // find the next occurence of val starting after the newly inserted character
}
return str;
}
You may use this function like this:
int main()
{
std::string testStr{"Thiss iss a tesst"};
duplicate_char(testStr, 's');
std::cout << testStr << std::endl;
}
The 'program' is to take input in then spit the string back out on seperate lines and all numbers are to be multiplied by two in this case.
My issue occurs when a number is input after a white space.
Example
Sentence: 12 fish
Outputs:
24
fish
But...
Sentence: there are 12
Outputs:
there
are
0
The program I have written:
#include <iostream>
#include <string>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
using namespace std;
int main()
{
string str;
int number = 811;
cout << "Sentence: ";
getline(cin,str);
istringstream iss(str);
while(iss)
{
bool ree = 0;
string word;
iss >> word;
if(isdigit(word[0]))
{
stringstream(str) >> number;
number = (number * 2);
cout << number << endl;
ree = 1;
number = 911;
}
if(!ree)
{
cout << word << endl;
}
ree = 0;
}
}
Hopefully it's something small I am not seeing!
Thanks for the help in advanced.
The problem is that
stringstream(str) >> number;
creates a fresh string stream from the initial sentence, then tries to extract from it into number. Of course that will fail (as the first word in the sentence is not a number). If you wonder why number was set to 0, that's because on failure, the stringstream::operator>> zeros the argument (since C++11).
"If extraction fails, zero is written to value and failbit is set." ...
Before C++11, it left the argument unchanged. See the documentation for more details.
The correct way is to use a conversion from string to int (or long), namely std::stoi, and replace that line by
try{
number = std::stoi(word);
}
catch(std::exception& e){
std::cout << "error converting" << '\n';
}
Use stoi to parse the input like this:
int num = std::stoi(input);
using stoi is easy, and you can lazily catch the exception by the following:
if(!stoi(string)){
std::cout << "caught a non integer string" << endl;
}
I'm working on homework for my c++ class, and it's been quite awhile since I've used it. I was wondering if there was a way to allow spaces in a string (instead of it nulling out and ending the string)
my current code is this:
int chapter10() {
string strinput;
char charstr[1000];
int numwords=1;
cout << "Enter a phrase ";
cin >> strinput;
cout << strinput;
const int size = strinput.size() + 1;
strcpy_s(charstr, strinput.c_str());
cout << strinput << endl;
for (int i = 0; i != size; i++) {
if (*(charstr + i) == ' ')
numwords++;
}
cout << "There are " << numwords << " words in that string." << endl;
return 0;
}
The problem I'm having, is for instance, if I type "Hello World" and press enter, it pops the next line (right after the cin) and says "Hello", and the space made it cut the rest of the phrase off.
How does one fix this issue? I don't want to use the str:: things as I barely know what they are, and have really never had to use them, and that would look a bit suspicious to the teacher :P
Update: If you've suggested using getline(cin, strinput); It doesn't work too well. I can from what I see, only type in the 10 to reach my function, but after I press enter, it thinks that I've presses something else, which makes it completely skip the cin to get the string value. But, there is something weird with this, if I type "10 hello world" it does everything correctly. Well, with the exception that it needs to be in the same line as the number to reach the function.
Solved: The use of getline(cin, strinput) works perfectly fine, if you're not using user input before hand. If you are, you're going to need a cin.ignore before the getline(). As stated in the comment by my best answer.
#include <iostream>
#include <iomanip>
#include <string>
#include <limits>
using namespace std;
//~~~Initialize all functions
int chapter10();
//~~~Initializing complete
int main() {
srand(time(0)); //makes rng thingy work instead of choose same numbers cause it doesn't do it on its own. lol
cout << "Enter the chapter number you need to look at: ";
int chapterNumber;
cin >> chapterNumber;
switch (chapterNumber) {
case 1: testingStuff(); break;
case 9: chapter9(); break;
case 10: chapter10(); break;
default: cout << "You chose an invalid chapter number, reload the program."; break;
}
system("pause");//So console doesn't close instantly cause that's not annoying at all...
}
int chapter10() {
string strinput;
char charstr[10000];
int numwords=1;
cout << "Enter a phrase." << endl;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
getline(cin, strinput);
const int size = strinput.size() + 1;
strcpy_s(charstr, strinput.c_str());
for (int i = 0; i != size; i++) {
if (*(charstr + i) == ' ' & *(charstr + (i+1)) != ' ' )//the & is fail safe so multiple space no ++numwords
numwords++;
}
cout << "There are " << numwords << " words in that string." << endl;
return 0;
}
The way I have my code written was I used a switch/case to reach my function. This required user input, which in turn caused my program to 'think' I was still typing for the second input required in the chapter10 function.
Adding in the line of code: cin.ignore(numeric_limits<streamsize>::max(), '\n'); allowed me to cancel the input, and start a new one.
If you want to get all characters an end-user enters on a single line, use getline: instead of cin >> strinput write this:
getline(cin, strinput);
The fact that it is actually std::getline(std::cin, strinput) makes no difference, because your code uses std namespace anyway. In case you were wondering what std:: prefix is, it's a namespace of the Standard C++ library.
You can use getline() function
It copies into a string till a newline is reached or delimiter is found - so it will accept all the spaces till newline is reached
http://www.cplusplus.com/reference/string/string/getline/
or you can also use cin.getline() as shown here -
std::cin input with spaces?
use:
cin >> noskipws >> strinput;
Use std::getline() function. Example:
#include <iostream>
#include <vector>
#include <sstream>
void WordCounter(
const std::vector<std::string> & lines) {
for (int i = 0; i < lines.size(); ++i) {
std::istringstream iss(lines[i]);
std::string word;
int count = 0;
while (iss >> word) {
++count;
}
std::cout << "Line #" << i << " contains " << count << " words." <<
std::endl;
}
}
int main() {
std::string line;
std::vector<std::string> lines;
while (std::getline(std::cin, line)) {
lines.push_back(line);
}
WordCounter(lines);
return 0;
}
Hi I'm trying to take a c-string from a user, input it into a queue, parse the data with a single space depending on its contents, and output the kind of data it is (int, float, word NOT string).
E.g. Bobby Joe is 12 in 3.5 months \n
Word: Bobby
Word: Joe
Word: is
Integer: 12
Word: in
Float: 3.5
Word: months
Here's my code so far:
int main()
{
const int maxSize = 100;
char cstring[maxSize];
std::cout << "\nPlease enter a string: ";
std::cin.getline(cstring, maxSize, '\n');
//Keyboard Buffer Function
buffer::keyboard_parser(cstring);
return EXIT_SUCCESS;
}
Function:
#include <queue>
#include <string>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <vector>
namespace buffer
{
std::string keyboard_parser(char* input)
{
//Declare Queue
std::queue<std::string> myQueue;
//Declare String
std::string str;
//Declare iStringStream
std::istringstream isstr(input);
//While Loop to Read iStringStream to Queue
while(isstr >> str)
{
//Push onto Queue
myQueue.push(str);
std::string foundDataType = " ";
//Determine if Int, Float, or Word
for(int index = 0; index < str.length(); index++)
{
if(str[index] >= '0' && str[index] <= '9')
{
foundDataType = "Integer";
}
else if(str[index] >= '0' && str[index] <= '9' || str[index] == '.')
{
foundDataType = "Float";
break;
}
else if(!(str[index] >= '0' && str[index] <= '9'))
{
foundDataType = "Word";
}
}
std::cout << "\n" << foundDataType << ": " << myQueue.front();
std::cout << "\n";
//Pop Off of Queue
myQueue.pop();
}
}
}
Right now with this code, it doesn't hit the cout statement, it dumps the core.
I've read about using the find member function and the substr member function, but I'm unsure of how exactly I need to implement it.
Note: This is homework.
Thanks in advance!
UPDATE: Okay everything seems to work! Fixed the float and integer issue with a break statement. Thanks to everyone for all the help!
Your queue is sensible: it contains std::strings. Unfortunately, each of those is initialised by you passing cstring in without any length information and, since you certainly aren't null-terminating the C-strings (in fact, you're going one-off-the-end of each one), that's seriously asking for trouble.
Read directly into a std::string.
std::istreams are very useful for parsing text in C++... often with an initial read of a line from a string, then further parsing from a std::istringstream constructed with the line content.
const char* token_type(const std::string& token)
{
// if I was really doing this, I'd use templates to avoid near-identical code
// but this is an easier-to-understand starting point...
{
std::istringstream iss(token);
int i;
char c;
if (iss >> i && !(iss >> c)) return "Integer";
}
{
std::istringstream iss(token);
float f;
char c; // used to check there's no trailing characters that aren't part
// of the float value... e.g. "1Q" is not a float (rather, "word").
if (iss >> f && !(iss >> c)) return "Float";
}
return "Word";
}
const int maxSize = 100; // Standard C++ won't let you create an array unless const
char cstring[maxSize];
std::cout << "\nPlease enter a string: ";
if (std::cin.getline(cstring, maxSize, '\n'))
{
std::istringstream iss(cstring);
std::string token;
while (iss >> token) // by default, streaming into std::string takes a space-...
token_queue.push(token); // ...separated word at a time
for (token_queue::const_iterator i = token_queue.begin();
i != token_queue.end(); ++i)
std::cout << token_type(*i) << ": " << *i << '\n';
}