Use of cin and getline for strings - c++

I was recently doing a problem in C++:
Write a program to work out if a series of 5 digits are consecutive
numbers. To make this easier, assumes the digits are a string:
string numbers = "10-9-8-7-6";
Make sure your code works for the following sequence, as well:
string numbers = "1-2-3-4-5";
I solved it, however I saw when I used cin for the string the console window threw some exception & didn't execute the program but on replacing it with getline, it worked perfectly.
Could anyone explain me the reason behind it because logically both should work properly.
The program is:
#include<iostream>
#include<string>
using namespace std;
void change(int x, int y, int &inc, int &dec)
{
if (x - y == 1)
++dec;
else if (y - x == 1)
++inc;
}
int main()
{
string s = "", snum = "";
cout << "enter 5 nos and use \'-\' to separate them: ";
cin >> s;
int i = 0, x = 0, y = 0, inc = 0, dec = 0;
for (char &ch : s)
{
if (ch == '-')
{
++i;
if (i == 1)
{
y = stoi(snum);
cout << y << endl;
}
else
{
x = y;
y = stoi(snum);
cout << x << " " << y << endl;
change(x, y, inc, dec);
}
snum = "";
}
else
snum += ch;
}
x = y;
y = stoi(snum);
cout << x << " " << y << endl;
change(x, y, inc, dec);
if (inc == 4 || dec == 4)
cout << "ORDERED";
else
cout << "UNORDERED";
return 0;
}

If you have to enter everything at the same time such as:
10 9 8 7 6
All on one line then cin does not record all that at the same time.
Concerning cin it only takes the characters before a space (" ") for example. Getline however takes that entire line and uses it. Another way to do the same thing would be to use the cstdio library and have it set up with either using printf or puts to prompt, and then use gets to gather all the information from the puts prompt. This is what I assume why it works.
Example:
cstdio library
char string[50];
printf("Enter a string of text");
gets(string);
cout << string << endl;
*EDIT
After the comment below I realized what you are asking, and if you are assuming the numbers are strings, and they are separated with hyphens and no spaces then it should work fine. It shouldn't be the problem of cin by maybe something else?
If there are spaces involved in your code then what I wrote above EDIT will be a simple solution to THAT problem.

If you need to get a formatted string, I recommend you scanf like this:
if( 5 == scanf("%d-%d-%d-%d-%d", &a, &b, &c, &d, &e) )
//welldone
// work with above 5 int easily :)
else
// Please enter again
This way you don't have to work with string at all and life would be easier.
You can easily check if these 5 are consecutive or not .
If you need not a new solution and want to get your code fixed, tell me in comment.

Related

Using GETS and CIN together

trying to take 2 different space separated number input as a string, concatenate them and print final string. somehow the input always messes up...
#define SORT(a) sort(a.begin(),a.end())
using namespace std;
int main()
{
int level, count = 0;
cin >> level;
string lx, ly, f;
getline(cin, lx);
getline(cin, ly);
f = lx + " " + ly;
SORT(f);
int size = f.size();
cout << f << endl << size << endl << level << endl;
return 0;
}
Why are you sorting them if all you want to do is combine them and print them?
Your initial code without the SORT() works perfectly.
I am not sure since I never use it, but I believe sort will sort all characters in the string alphabetically, so dfg acb will become abcdfg

C++ Recursion function

