alternate input issue

Hello everyone,

I am very new to coding and am making my through a C++ textbook. I am not a student, I am self-teaching to gain employment in the future.

I am trying to write a C++ program that is a simple calculator that accepts either integers or strings (eg. four) to divide, multiply, subtract or add.

The problem is that during the IF statement, it doesn't seem to respond to integers the way I input them. eg. if I input: 4 5 * (4 multiply 5) it outputs: 0 multiply 0 = 0;

The string to integer to function works correctly eg. four five * (4 multiply 5 = 20).

It's really bugging me and I was hoping someone could have a look and tell me why my integers are not being recognized as I input them.

Thanks heaps in advance :)

Regards,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
  #include "\Users\User\Desktop\C++\std_lib_facilities.h"

vector<string> numbersspoken = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
vector<int> numbers = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};



int wordtodigit(string word){
    for (int i = 0; i < numbersspoken.size(); ++i){
        if (numbersspoken[i] == word){
            return i;
            
            
        }
        
    }
}

int recognizeint (int number){
    for (int i = 0; i < numbers.size(); ++i){
        if (numbers[i] == number){
            return i;
            
        }
    }
}

int main(){
int ab, bb = 0;
int a, b = 0;
char symbol1 = ' ';
string spokenstring1;
string spokenstring2;


cout<<"Let's do some simple calculations with numbers (0-9) or words (zero-nine)\n"

<<"Input either two single digit numbers (eg.4(space)5) or the words of two single digit numbers (eg.four(space)five) followed by an operator:\n"
<<"* (multiply)\t+ (addition)\t/ (division)\t- (subtract)\n"
<<"eg.4 5 * (4 multiplied by 5) OR four five * (4 multiplied by 5)\n";


    while (cin){

if (cin>>spokenstring1>>spokenstring2>>symbol1){

    a = wordtodigit(spokenstring1);
    b = wordtodigit(spokenstring2);
   

}

else if (cin>>ab>>bb>>symbol1) {
 
    
   
    a = recognizeint(ab);
    b = recognizeint(bb);
   
}

else {
    cout<<"Please re-read the instructions.\n";
}

    switch (symbol1){

    case '*' :

    cout<<"The product of "<<a<<" multiplied by "<<b<<" equals "<<a*b<<".\n";
    break;

    case '+' :
    cout<<"The sum of "<<a<<" and "<<b<<" equals "<<a+b<<".\n";
    break;
    case '/' :
    cout<<a<<" divided by "<<b<<" equals "<<a/b<<".\n";
    break;
    case '-' :
    cout<<a<<" minus "<<b<<" equals "<<a-b<<".\n";
    break;
    default:
    cout<<a<<symbol1<<b<<"? Please re-read the instructions.\n";
    break;
}


}

}
Last edited on
Either use a debugger, or add some debugging prints, when you're confused by the program flow.
1
2
3
4
5
6
7
8
9
10
if (cin>>spokenstring1>>spokenstring2>>symbol1){
    cout << "Debug: reading as strings\n";
    a = wordtodigit(spokenstring1);
    b = wordtodigit(spokenstring2);
}
else if (cin>>ab>>bb>>symbol1) {
    cout << "Debug: reading as ints\n";
    a = recognizeint(ab);
    b = recognizeint(bb);
}


4 is also a string as far as the input extractor is concerned.

You might think to try reading the integers first, then try as strings.
But the stream will be in an error state if they're not integers.
https://en.cppreference.com/w/cpp/io/basic_ios/clear
If I read your code correctly (line 45, ff.) then you read the input numbers from the std::cin as std::string's and then you pass those strings through your function wordtodigit(). But, as far as I can tell, that function only deals with written out numbers, e.g. "five", but not with digits like "5".

Note that if (cin>>spokenstring1>>spokenstring2>>symbol1) will never be false, except when an error has occurred while extracting the strings from std::cin. And, of course, a user input like "5" can happily be extracted as a string from the std::cin stream. So, I don't think your else case will ever be executed...


Maybe you want something like:
1
2
3
4
5
6
7
8
int wordtodigit(std::string word) {
    for (int i = 0; i < numbersspoken.size(); ++i) {
        if (numbersspoken[i] == word) {
            return i;      
        }
    }
    return std::stoi(word); // <-- convert string to integer
}

...and ditch your recognizeint() function.
Last edited on
The issue is that you're first trying to read the string version then the int version. This will always read an int as a string. You need to first try to read the int version and if that fails then try to read the string version. Something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>

const std::vector<std::string> numbersspoken { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };

int wordtodigit(const std::string& word) {
	for (size_t i {}; i < numbersspoken.size(); ++i)
		if (numbersspoken[i] == word)
			return i;

	return -1;
}

