Forcing user to enter certain pattern when request input - c++

Is there some way of forcing the user to enter a certain pattern when I request input?
For example, If I request they enter five numbers (xx x xx)
I was wondering maybe an array that I can enter my pattern into, then it be matched to the input, but not for value obviously.
I do not know how I would do this (if its possible).
I am a beginner, as you can tell, so I thought I would come here cause you would know. If this is not possible, how else can this be done?

You can write while loop where you'll enter your input while some condition is true.
while(std::cin >> input){
if (checkInput(input))
break;
}
Function checkInput will check your input and returns true if your input matches some requirements.

For matching patterns in string I use the regex functions from the standard library (https://en.cppreference.com/w/cpp/regex)
You can use this site to test regular expressions : https://regex101.com/
#include <cassert>
#include <regex>
bool is_valid_input(const std::string& input)
{
// (xx x xx) needs pattern "\(\d{2} \d \d{2}\)"
// in code you get even more backslashes
static std::regex rx{ "\\(\\d{2} \\d \\d{2}\\)" };
static std::smatch match;
return std::regex_match(input, match, rx);
};
int main()
{
const std::string good_input{ "(12 3 45)" };
const std::string bad_input{ "(x3 4 55" };
assert(is_valid_input(good_input));
assert(!is_valid_input(bad_input));
}

You should have a while loop checking the input and breaking when the input is the correct pattern you want.
#include <iostream>
#include <string>
using namespace std;
int main() {
char numbers;
cout << "Enter 5 numbers: ";
cin >> numbers;
while(!checkForValidPattern(numbers)) {
cout << "Try 5 numbers XXXXX : ";
cin >> numbers;
}
cout << "numbers = " << numbers << endl;
return 0;
}
Of course, you will have to create the validation function and it depends on your specific need.

Do you mean simply with the correct location of spaces? If so perhaps you could read the third character in the string and the 5th and if they are anything other than whitespace then reject it. Maybe something like
while (true) {
std::cout << "input: ";
std::string input;
std::cin >> input; // e.g. "12 3 45"
char const correct1 = input[2];
if (correct1 == ' ') {
break;
} else {
std::cout << "Incorrect pattern";
}
}
You would then do the same for the 5th character
This may be entirely incorrect but thats roughly what I would do.

Related

Convert Text with spaces to Camel Case

i want to take a film name from user and change that to camel case , my code work if there is no numbers or spaces between letters
#include <iostream>
#include <string>
using namespace std;
int main()
{
int Count,Length=0;
string Films;
cout<<"Enter Film Count: ";
cin>>Count;
for(int i=0;i<Count;i++)
{
cout<<"Enter Film Names: ";
cin>>Films;
Length=0;
while(Length<1000)
{
switch(Length)
{
case 0: Films[Length]=toupper(Films[Length]); break;
default: Films[Length]=tolower(Films[Length]); break;
}
Length++;
}
cout<<"Results: "<<Films<<endl;
}
return 0;
}
i tried other topic solutions but i cant do it correctly.
Problem:
You've chosen the wrong approach to solve the problem. Your current code only changes the first character to uppercase and the rest to lowercase.
Solution:
Instead of using a while and a switch, use a for loop and an if statement that checks for spaces, delete them and change the following characters to uppercase.
Additional information:
using namespace std; is considered a bad practice (More info here).
The while loop can be replaced for a for loop to limit the Length scope and improve readability.
It's a good practice to check whether the std::cin inputs are valid or not to prevent Undefined Behavior.
Full code:
#include <iostream>
#include <string>
int main()
{
int count;
std::cout << "Enter film count: ";
std::cin >> count;
if(std::cin.fail())
{
std::cout << "Invalid input." << std::endl;
exit(0);
}
std::cin.ignore(10000,'\n');
for(int i = 0; i < count; i++)
{
std::string film;
std::cout << "Enter film name: ";
std::getline(std::cin, film);
if(std::cin.fail())
{
std::cout << "Invalid input." << std::endl;
exit(0);
}
if(film.size() == 0)
break;
film[0] = tolower(film[0]);
for(unsigned int i = 1; i < film.size() - 1; i++)
{
if(film[i] == ' ')
{
film.erase(i,1);
film[i] = toupper(film[i]);
i--;
}
}
std::cout << "Result: " << film << std::endl;
}
return 0;
}
Example:
Enter film count: 1
Enter file name: Love live! the school idol movie
Result: loveLive!TheSchoolIdolMovie
I could see really a lot of code to solve a simple problem. I will later show a one-liner that converts a string with words to camel case.
As a side note, code should always contain tons of comments. Otherwise, nobody will understand it, and later, even you will not understand your own code.
Anyway. Let us look at the requirements. What shall we do?
User shal input the number of film titles to convert
Title for title shall be read from the user
Titles have to converted to camel case style and shown to the user
Now, we think an how we want to solve the problem:
We will always instruct the user what to do next
We will make sanity checks for the users input
We will get the number of titles from the user
Then, we create a loop and read title for title
The current read title will be converted to camel case
The result will be shown to the user
Ok, we need to go into details for "The current read title will be converted to camel case"
Let us think again. We get a string, that consists of words. So, we need to extract words from the string. We consider that everything is a word, that is separated by white space.
Then, depending on the camle case style, please see here, we convert all first letters of a word to uppercase and discard all white spaces. The first word will have a starting lower case letter (selectable).
But how to extract words from a string? We remember the extractor operator >> will discard all white spaces and only read the text. That is what we need. So, we will pack the string into an std::istringstream and then extract word for word.
And with a simple boolean condition, we decide, if the first letter of the first word shall be in upper- or lower case.
So, let us implement or thoughts into code:
#include <iostream>
#include <sstream>
#include <string>
#include <cctype>
int main() {
// Instruct user, what to do
std::cout << "\nPlease end number of film titles to convert: ";
// Read input from the user and check, if that was valid
if (size_t numberOfFilms{}; std::cin >> numberOfFilms && numberOfFilms > 0) {
// Now, in a loop, read all the film titles that the user wants to be processed
for (size_t index{}; index < numberOfFilms; ++index) {
// Instruct user, what to do
std::cout << "\n\nPlease end film title " << index + 1 << ": \t";
// Read a complete line and check, if that worked
if (std::string line{}; std::getline(std::cin >> std::ws, line)) {
// Put the complete string into an istringstream, so that we can extract the words
std::istringstream lineStream{line};
// Here we can select the style of our camel case
bool wordShallHaveFirstLetterInUpperCase{ false };
// Extract all words from the line stream and convert first letter
for (std::string word{}; lineStream >> word; std::cout << word) {
// Depending on the camel case style
if (wordShallHaveFirstLetterInUpperCase)
word[0] = std::toupper(word[0]);
else
word[0] = std::tolower(word[0]);
// From now on all words shall start with an uppercase character
wordShallHaveFirstLetterInUpperCase = true;
}
}
else std::cerr << "\n\n*** Error: Problem while a title\n\n";
}
}
else std::cerr << "\n\n*** Error: Problem while reading the number of ilm titles\n\n";
return 0;
}
This is a rather straight forward implementation of our detailed design. And after running some tests, we see that it will work.
Now, for the more advanced users.
In professional software development, people try to avoid loops and branch statements. Because this will increase the code complexity (usually measured via the cyclomatic complexity). And complex code needs more tests cases for C0, C1 or even MCDC code coverage.
Therefore, often algorithms from the standard library are used. And they hide the loops somehow inside. But that is OK, because the standard library is thoroughly tested and sometimes even qualified with a certification.
So, as one example, you can do the whole camel case conversion with one statement. With std::transform and by using std::regex and iterators and a stateful Lambda.
The downside is, that it is not so easy to understand for the reader . . .
Please see yourself:
#include <iostream>
#include <iterator>
#include <algorithm>
#include <regex>
#include <string>
#include <cctype>
// The separator will be white space
const std::regex re{ R"(\s+)" };
int main() {
// Instruct user, what to do
std::cout << "\nPlease end number of film titles to convert: ";
// Read input from the user and check, if that was valid
if (size_t numberOfFilms{}; std::cin >> numberOfFilms && numberOfFilms > 0) {
// Now, in a loop, read all the film titles that the user wants to be processed
for (size_t index{}; index < numberOfFilms; ++index) {
// Instruct user, what to do
std::cout << "\n\nPlease end film title " << index+1 << ": \t";
// Read a complete line and check, if that worked
if (std::string line{}; std::getline(std::cin >> std::ws, line)) {
// Convert to camel case and show output
std::transform(std::sregex_token_iterator(line.begin(), line.end(), re, -1), {}, std::ostream_iterator<std::string>(std::cout),
[firstIsUpper = 0U](std::string s) mutable {if (firstIsUpper++) s[0] = std::toupper(s[0]); else s[0] = std::tolower(s[0]); return s; });
}
else std::cerr << "\n\n*** Error: Problem while a title\n\n";
}
}
else std::cerr << "\n\n*** Error: Problem while reading the number of ilm titles\n\n";
return 0;
}
Ultra compact, but difficult to read . . .
In case of questions, please ask.

Extract all numbers from stringstream

I want to read string and extract all numbers.
Input: 5a3 1f a0aaaa f1fg3
Output: 53 1 0 13
I tried this code:
string s;
getline(cin, s);
stringstream str_strm(s);
int found;
string temp;
while (!str_strm.eof()) {
str_strm >> temp;
if (stringstream(temp) >> found)
{
cout << found << endl;
}
}
but when found 5 (from example)after that automatically start to check the other string. How can I extract all numbers?
Here's a possible solution - while loop is used to separate strings with whitespaces, after that digits are extracted from the sub-strings.
int main()
{
stringstream ss("5a3 1f a0aaaa f1fg3");
string str;
while (getline(ss, str, ' ') ){
str.erase(std::remove_if(str.begin(), str.end(), [](unsigned char c) { return !std::isdigit(c); }), str.end());
cout << str << " ";
}
}
You could read each space separated word, and then remove the non-digits, like this
std::string word;
while (std::cin >> word)
{
word.erase(std::remove_if(word.begin(), word.end(),
[](unsigned char c) { return not std::isdigit(c); }),
word.end());
std::cout << word << " ";
}
For the input of 5a3 1f a0aaaa f1fg3, it prints 53 1 0 13.
The admittedly odd way of removing elements of a range, is a common idiom.
You could even avoid the loop entirely, if you have the input on a single line
std::string word;
std::getline(std::cin, word);
word.erase(std::remove_if(word.begin(), word.end(),
[](unsigned char c) { return not std::isdigit(c)
and not std::isspace(c); }),
word.end());
std::cout << word;
Please see here the ultra simple example. (There is an even simpler solution at the bottom of this post)
It is using modern C++ elements and algorithms. And has only a few lines of code.
#include <iostream>
#include <string>
#include <regex>
#include <iterator>
#include <algorithm>
#include <sstream>
int main() {
// Read a string from the console
if (std::string line{}; std::getline(std::cin, line)) {
// Put the complete line into a std::istringstream
std::istringstream iss{line};
// Print result
std::transform(std::istream_iterator<std::string>(iss), {}, std::ostream_iterator<std::string>(std::cout, " "),
[](const std::string& s) { return std::regex_replace(s, std::regex{ R"([^\d])" }, ""); });
}
return 0;
}
So, what's going on here. Let us look at it statement by statement. So, first:
if (std::string line{}; std::getline(std::cin, line)) {
This is a if-statement with initializer. If you look up if in the C++ reference, here, then you can see, that we can now have an additional initialization statement as the first part in the if. And why are we using that? Because it is an additional measure for scoping. The variable "line" is only used within the scope of the if statement. It is not needed outside the if. From the functionality point of view, it is the same as writing:
std::string line{};
if (std::getline(std::cin, line)) {
But then, "line" would be also visible outside of the if statement. And, because we want to prevent the pollution of outer namespace, we select this method.
Next is std::getline. This will read a complete line from the input stream, so, from the console (std::cin)and put it into the string. The std::getline returns a reference to the stream. The stream has an overloaded bool operator, that returns, if there was a failure (or end of file) or not. So, the if statement checks, if the input operation works. By the way. All IO-opereations should be checked, if they work or fail.
Good, now we have the complete line of the user input in our variable "line".
With
std::istringstream iss{line};
we put the string into an std::istringstream. We do this, because we want to make use of the C++ "iostream" library. The std::istringstream behaves as any other stream, for example std::cin and you can extract values from it that are separated by a white space. Like in std::cin >> v1 >> v2. The disadvantage for such an approach is, that you need to know the number of values in advance or use a dynamic growing container and a loop.
And this brings ud to our next construct that I want to explain. You may have heard about "iterators". Iterators are like pointers and can point to a range of elements. If you have a std::vector or any other container, then you can iterate with the begin() and end() iterator over all elements in the std::vector without knowing, how many elements are in the std::vector, without knowing how many elements it contains.
And for input streams, we have something similar: The std::istream_iterator. This iterator will iterate over the elements in the std::sitringstream and returns the type of variable given in its template parameter, by repeatedly calling the extractor operator >>. Here, in our case, a std::string. You may know ask: Until when? Where is the end. If you look in the description of the constructor number 1 of the std::istream_operator then you will see, that the default constructor Constructs the end-of-stream iterator. and the default construct can be generated by using the empty braced {} initializer. So {} is the end iterator.
If we want to read all std::strings from the std::istringstream, then we read between
std::istream_iterator<std::string>(iss) and {}. So every string that is in the std::istringstream.
Good, next, there is a similar thing for output, the std::ostream_iterator. This will call the inserter operator "<<" for all elements in a given range. And, we can can specify, to which stream it should send the data, here std::cout and additionally a separator-string, which will be appended to the outputted value.
OK, next: std::transform. As it names says, it will transform the elements in a range of elements, between a begin() and end() iterator, to a other range. So, it will transform the elements as shown above from the std::istringstream and send them to the std::ostream iterator. So, we read the source value, transform it, then write it.
But, how to transform. For the transformation, we give a simple lambda function, which calls the std::regex_replace function. This is a standard function, to replace parts of a string with other string data. And, the what that will be replaced is specified by a std::regex. This is a special pattern that is defined in some kind of meta language and matches specified parts of a string. in our case we use [^\d] which means, not a digit. You can test regexes here. You can also lean about them here.
And now, all together, explains the above solution.
All this can be further optimized to 2 statements:
#include <iostream>
#include <string>
#include <regex>
int main() {
// Read a string from the console
if (std::string line{}; std::getline(std::cin, line)) {
// Remove unnecessary characters
std::cout << std::regex_replace(line, std::regex{ R"([^\d ])" }, "") << "\n";
}
return 0;
}
I cannot think of a more simpler solution.
In case of questions, please ask.
You can use get from istream to get each character, including whitespace, and then isdigit to check for a digit character...
#include <iostream>
#include <cctype>
int main()
{
char ch;
std::cin.get(ch);
while (!std::cin.eof())
{
if (isdigit(ch) || ch == ' ' || ch == '\n')
{
std::cout << ch;
}
std::cin.get(ch);
}
return 0;
}
However, you can avoid using std::cin.eof() for your expression for your While loop as follows...
#include <iostream>
#include <cctype>
int main()
{
char ch;
while (std::cin.get(ch))
{
if (isdigit(ch) || ch == ' ' || ch == '\n')
{
std::cout << ch;
}
}
return 0;
}
Regular expression pattern matching can be used to find all the digits in the input string.
Here is an example program to find the digits:
// C++ program to find all digits in a string
#include <bits/stdc++.h>
using namespace std;
int main() {
string inputString;
cout << "Enter the input string: ";
getline(cin, inputString);
cout << "Digits found: ";
// Define the regular expression matcher and pattern
smatch matcher;
regex pattern("[[:digit:]]");
while (regex_search(inputString, matcher, pattern)) {
// Show the match
cout << matcher.str(0);
// Continue searching the rest of the string
inputString = matcher.suffix().str();
}
return 0;
}
Output:
Enter the input string: sdfh354 eutyt;ljkn756897490uiotureu 587689jkgf 90
Digits found: 35475689749058768990
Here is another approach of finding the numbers in the string, without using the regular expression pattern matching:
#include <iostream>
#include <cctype>
#include <bits/stdc++.h>
using namespace std;
int main() {
string rawInput;
cout <<"Enter input string: ";
getline(cin, rawInput);
// Get all words from the input string
stringstream allWords(rawInput);
// Find and print digits in each word
string word;
while(allWords >> word) {
for(int i = 0; word[i]; i++) {
// Print only the numbers in the word
if(isdigit(word[i])) {
cout<<word[i];
}
}
cout<<" ";
}
cout<<"\n";
return 0;
}
Output:
Enter input string: ghjg45 jsdfj 897897 343yut45 90
45 897897 34345 90
How can I extract all numbers?
When you KNOW that the input numbers are all hex values ... (and how many)
stringstream ss ("5a3 1f a0aaaa f1fg3");
for (int i=0; i<4; ++i)
{
int k;
ss >> hex >> k;
cout << k << endl;
}
with output
1443
31
10529450
3871

How to use cin with unknown input types?

I have a C++ program which needs to take user input. The user input will either be two ints (for example: 1 3) or it will be a char (for example: s).
I know I can get the twos ints like this:
cin >> x >> y;
But how do I go about getting the value of the cin if a char is input instead? I know cin.fail() will be called but when I call cin.get(), it does not retrieve the character that was input.
Thanks for the help!
Use std::getline to read the input into a string, then use std::istringstream to parse the values out.
You can do this in c++11. This solution is robust, will ignore spaces.
This is compiled with clang++-libc++ in ubuntu 13.10. Note that gcc doesn't have a full regex implementation yet, but you could use Boost.Regex as an alternative.
EDIT: Added negative numbers handling.
#include <regex>
#include <iostream>
#include <string>
#include <utility>
using namespace std;
int main() {
regex pattern(R"(\s*(-?\d+)\s+(-?\d+)\s*|\s*([[:alpha:]])\s*)");
string input;
smatch match;
char a_char;
pair<int, int> two_ints;
while (getline(cin, input)) {
if (regex_match(input, match, pattern)) {
if (match[3].matched) {
cout << match[3] << endl;
a_char = match[3].str()[0];
}
else {
cout << match[1] << " " << match[2] << endl;
two_ints = {stoi(match[1]), stoi(match[2])};
}
}
}
}

Restrict user to input real number only in C++

How can I restrict the user to input real numbers only in C++ program?
Example:
double number;
cin >> number;
and it won't accept the input like: '12add' , 'abcd' etc...
can someone guides me to that? using bool value.
Thanks!
You cannot force the user to give correct input. But you can ask them to give another input if previous was invalid. There are different procedures to do so. One is the following:
Use getline to read a line
Parse and understand the line
If line is invalid, give error to user and go to 1
This is alright and quite common. It uses dynamic memory though. Another option would be:
Use cin >> value; like you normally do
Check cin.fail() to see if input was correctly read (check for cin.eof() also)
If failed, ignore all input until whitespace:
char c;
while (cin >> c)
if (isspace(c))
break;
This has the added advantage that in an erroneous input like this:
abc 12.14
you don't ignore the whole line, but just the abc.
I always use this code to request a specific type of input(Except strings and chars).
The idea is to request any numeric type and use stringstream to see if it can be stored as the requested type, if not it will keep prompting the user until he inputs the requested type.
template <typename T> // will not work with strings or chars
T forceInputType_T() {
T name;
bool check = false;
string temp;
while (check == false) {
cin >> temp;
stringstream stream(temp);
if (stream >> number) {
check = true;
} else {
cout << "Invalid input type, try again..." << endl;
}
}
return name;
}
If you want to use a Boolean then you could check every character in the string if it contains a number than return false and keep asking for an valid input with a loop !
You cannot restrict what user types on the keyboard. You can accept it as std::string and use boost::lexical_cast to convert it to your expected number type and catch and process boost::bad_lexical_cast exception.
You can retrieve your data as a std::string then use one of the standard string conversion function to see if the content matches your expectations.
double number
if (cin >> number) {
do_stuff_with(number);
} else {
std::cerr << "That wasn't a number!";
}
Check out the sscanf function.
Unfortunately you cannot avoid it... You can accept a string as input and parse the string (maybe with regex) for correctness.
You can use regex to solve it
double inputNumber()
{
string str;
regex regex_double("-?[0-9]+.?[0-9]+");
do
{
cout << "Input a positive number: ";
cin >> str;
}while(!regex_match(str,regex_double));
return stod(str);
}
Remember that include regex library in the header.
Use this:
#include <conio.h>
#include <string>
#include <iostream>
using namespace std;
int main() {
cout << "Input a positive whole integer: ";
string currentInput;
while (true) {
char ch = getch();
if (ch <= '9' and ch >= '0') cout << ch; currentInput += ch;
// Handle other keys (like backspace, etc)
else if (ch == '\r') cout << endl; break;
}
}

Reverse String Error?

I am creating this revese string App but i get a error if i include a space in the string !
#include <iostream>
#include <string>
using namespace std;
int main()
{
int inputa;
cout<<"%%%%%%%%%%%%%%%%%%String Reversing App%%%%%%%%%%%%%%%%%%%%%%%%"<<endl<<endl;
cout<<"\nEnter 1 to continue and 0 to exit"<<endl<<endl;
cin>>inputa;
if(inputa!=0)
{
do
{
string a,c="";
cout<<"\nEnter the string you want to Reverse : ";
cin>>a;
for(int x=a.length()-1; x>=0; x--)
{
c=c+a.substr(x,1);
}
cout<<"\nThe Reverse String is : "<<c<<endl;
cout<<"\nEnter 1 to continue and 0 to exit"<<endl<<endl;
cin>>inputa;
}
while(inputa!=0);
}
//not my home work
}
If I type the following string like "abc def" there i get an error . But otherwise it works perfectly ! Is there some mistake with the codes ! I am new to CPP so it would be helpful if you could help me !
operator>> will stop reading at the first space (as David pointed out) - use getline instead
std::string a;
getline(std::cin, a);
Full edit of your code
#include <iostream>
#include <string>
#include <limits>
int main()
{
std::cout << "%%%%%%%%%%%%%%%%%%String Reversing App%%%%%%%%%%%%%%%%%%%%%%%%\n\n";
std::cout << "\nEnter 1 to continue and 0 to exit" << std::endl;
int inputa;
std::cin >> inputa;
if(std::cin && inputa!=0)
{
std::cin.ignore(std::numeric_limits<int>::max( ), '\n');
do
{
std::string a,c;
std::cout<<"\nEnter the string you want to Reverse : ";
getline(std::cin, a);
for(int x=a.length()-1; x>=0; --x)
{
c+=a[x];
}
std::cout<<"\nThe Reverse String is : " << c << std::endl;
std::cout << "\nEnter 1 to continue and 0 to exit" << std::endl << std::endl;
std::cin >> inputa;
std::cin.ignore(std::numeric_limits<int>::max( ), '\n');
}
while(std::cin && inputa!=0);
}
}
Including David's verbatim answer because he answered with much more detail (David Rodríguez - dribeas) - please +1 him before he deletes it. His answer adds much more information that I did not mention so we are merging this into a single reply at Davids request,
The answer by Adrian is correct, deals with the immediate issue and provides a solution. As to why it enters an infinite loop, the reason is that after reading the first word, you are trying to read an integer std::cin >> inputa, which will fail as cde cannot be parsed as an integer. At this point the stream enters a fail state and subsequent reads will fail without doing anything (until you clear the error state).
What should you do?
If you want to process whole lines, then you should use std::getline, rather than operator>>. Beware on mixing both, as operator>> won't consume the spaces after the read (including new lines) and you might just read an empty line with the next std::getline. You can either always read with std::getline and then parse the line, or use ignore to clear up to the newline. Finally, whenever you perform IO operations, don't expect the operation to succeed: check the state of the stream. If you don't and your loop depends on IO to complete, it is quite easy to enter this sort of infinite loop, where the stream is marked as failed, no later reads succeed and you never break out of the loop.