Good afternoon everyone, I am new to recursion and am trying to create a program to take user input to build a math function. It works when doing simple things such as 3 + 4, but when trying something like (3 + 4) + 6 the main prints an empty string. The purpose of the program is to place nested numbers inside parenthesis to make them clear to read. I have tried following the code, but the recursion seems to be what i don't understand. Thanks for your time and help.
Code
#include <iostream>
#include <string>
using namespace std;
string buildEq(bool nested, string tab);
int main()
{
cout << "Welcome to the equation builder!" << endl << endl;
cout << "Each step can only have one operation between two numbers." << endl;
cout << "So the equation (3 + 4) + 6 would have one 'nested' operation." << endl << endl;
string equation = buildEq(false, "");
cout << endl << "The equation you have built is... " << equation << endl;
cout << endl << "Thanks for coming!" << endl;
return 0;
}
string buildEq(bool nested, string tab)
{
string equation;
string nesting;
cout << tab << "For this step, is there nesting? (y/n): ";
cin >> nesting;
if(nesting == "y")
{
nested = true;
tab += "\t";
buildEq(true, tab);
}
else
{
int number = 0;
int operation_count = 1;
while(number < 2)
{
if(nested == true)
{
equation += "(";
}
string num= "";
cout << tab << "What number would you like to enter: ";
cin >> num;
equation += num+= " ";
number++;
while(operation_count == 1)
{
string operation;
cout << tab << "What operation would you like to perform? (+, -, /, *): ";
cin >> operation;
equation += operation += " ";
operation_count++;
}
if(nested == true && number == 2)
{
equation += ")";
}
}
}
return equation;
}
Correct output
Welcome to the equation builder!
Each step can only have one operation between two numbers.
So the equation (3 + 4) + 6 would have one 'nested' operation.
For this step, is there nesting? (y/n): n
What number would you like to enter: 3
What operation would you like to perform? (+, -, /, *): +
What number would you like to enter: 4
The equation you have built is... 3 + 4
Thanks for coming!
Press <RETURN> to close this window...
Function results empty
Welcome to the equation builder!
Each step can only have one operation between two numbers.
So the equation (3 + 4) + 6 would have one 'nested' operation.
For this step, is there nesting? (y/n): y
For this step, is there nesting? (y/n): n
What number would you like to enter: 3
What operation would you like to perform? (+, -, /, *): +
What number would you like to enter: 4
The equation you have built is...
Thanks for coming!
Press <RETURN> to close this window...
(Probably an overkill, but I don't think that the question itself is an easy example for understanding recursions)
In order to understand the recursion part, we need to look at the general problem, and understand how we progress from one invocation to another (the recursive step), and what is our stopping point (the base case) . Your goal here is to create a valid equation, in order to do so, your input should follow certain guidelines. Specifically, in order to verify such a problem, you need to verify that each input is following a syntax which is called Context Free Grammar, denoted by the following rules (N stands for number or nested, O for operation, D for digit and $ for nothing):
N -> ( N ) O | D O
D -> 0-9
O -> + N | - N | * N | / N | $
There are two recursions here. In each stage we need to get a valid equation, and those rules make sure it stays like that.
The following code is creating a proper equation from the user.
Notice a few important notes -
I'm using std::stringstream, which is more efficient at creating strings and appending to the existing "string".
You should not over-use std::endl, since in addition to adding a line break, it also flushes to the stdout, which is expensive.
Using "Using namespace std;" isn't a good habit!
Look at how I pass the same stringstream, and each stage adds to this, in order to create the general string. If your code doesn't add to the "carried" value, it means that you are doing nothing in this recursive step.
The code:
#include <sstream>
#include <iostream>
#include <string>
#include <cctype>
#include <assert.h>
void get_num_or_nested(std::stringstream& eq);
void get_operation_or_stop(std::stringstream& eq);
bool is_number(const std::string& s)
{
int digit_count = 0;
for (const char& character : s)
{
if (std::isdigit(character))
{
++digit_count;
}
}
return !s.empty() && s.size() == digit_count;
}
bool is_operation(char c)
{
return (c == '+' || c == '-' || c == '*' || c == '/');
}
std::string get_input_from_user()
{
std::string input;
std::cin >> input;
return input;
}
void get_operation_or_stop(std::stringstream& eq)
{
std::cout << "Insert one of the following:\n";
std::cout << "An operation - [ + | - | * | / ]\n";
std::cout << "s for Stop" << std::endl;
std::string input = get_input_from_user();
if (input.size() == 1)
{
if (is_operation(input[0]))
{
eq << input;
get_num_or_nested(eq);
}
else if (input != "s")
{
assert(false);
}
// stops!
}
else
{
assert(false);
}
}
void get_num_or_nested(std::stringstream& eq)
{
std::cout << "Insert one of the following:\n";
std::cout << "A number\n";
std::cout << "n for Nested" << std::endl;
std::string input = get_input_from_user();
if (input == "n")
{
eq << "(";
get_num_or_nested(eq);
eq << ")";
get_operation_or_stop(eq);
}
else if (is_number(input))
{
eq << input;
get_operation_or_stop(eq);
}
else
{
assert(false);
}
}
int main()
{
std::cout << "Welcome to the equation builder!\n" << std::endl;
std::stringstream eq;
get_num_or_nested(eq);
std::cout << "The equation you have built is... " << eq.str() << std::endl;
std::cout << "Thanks for coming!" << std::endl;
}
The only thing that is wrong is when the user says yes to nesting. Instead of calling the function and discarding what it returned, you need to return what the function returned.
if(nesting == "y")
{
nested = true;
tab += "\t";
return buildEq(true, tab);
}

How to count how many times a specific letter appears in a string? (C++)

I've been struggling with a homework assignment that counts the amount of instances a uppercase letters, lowercase letters, and numbers in a string. appears in a string.
I'm using a one-dimensional array with a constant size of 132 to store the entered string, and I need to use two functions. One needs to count the amount of letter occurrences in the string and the other function will execute the output something similar to above. I'm struggling most with the letter counting aspect of the program itself.
Currently, this is what my current homework resembles for the most part. It's a work in progress (of course) so errors in the code are very likely.
void LetterCount(char c_input[], int l_count)
{
// code to count letters
}
void CountOut(//not sure what should go here yet until counting gets figured out)
{
// code that handles output
}
int main()
{
const int SIZE = 132;
char CharInput[SIZE];
int LetterCount = 0;
cout << "Enter a string of up to 132 characters in size: ";
cin.getline(CharInput, SIZE);
cout << "You entered: " << CharInput << endl;
Count(CharInput);
CountOut(//not sure what goes here yet);
return 0;
}
The output would look something like:
a - 2
b - 1
c - 1
d - 0
e - 1
etc...
I've tried some experimentation with for loops to count the letters and have seen some examples of the function gcount(), but I haven't gotten anything to work. Does anyone have a suggestion as to how I would count the letters in an inputted string?
map is a very efficient data structure here
#include <iostream>
#include <map>
using namespace std;
int main(){
string str = "a boy caught 2 fireflies";
map<char, int> str_map;
for(auto x : str) ++str_map[x];
for(auto x : str_map) cout << x.first << ' ' << x.second << '\n';
}
What you want is to build a simple histogram, and it's pretty easy to do. Since what you're looking at is chars, and there can be 256 possible values of an 8-bit char (in practice your input string probably uses less, but we'll be conservative here because memory is cheap), you'll want to start with an array of 256 ints, all of them initialized to zero. Then iterate over the chars your string, and for each char in your string, use that char-value as an offset into the array(*), and simply increment that item in the array.
When you're done, all that remains is to iterate over the ints in the array and print out the ones that are non-zero, and you're done.
(*) you may want to cast the char to unsigned char before using it as an offset into the array, just to avoid any chance of it being interpreted as a negative array-index, which would result in undefined behavior (this is only an issue if your input string contains ASCII characters 128 and higher, so it may not matter in your case, but it's always good form to make code that does the right thing in all cases if you can)
As Jeremy frisner said you're building a histogram, but I disagree with the types used.
You'll want to declare your histogram like so:
size_t histogram[sizeof(char)*CHAR_BIT] = {0};
The size_t because you might overflow without it, and you need enough space if it's a nonstandard byte size.
As for printing it out. You should take a look at an ASCII table and examine which values you need to print out.
You could do it by comparing c-strings with other c-strings. But with chars and strings you can get errors like: "const *char cant be compared with strings". So you'll have to compare each c string(array) index with other c string indexes. In this program I use if statements to look for certain vowels. The way it works is that each "string alphabet_letter" is equal to it's respective lowercase and capital letters (for comparison). this is a very redundant way to do it and, if you want to count all total letters, perhaps you should try a different way, but this method doesn't use very complicated methods that require deeper understanding.
using namespace std;
int main(){
int vowel;
string A = "aA";
string E = "eE";
string I = "iI";
string O = "oO";
string U = "uU";
string str;
string str1;
bool userLength = true;
int restart = 0;
do{
cout << "Enter a string." <<endl;
getline(cin, str);
int VowelA = 0;
int VowelE = 0;
int VowelI = 0;
int VowelO = 0;
int VowelU = 0;
for(int x = 0; x < 100; x++){
if(restart == 1){
restart = 0;
x = 0;
}
if(A[0] == str[x]){
VowelA = VowelA + 1;
}
if(E[0] == str[x]){
VowelE = VowelE + 1;
}
if(I[0] == str[x]){
VowelI = VowelI + 1;
}
if(O[0] == str[x]){
VowelO = VowelO + 1;
}
if(U[0] == str[x]){
VowelU = VowelU + 1;
}
if(A[1] == str[x]){
VowelA = VowelA + 1;
}
if(E[1] == str[x]){
VowelE = VowelE + 1;
}
if(I[1] == str[x]){
VowelI = VowelI + 1;
}
if(O[1] == str[x]){
VowelO = VowelO + 1;
}
if(U[1] == str[x]){
VowelU = VowelU + 1;
}
int strL = str.length();
if(x == strL){
cout << "The original string is: " << str << endl;
cout << "Vowel A: "<< VowelA << endl;
cout << "Vowel E: "<< VowelE << endl;
cout << "Vowel I: "<< VowelI << endl;
cout << "Vowel O: "<< VowelO << endl;
cout << "Vowel U: "<< VowelU << endl;
cout << " " << endl;
}
}
char choice;
cout << "Again? " << endl;
cin >> choice;
if(choice == 'n' || choice == 'N'){userLength = false;}
if(choice == 'y' || choice =='Y')
{
restart = 1; userLength = true;
cin.clear();
cin.ignore();
}
//cout << "What string?";
//cin.get(str, sizeof(str),'\n');
}while(userLength == true);
}
/*
Sources:
printf help
http://www.cplusplus.com/reference/cstdio/printf/
This helped me with the idea of what's a vowel and whats not.
http://www.cplusplus.com/forum/general/71805/
understanding gets()
https://www.programiz.com/cpp-programming/library-function/cstdio/gets
Very important functional part of my program...Logic behind my if statements, fixed my issues with string comparison
What i needed to do was compare each part of one cstring with another c string
strstr compares two strings to see if they are alike to one another this source includes that idea-> https://www.youtube.com/watch?v=hGrKX0edRFg
so I got the idea: What is one c string was all e's, I could then compare each index for similarities with a c string whos definition was all e's.
At this point, why not just go back to standard comparison with strings? But you cant compare const chars to regular chars, so I needed to compare const chars to const chars
hence the idea sparked about the c strings that contained both e and E.
https://stackoverflow.com/questions/18794793/c-comparing-the-index-of-a-string-to-another-string
https://stackoverflow.com/questions/18794793/c-comparing-the-index-of-a-string-to-another-string
Fixed Error with using incremented numbers outside of involved forloop.
https://stackoverflow.com/questions/24117264/error-name-lookup-of-i-changed-for-iso-for-scoping-fpermissive
understanding the use of getline(cin, str_name)
https://stackoverflow.com/questions/5882872/reading-a-full-line-of-input
http://www.cplusplus.com/reference/istream/istream/getline/
http://www.cplusplus.com/forum/beginner/45169/
cin.clear - cin.ignore --fixing issue with cin buffer not accepting new input.
https://stackoverflow.com/questions/46204672/getlinecin-string-not-giving-expected-output
*/

While loop terminates after one iteration

I am trying to write a function in C++ to evaluate a postfix notation equation. My general strategy is to scan a string (in the proper format, e.g. "10 20 + 30 -").
I am doing this by incrementing an index variable i. At each increment, I check to see if the character is a digit, operator, or neither. If it's a digit, I use the getNextNum() function to get all following digits, convert that to a float, then push it to a stack. I also increment i by the length of the number captured.
If the character is an operator, I get the top two elements of the stack, do the operation, then push the result back to the stack.
The trouble is, my while loop only seems to go through once. The function only returns the first number in the string. I can't figure out what's wrong, I would appreciate any help! I inserted cout statements in the while loop, and i is only incrementing to the index after the first number.
EDIT: Ok, I added the getNextNum() function. Also, I updated the evalPostfix() with a cout of strLength, as well as i after each iteration of the while loop. When running the given code, I get this:
Running…
Please enter an expression in postfix notation: 555 666+
3
555
3
Your expression evaluates to: 555
It seems like strLength is being set to less than it should. Why could this be?
#include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <stack>
using namespace std;
string getNextNum(string equation, int i);
float evalPostfix(string postfix);
float doOperation(float x, float y, char op);
float doOperation(float x, float y, char op)
{
switch (op) {
case '+':
return x + y;
case '-':
return x - y;
case '*':
return x * y;
case '/':
return x / y;
default:
return 0.0;
}
}
string getNextNum(string equation, int i)
{
string num = "";
const string DELIM = "+-*/%^ ";
while (i<equation.length()) {
// Iterate through equation until you hit a delimiter.
if (DELIM.find(equation[i]) != -1) {
break;
}
num += equation[i];
i++;
}
return num;
}
float evalPostfix(string postfix)
{
const string OPS = "+-*/%^";
const string NUMS = "0123456789";
int strLength = postfix.length();
stack<float> numStack;
int i = 0;
cout << strLength << endl;
while (i<strLength) {
if (NUMS.find(postfix[i]) != -1) {
// If a character is a digit, then you should get the
// value and push it to the stack (could be multiple characters long).
string sNextNum = getNextNum(postfix, i);
float fNextNum = atof(sNextNum.c_str());
numStack.push(fNextNum);
cout << sNextNum << endl;
i += (sNextNum.length() - 1);
}
else if (OPS.find(postfix[i] != -1)) {
// Otherwise, pop the top two elements of the stack, perform the
// operation, then push the result back to the stack.
char op = postfix[i];
float x = numStack.top();
numStack.pop();
float y = numStack.top();
numStack.pop();
float z = doOperation(x, y, op);
numStack.push(z);
}
i++;
cout << i << endl;
};
// Once the entire string has been scanned through, there should be a float
// left in the stack, simply return that.
return numStack.top();
}
int main ()
{
cout << "Please enter an expression in postfix notation: ";
string postfix;
cin >> postfix;
float eval = evalPostfix(postfix);
cout << "Your expression evaluates to: " << eval;
return 0;
}
You have a few issues one of the major one being a typo, you have a misplaced ) this:
else if (OPS.find( postfix[i] != -1 ) ) {
^ ^
should be:
else if (OPS.find( postfix[i] ) != std::string::npos) {
^ ^
so you are comparing the char at position i to -1 and then doing a find on the boolean result. Next you should be using -1 to compare the results of find but std::string::npos
As Jonathan pointed out:
cin >> postfix ;
only read up to the first black or newline. Using getline will fix that problem:
if (getline(cin, postfix))
One primary problem was that the input cin >> postfix; statement only reads the first word. Echo inputs to ensure that the program is seeing what you think it is seeing.
Shafik Yaghmour points out another problem.
Points to learn:
echo inputs to make sure the program is seeing what you think it is seeing;
trace key variables with suitable printing messages;
post SSCCE (Short, Self-Contained, Correct Example) — code that can be compiled;
post example input and the output you're getting from it.
This code works on input 555 666+:
#include <iostream>
#include <string>
#include <stack>
using namespace std;
static float doOperation(float x, float y, char op)
{
cout << "doOp: x = " << x << ", y = " << y << ", op = " << op << endl;
if (op == '+')
x += y;
return x;
}
string getNextNum(string equation, int i)
{
string num = "";
const string DELIM = "+-*/%^ ";
while (i<equation.length()) {
// Iterate through equation until you hit a delimiter.
if (DELIM.find(equation[i]) != -1) {
break;
}
num += equation[i];
i++;
}
return num;
}
float evalPostfix(string postfix)
{
const string OPS = "+-*/%^";
const string NUMS = "0123456789";
int strLength = postfix.length();
stack<float> numStack;
int i = 0;
while (i<strLength) {
cout << "Top - i: " << i << ", strLength: " << strLength << endl;
if (NUMS.find(postfix[i]) != -1) {
// If a character is a digit, then you should get the
// value and push it to the stack (could be multiple characters long).
string sNextNum = getNextNum(postfix, i);
float fNextNum = atof(sNextNum.c_str());
numStack.push(fNextNum);
cout << sNextNum << endl;
i += (sNextNum.length() - 1);
}
else if (OPS.find(postfix[i])!= -1) {
// Otherwise, pop the top two elements of the stack, perform the
// operation, then push the result back to the stack.
char op = postfix[i];
float x = numStack.top();
numStack.pop();
float y = numStack.top();
numStack.pop();
float z = doOperation(x, y, op);
numStack.push(z);
}
i++;
cout << "End - i: " << i << ", strLength: " << strLength << endl;
}
cout << "After - i: " << i << ", strLength: " << strLength << endl;
// Once the entire string has been scanned through, there should be a float
// left in the stack, simply return that.
return numStack.top();
}
int main ()
{
cout << "Please enter an expression in postfix notation: ";
string postfix;
//cin >> postfix;
if (getline(cin, postfix))
{
cout << "Evaluating: " << postfix << endl;
float eval = evalPostfix(postfix);
cout << "Your expression evaluates to: " << eval << endl;
}
return 0;
}
Sample trace:
Please enter an expression in postfix notation: 555 666+
Evaluating: 555 666+
Top - i: 0, strLength: 8
555
End - i: 3, strLength: 8
Top - i: 3, strLength: 8
End - i: 4, strLength: 8
Top - i: 4, strLength: 8
666
End - i: 7, strLength: 8
Top - i: 7, strLength: 8
doOp: x = 666, y = 555, op = +
End - i: 8, strLength: 8
After - i: 8, strLength: 8
Your expression evaluates to: 1221
Clearly, you can lose much of the diagnostic output once the specific problem you are solving is resolved, but being prepared to add it along the lines shown can dramatically speed up the process of solving it.

C++ How to check an input float variable for valid input

I'm writing a program that acts as a calculator; based on the character input by the user it performs a certain operation. The structure of the program seems to work fine, but I'd like to be able to check for erroneous input. After receiving the float variable, is there any way to check if it does not contain any characters other than digits and decimals? I've tried isdigit, and this:
if (!(cin >> x)) {
cout << "You did not enter a correct number!" << endl;
return;
}
But nothing seems to be working.
Here is a sample of one of the simple operation functions I'm using:
void Add(){
float x = 0, y = 0, z = 0;
cout << "Please enter two numbers you wish "
<< "to add separated by a white space:" << endl;
cin >> x >> y;
z = x+y;
cout << x << " + " << y << " = " << z << "." << endl;
return;
}
You test the state of the stream:
float x, y;
if (std::cin >> x >> y) {
// input extraction succeeded
}
else {
// input extraction failed
}
If this isn't working for you, then you need to post the exact code that isn't working.
To detect erroneous string input where you expected a number, C++ doesn't automatically know what you want, so one solution is to first accept your input as strings, validate those strings, then if valid, only then convert the strings to float numbers using the atof() function.
The standard string class has a function called find_first_not_of() to help you tell C++ which characters you consider valid. If the function finds a character not in your list, it will return the position of the bad character, otherwise string::npos is returned.
// add.cpp
#include <iostream>
#include <string>
#include <cstdlib> // for atof()
using namespace std;
void Add()
{
cout << "Please enter two numbers you wish "
<< "to add, separated by a white space:"
<< endl;
string num1, num2;
cin >> num1;
if( num1.find_first_not_of("1234567890.-") != string::npos )
{
cout << "invalid number: " << num1 << endl;
return;
}
cin >> num2;
if( num2.find_first_not_of("1234567890.-") != string::npos )
{
cout << "invalid number: " << num2 << endl;
return;
}
float x = 0, y = 0, z = 0;
x = atof( num1.c_str() );
y = atof( num2.c_str() );
z = x+y;
cout << x << " + " << y << " = " << z << "." << endl;
}
int main(void)
{
Add();
return 0;
}
One possibility would be to read the input as a string, then use boost lexical_cast to convert to floating point. lexical_cast only considers the conversion successful if the entire input converts to the target -- otherwise, it'll throw a bad_lexical_cast exception.
Another idea would be to test the input against a regex. An example regex for a float could be
-?[0-9]+([.][0-9]+)?
This method would also make it easier to refine the matching mechanism by only modifying the regex, and you could map multiple regular expressions against different types of input, for example an integer could then be expressed as
-?[0-9]+
and so on. Keep in mind however, that this only tests if the input is a valid format, it still requires a numerical conversion afterwards (I prefer boost::lexical_cast).
(You can also try it out with http://gskinner.com/RegExr/)