int main() {
	std::cout << "Let's do some simple calculations with numbers (0-9) or words (zero-nine)\n"
		<< "Input either two single digit numbers (eg.4(space)5) or the words of two single digit numbers (eg.four(space)five) followed by an operator:\n"
		<< "* (multiply)\t+ (addition)\t/ (division)\t- (subtract)\n"
		<< "eg.4 5 * (4 multiplied by 5) OR four five * (4 multiplied by 5)\n";

	while (true) {
		int a {}, b {};
		char symbol1 {};
		std::string spokenstring1;
		std::string spokenstring2;

		std::cin.clear();
		if (!(std::cin >> a >> b >> symbol1)) {
			std::cin.clear();
			if (std::cin >> spokenstring1 >> spokenstring2 >> symbol1) {
				a = wordtodigit(spokenstring1);
				b = wordtodigit(spokenstring2);
				if (a < 0 || b < 0) {
					std::cout << "Invalid number word\n";
					std::cin.clear(std::ios_base::badbit);
				}
			} else
				std::cout << "Please re-read the instructions.\n";
		}

		if (std::cin) {
			switch (symbol1) {
				case '*':
					std::cout << "The product of " << a << " multiplied by " << b << " equals " << a * b << ".\n";
					break;

				case '+':
					std::cout << "The sum of " << a << " and " << b << " equals " << a + b << ".\n";
					break;

				case '/':
					std::cout << a << " divided by " << b << " equals " << a / b << ".\n";
					break;

				case '-':
					std::cout << a << " minus " << b << " equals " << a - b << ".\n";
					break;

				default:
					std::cout << a << symbol1 << b << "? Please re-read the instructions.\n";
					break;
			}
		}
	}
}

Thank you for your help everyone. I need to look into some of the things you have all mentioned. Most of the advice given is beyond my knowledge but I'm thankful I've got some leads as to why my program is not running correctly :)

Have a great day everyone. Thanks again.
I thought id post what I ended up with. I wanted to get my program to work in a way I understood so I've applied some things you guys have taught me but tried to keep it really basic.

I don't really have any solutions for bad input but the next chapter in the textbook I'm using is on 'errors' so that's okay.

I noticed if I tried to divide (for eg.) 5 by 4 I would get a rounding error so I initialized two doubles before the switch statement and converted the two ints into doubles for the '/' case.

Anyway, I managed to take some advice you gave me and used my understanding of c++ so far to get my program to execute correctly, so that's cool.

Cheers all.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include "\Users\User\Desktop\C++\std_lib_facilities.h"

vector<string> words_legal {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};

int word_to_number(string word){
    for (int i = 0; i < words_legal.size(); ++i){
        if(words_legal[i] == word){
            return i;
        }
    }
}

int main(){

    while (true){

        cout<<"Simple Calculator: input a simple calculation using numbers (0-9) or words (zero-nine), seperated by an operator (+, -, *, /) \n"
        <<"Eg. 2 + 3 OR two + three (then press 'enter')\n";


while (cin){
    string spokennumber1, spokennumber2 {};
   
    int a, b {};
   
    char symbol1 {};

    

    cin.clear();

   if (!(cin >> a >> symbol1 >> b )){
    
    
    cin.clear();
    if (cin >> spokennumber1 >> symbol1 >> spokennumber2 ){
        cout<<"debug: reading strings\n";
    a = word_to_number(spokennumber1);
    b = word_to_number(spokennumber2);
        
   } 
   }
    
double a1, b1 {};
    if (cin){
        switch (symbol1){

    case '*' :

    cout<<"The product of "<<a<<" multiplied by "<<b<<" equals "<<a*b<<".\n";
    break;

    case '+' :
    cout<<"The sum of "<<a<<" and "<<b<<" equals "<<a+b<<".\n";
    break;
    case '/' :
    
    a1 = a;
    b1 = b;

    cout<<a1<<" divided by "<<b1<<" equals "<<a1/b1<<".\n";
    break;
    case '-' :
    cout<<a<<" minus "<<b<<" equals "<<a-b<<".\n";
    break;
    default:
    cout<<a<<symbol1<<b<<"? Please re-read the instructions.\n";
    break;
}
    }

}
return 0;
}

}
Without error checking (which would be longer than the original code):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <cctype>
using namespace std;

int number( const string &str )
{
   map<string,int> words{ { "zero", 0 }, { "one", 1 }, { "two"  , 2 }, { "three", 3 }, { "four", 4 },
                          { "five", 5 }, { "six", 6 }, { "seven", 7 }, { "eight", 8 }, { "nine", 9 } };
   if ( isdigit( str[0] ) ) return stoi( str );
   else                     return words[str];
}

int main()
{
   string a, b;
   char op;
   
   cout << "Enter a op b: ";   cin >> a >> op >> b;
   switch( op )
   {
      case( '+' ):   cout << number( a ) + number( b ) << '\n';   break;
      case( '-' ):   cout << number( a ) - number( b ) << '\n';   break;
      case( '*' ):   cout << number( a ) * number( b ) << '\n';   break;
      case( '/' ):   cout << 1.0 * number( a ) / number( b ) << '\n';   break;
   }
}


Enter a op b: seven * 2
14


Enter a op b: nine + seven
16


Enter a op b: three / 5
0.6


Lots of error checking to do:
- words are in legitimate range; recognised; appropriate case
- integer input in correct range
- ops are legitimate characters
- correct number of inputs
- division by zero
etc. etc.
Last edited on
nice. I'm assuming that function maps each digit with a corresponding word so they can be used interchangeably. very neat. can't wait to learn :) Thanks for showing me how it's done!
also very cool that if you multiply 1.0 to the result of two integers you output a double.
Registered users can post here. Sign in or register to post.