I am in a beginner C++ course and I am trying to create a program that outputs the 12 days of Christmas song using the two given function calls show_ordinal(int) and show_verse(int) as an assignment. It is supposed to call the verse and show the day with it's ordinal suffix and then loop the remaining verses depending on where the user decides to start from, so if it was show_verse(3) it would be on the 3rd day of Christmas... all the way to the pear tree. I started writing for the function to get the ordinal but kept getting segmentation fault errors.
#include <iostream>
using namespace std;
string show_ordinal(int);
void show_verse(int);
int main()
{
cout << show_ordinal(2) << endl;
return 0;
}
string show_ordinal(int x)
{
switch (x % 10)
{
case 1:
if (x % 10 == 1)
{
cout << x << "st";
}
break;
case 2:
if (x % 10 == 2)
{
cout << x << "nd";
}
break;
case 3:
if (x % 10 == 3)
{
cout << x << "rd";
}
break;
case 4:
if (x % 10 != 1 || x % 10 != 2 || x % 10 != 3)
{
cout << x << "th";
}
break;
}
}
Testing the function by trying to call it with an int value of 2 in main,I have been working on it for awhile and cannot get it to work any help would be greatly appreciated.
show_ordinal returns nothing for
cout << show_ordinal(2) << endl;
to print out. It promises to return a string, but it never does. This is bad form. When a function has a non-void return type it must return a result on all code paths or the function, and the program, is ill formed. A crash or other segfault is a common result, but you could get silent corruption of data, and that is much harder to track down.
Rather than couting all of your results, assign the results to a string and return the string.
You never return a string from show_ordinal(), you just output to cout. Instead of using cout, I think you want to contsruct a string using x and your computed suffix and return that:
string show_ordinal(int x) {
string out;
switch (x % 10) {
case 1:
out = to_string(x) + "st";
break;
case 2:
out = to_string(x) + "nd";
break;
case 3:
out = to_string(x) + "rd";
break;
default:
out = to_string(x) + "th";
break;
}
return out;
}
You should probably count yourself lucky that you experienced a seg fault, because what you are doing is producing undefined behavior. If you don't believe me, check out what OnlineGDB does to your code.
The problem is that you define show_ordinal with a return value of std::string, but never return anything from the function. This produces undefined behavior in the C++ specification. To fix it you can do one of these two things:
Actually return a string. Rather than shifting into std::cout within the function, shift into an std::ostringstream instead, then return the stringified version:
#include<string>
#include<sstream>
std::string show_ordinal(int x) {
std::ostringstream oss;
switch (x % 10) {
case 1:
// Note: I got rid of your extraneous "if" statement.
// "switch" is already doing that work for you.
oss << x << "st";
break;
/* more cases here */
}
return oss.str();
}
Define the function to return nothing. If you really want the function to handle the shifting to std::cout, define it with a void return signature and don't shift the output to std::cout in main:
#include<iostream>
#include<string>
void show_ordinal(int x);
int main() {
show_ordinal(2);
}
void show_ordinal(int x) {
switch (x % 10) {
case 1:
std::cout << x << "st\n";
break;
/* more cases here */
}
}
Either of these should solve your problem.
Note: A few more things:
Please include all the headers for the standard libraries you are using. Add #include<string>.
You don't need those extra if statements in the case blocks. If your code made it to case 1, then x % 10 == 1 is guaranteed, so don't check it again.
show_ordinal won't do anything for x % 10 > 4. Consider replacing case 4 with default. See the documentation for the switch statement.
Please get out of the habit of using namespace std. It will get you in trouble in the future.
Related
I'm trying to see if I can make a fizzbuzz c++ switch statement. I'm getting an error saying i is not usable in a const expression. Does that mean I can't make this thing work? Or is there a work around? Here's my code.
#include <iostream>
using namespace std;
int main() {
for(int = 1; 1 <= 100; i++){
switch(true){
case(i % 3 == 0 & i % 5 == 0):
cout << "fizzbuzz" << endl;
break;
case(i % 3 == 0):
cout << "fizz" << endl;
break;
case(i % 5 == 0):
cout << "fizz" << endl;
break;
default:
cout << i << endl;
}
}
}
If you really want to use switch/case then you could do it like this:
switch (i % 15)
{
case 0 : cout << "fizzbuzz\n"; break;
case 5:
case 10: cout << "buzz\n"; break;
case 3:
case 6:
case 9:
case 12: cout << "fizz\n"; break;
default: cout << i << "\n"; break;;
}
There are a couple of fundamental problems with how you're using switch/case.
The expected way to use it is to have the switch refer to a variable or expression, then the case sections refer to constant values.
Instead what you're doing is switch(true) which doesn't make any sense, even though it compiles. It's equivalent to switch(1). So in that case only case 1: would ever apply.
You cannot use expressions for case. These must be constant integer values. So for example you can either plain integers case 0:, or also commonly pre-processor defines case FIZZBUZZ:.
As stated in the comments, several times, you cannot always use a switch() statement like a if statement and there are several other issues with your code. I am not going to give you the right answer as I don't believe that will help you the most.
Here are some notes:
1) Instead of a switch you should use if, else if, and else statements.
2) In C++ a and is expressed as && not &
3) A for loop is declared like for(int i = 0; i <= 100; i++)
You should watch/read some simple tutorials on how to code C++ as it is important you understand these basics.
How to write this program with switch condition statement instead of if?
#include <iostream>
using namespace std;
int main() {
int i;
for (i = 1; i <= 100; i++) {
if ((i % 7 == 0) && (i > 0)) {
cout << i << endl;
}
}
return 0;
}
The code you're looking for should be something like this:
#include <iostream> // this is for std::cin and std::cout (standard input and output)
using namespace std; // to shorten std::cout into cout
int main() {
cout << "multiples of 7 lower than 100 are:" << endl;
for ( int i=1 ; i<=100 ; i++ ) {
switch ( i%7 ) {
case 0: // this case 0 is similar to if ( i%7 == 0 )
cout << i << " ";
break;
default:
break;
}
}
cout << endl;
return 0;
}
The output will then be:
multiples of 7 lower than 100 are:
7 14 21 28 35 42 49 56 63 70 77 84 91 98
Here you are:
#include <iostream>
int main()
{
for (int i = 1; i<=100; i++)
{
switch(i % 7)
{
case 0:
std::cout << i << std::endl;
break;
default:
break;
}
}
return 0;
}
Online compilation: http://ideone.com/uq8Jue
It sounds like you are a little unfamiliar with a switch statement. A switch statement is like an if-else statement, except that it isn't a Boolean argument. So essentially it asks: Tell me the value of . And then for each case (possible outcome), it has a follow up action.
So you want to ask: tell me the value of the number, modulus 7. If it is zero, add one to the counter. If it is 1, do .
So your code should have a general structure of:
Switch(i%7):
Case 0{increment counter or display to std. out or store in array}
Case 1{other action}
It is possible to replace the if statement with switch/case statement for your case. But I think you have some misunderstanding about where to use if and where switch/case statements. I will suggest you use this statement as they are used in real life.
Use if, if you're going to check the condition. For example:
if (a > b){...} or if (a == 7){...} or if (functionReturnsTrue()){...}
The switch/case statement could be used when you have a set of conditions and the logic is different for each element in that set. For example:
enum HttpMethod {
GET,
POST,
PUT,
DELETE,
};
...
void handleHttpRequest(HttpRequest req)
{
...
switch(req.getHttpMethod())
{
case GET: handleGETRequest(req); break;
case POST: handlePOSTRequest(req); break;
case PUT: handlePUTRequest(req); break;
case DELETE: handleDELETERequest(req); break;
default: throw InvalidHttpMethod(); // in case when noone corresponds to the variable
}
}
Of course, you can write the same using if statement, but switch/case statement also have some compilation effects. When you switch the variable of enum type, you might get a compiler warning at least, if you dont check your variable for all possible flows.
Just going to change my question for now - I could just use some guidance as to why I have three compiler errors in my program, not quite sure what I did wrong/am missing - I have added comments into the code just to state where they are. Thanks
#include <iostream>
#include <string>
using namespace std;
class romanType
{
public:
void setRomanNum(string store);
// this function will store the Roman numeral
int convertNum(char rNum);
// this function will convert the Roman numeral to a decimal
void decimalPrint(int total);
// this function will print the decimal number
void romanPrint(char rNum);
// this function will print the Roman numeral
int getNum(char letter);
// this function will get the number input
romanType(int store);
//Constructor with parameter
romanType();
char roman[7];
string num;
int length = 0;
string dNum;
int equals;
};
romanType::romanType(int store)
{
dNum = 1;
}
void romanType::setRomanNum (string store)
{
dNum = store;
}
void romanType::romanPrint(char rNum)
{
cout << "The Roman numeral is: " << roman << endl;
}
void romanType::decimalPrint(int total)
{
cout << "The Decimal number is: " << equals << endl;
}
int romanType::convertNum (char rNum)
{
int letter;
int totalNum = 0;
for (int i = 0; i< dNum.length(); i++)
// "loop will run at most once (loop increment never executed)"?
{
switch (roman[i])
{
case 'M':
totalNum+= 1000;
break;
case 'D':
totalNum += 500;
break;
case 'C':
totalNum += 100;
break;
case 'L':
totalNum += 50;
break;
case 'X':
totalNum += 10;
break;
case 'V':
totalNum += 5;
break;
case 'I':
totalNum += 1;
break;
}
totalNum = totalNum + letter;
equals = totalNum;
return equals;
}
};
// "control may reach end of non-void function"
int main()
{
romanType output;
int rNumeral;
char entry;
cout << "Please enter a Roman numeral (Capitalized only): " << endl;
cin >> rNumeral;
cout << "Print Decimal or Roman Numeral? Type 1 for Decimal, 2 for Roman Numeral: " << endl;
cin >> entry;
if (entry == '1')
{
cout << "You chose to view the decimal conversion." << endl;
output.decimalPrint(rNum);
// How do I output the decimal conversion from the void romanType::decimalPrint(int total) function?
}
else if (entry == '2')
{
cout << "You chose to view the Roman numeral." << endl;
output.romanPrint(rNumeral);
}
else
cout << "Error: bad input" << endl;
return 0;
exit(1);
}
The mistake in the algorithm is that the Roman system is non-positional. See en.wikipedia.org/wiki/Roman_numerals and en.wikipedia.org/wiki/Subtractive_notation. You can't just add up consequent digits (i.e. letters) but you also have to identify and account for the cases when subtraction takes place.
why am I getting the error "no matching constructor for initialization of "roman type"?
Because the only provided constructor is not the default one, but takes one parameter of type int. Since such a constructor was provided, the default constructor wasn't generated by the compiler. Define romanType::romanType() or change the existing one to romanType::romanType(int i = 0) (add a default parameter). See Is there an implicit default constructor in C++? and why default constructor is not available by default in some case
expected expression?
Provide braces around the preceding else block. More than one statement -> braces required.
if (entry == '1') {
cout << "You chose to view the decimal conversion." << endl;
output.decimalPrint(rNum);
} else if (entry == '2')
cout << "You chose to view the Roman numeral." << endl;
output.romanPrint(rNumeral);
}
"control may reach end of non-void function"
This is a warning only, but it will turn into an error if you include the -Werror flag that tells the compiler to treat all warnings as errors.
Ok I was wrong on this one. Actually the trick is that it is (in theory) possible that the romanType::convertNum(int) function follows a route where the for loop will never get executed and thus no return statement will be executed either. That's bad since the function is declared to return int hence there must be present an explicit return statement that (surprise) would return a value. Move the return out of the loop. This error is also closely related to the next one, discussed below.
"loop will run at most once (loop increment never executed)"?
This is because the return statement is placed incorrectly: inside the for loop not outside of it, and inside the function body. Hence the loop runs once and the function returns. Move the return statement. Credit to #ATN_LR_boom for noticing this!
Also, please get in the habit of formatting code properly. It will save you a lot of headache down the way.
Other than that, I'd use a std::map for the conversion function, it's shorter and more clear to the reader compared to the switch statement. Something along the lines of
int romanType::convertNum(int rNum) {
const static std::map<char, int> conversion = {
{'M', 1000},
{'D', 500},
// more mappings
{'I', 1}
};
if ((auto it = conversion.find(rNum)) != conversion.end())
return it->second;
else
return -1;
}
Your logic for the switch is wrong, try something like this:
int totalNum = 0;
for (int i = 0; i< dNum.length(); i++)
// the loop ran once because you were returning values when catching a letter
{
switch (roman[i])
{
case 'M': // roman[i] is a char, the cases should try to catch chars
totalNum += 1000; // increment your global number
break;
case 'D':
totalNum += 500;
break;
...
}
return totalNum;
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
string numString(int k)
{
string str;
switch (k) {
case 0 : str ="ZERO"; break;
case 1 : str ="ONE"; break;
case 2 : str ="TWO"; break;
case 3 : str ="THREE"; break;
case 4 : str ="FOUR"; break;
case 5 : str ="FIVE"; break;
case 6 : str ="SIX"; break;
case 7 : str ="SEVEN"; break;
case 8 : str ="EIGHT"; break;
case 9 : str ="NINE"; break;
}
return str;
}
int main(int argc, char** argv) {
int value;
int digit;
cout << "Enter a number: ";
cin >> value;
while (value > 0 )
{
digit = value % 10;
value = value / 10;
cout << numString(value) << endl;
}
return 0;
}
My program is supposed to prompt the user for an integer value read that value, and output the word equivalent of each digit
For example if "9502" was entered it would output "NINE FIVE ZERO TWO"
Yet mine only outputs "NINE ZERO" and then stops. I can't figure out what I'm doing wrong, any help at all is greatly appreciated.
Yet mine only outputs "NINE ZERO" and then stops.
That's literally what you told it to do!
while (value > 0 )
You'll have to find some other way to signal a "termination" condition if zero is supposed to be valid.
Traditionally we let the system's own end-of-file signalling take care of that for us, so that we don't have to "reserve" some otherwise-valid input and use it as a signal flag.
while (cin >> value) {
digit = value % 10;
value = value / 10;
cout << numString(value) << endl;
}
That fixes your loop, although unfortunately your maths are still wrong and your output is not what you intend. In fact, your digit variable is not used at all. I am not going to spoonfeed an algorithm here: you'll have to work out on paper how to achieve the business logic. :)
This is an analysis of your program using the input 9502.
Iteration 1, in main:
(new) value = 9502 / 10;
(new) digit = 9502 % 10;
value == 950;
digit == 2;
call numString(950);
// Note: there is no case for 950 in numString so an empty string is returned.
Iteration 2, in main:
(new) value = 950 / 10;
(new) digit = 950 % 2;
value == 95;
digit == 0;
call numString(95);
// Note: there is no case for 95 in numString so an empty string is returned.
The above iterations and variable values can be obtained with pen & paper (or a note pad). You can also do the same with something called a debugger.
I hope this helps.
#include <iostream>
#include <sstream>
#include <stack>
#include <limits>
#include <string>
using namespace std;
int main()
{
string input;
cout << "Enter a postfix expression: " << endl;
getline(cin, input);
int operand1, operand2, result,number;
stack<char>operation;
stringstream temp;
int i=0;
while (i < input.length())
{
if (isdigit(input[i]))
{
operation.push(input[i]);
}
else
{
operand2 = operation.top();
temp << operation.top();
operation.pop();
operand1 = operation.top();
temp << operation.top();
operation.pop();
switch(operand1,operand2)
{
case '+': result=operand1 + operand2;
break;
case '-': result=operand1 - operand2;
break;
case '*': result=operand1 * operand2;
break;
case '/': result=operand1 / operand2;
break;
}
operation.push(result);
}
i++;
}
cout << "The result is: "<<temp.str()<<endl;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
return 0;
}
I've changed the code and managed to obtain the "pop" value, but the operation didn't work.
You probably meant
switch(input[i])
instead
switch(operation.top())
Update response to code changes
I can confirm you changed the code, but not in a good way.
The code mostly has all the flaws it already had, and a few more.
What good is that you now combine the operands into a stringstream?
You now switch on (operand1,operand2)...
both are uninitialized
(operand1,operand2) means basically (operand2) in this context (sequence operator)
your branch labels are ... operators (+-/*)
you now print a final result which is the concatenation of all digits in the input (if you ever reach the end of the program without crashing)?
Among the things that were wrong before, and should still be fixed
the mental model of a stack calculator.
numbers (integers) are the operands (so 9, 100, 39829 are valid operands)
+-/* are the operators (operators operate on the operands)
the stack is an operand stack, not an operator stack (operators do not have to be remembered, because they are evaluated immediately)
numbers consist of 1 or more digits (0123456789) in a row; so you'd need to read several characters before you can 'push' a number on the operand stack
the operators +-/* take 2 operands, so any operation on a stack of size<2 is an error (you need to check that or the program will crash while trying to access memory that doesn't exist or contains rubbish).
That should be enough to get you started.
Two things I do think are positive:
You program compiles. +1 for you actually using a compiler there :)
You took the repeated operation.push(result) out of the switch so it isn't duplicated anymore. +1 for coding style ...
I hope you can gather from this that the code isn't very good (to put it mildly), and I really think some basic exercises are in order:
1. write a simple for loop that prints numbers 1 to 10 to the console
1. write a simple while loop that prints words entered by the user
1. use a simple loop to print all numbers between 1 and 50 that are multiples of 7
1. use a switch statement to print "yes" whenever the user enters one of the letters a, b, k, or z
2. make a simple loop that only prints the input character for every character that follows the identical (so 'abccdefgghijkllmabcdd' would become 'cgld')
1. use the same loop but this time print every word that immediately follows the identical word (so "no, no, you should not pop, pop, but push, pop" becomes "no pop")
That should give you a feel for how things really work, without the guesswork or the 'magic factor'.
Oh, and don't forget, I implemented the whole thing for you below. I don't suggest you blindly copy it (it will be rather obvious to your teacher :)) but it is there for you to take a peek if you want to know, what I mean with all my words above :)
You are pushing loose digits, not parsed numbers
In line 31 you pop a possibly empty stack (resulting in segfault unless you use the debug-mode STL flags on your compiler)
Just for fun:
#include <iostream>
#include <stack>
#include <vector>
#include <limits>
#include <string>
#include <stdexcept>
#include <iterator>
#include <fstream>
using namespace std;
template <class T>
static void dumpstack(std::stack<T> s/*byval!*/)
{
std::vector<T> vec;
while (!s.empty())
{
vec.push_back(s.top());
s.pop();
}
std::copy(vec.rbegin(), vec.rend(), std::ostream_iterator<int>(std::cout, " "));
}
class calc
{
private:
std::stack<int> _stack;
int _accum;
bool _pending;
void store(/*store accumulator if pending*/)
{
if (_pending)
{
_stack.push(_accum);
_pending = false;
_accum = 0;
}
}
public:
calc() : _accum(0), _pending(false)
{
}
void handle(char ch)
{
switch (ch)
{
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
_pending = true;
_accum *= 10;
_accum += ch-'0';
break;
case '+': case '-': case '/': case '*':
{
store();
if (_stack.size()<2)
throw std::runtime_error("stack underflow");
int op2 = _stack.top(); _stack.pop();
int op1 = _stack.top(); _stack.pop();
switch (ch)
{
case '+': _stack.push(op1 + op2); break;
case '-': _stack.push(op1 - op2); break;
case '/': _stack.push(op1 / op2); break;
case '*': _stack.push(op1 * op2); break;
}
// feedback to console:
std::cout << std::endl << "(evaluated: " << op1 << " " << ch << " " << op2 << " == " << _stack.top() << ")" << std::endl;
dump();
}
break;
default:
store(); // todo: notify of ignored characters in input?
}
}
void dump() const
{
dumpstack(_stack);
}
};
int main()
{
cout << "Enter postfix expressions: " << endl;
calc instance;
try
{
while (std::cin.good())
{
char ch = std::cin.get();
instance.handle(ch);
}
std::cout << "Final result: ";
instance.dump();
return 0;
} catch(const std::exception& e)
{
std::cerr << "E: " << e.what() << std::endl;
return 255;
}
}
Test output: (note that you can continue with the remaining, partially evaluted, stack after pressing carriage return)
Enter postfix expressions:
1 2 3 +4 * - / 1333 *
(evaluated: 2 + 3 == 5)
1 5
(evaluated: 5 * 4 == 20)
1 20
(evaluated: 1 - 20 == -19)
-19 E: stack underflow
There are many things wrong with the code, starting with parsing of the input expression. The actual crash is most probably due to the fact that if you input something like "12+" you will push '1' and '2' into the stack (note: characters 1 and 2, not values 1 and 2!!!) and then try to extract two operands and an operator that you never inserted into the stack.
On parsing the input, you are reading character by character, and only using the first digit, the parsing is not able to handle spaces or any other separator... Try to break the problem in two: parsing and processing. The problem of parsing can be tackled by not using the actual values read, but just printing them (or storing in some form and then printing the whole read expression), and can be a first step. Ensure that the parser is able to deal with common expressions like "1 2 +", "10 20 +", "1 2+", " 1 2 + " (note the different positions of spaces) in a robust way. And that it fails gracefully to parse expressions like " +", "1 +", "1 2 ++"... You can never trust user input, they will make mistakes and that should not bring your program to its knees.
Once you are sure that you are able to parse the input, start on the actual algorithm. Make it robust against invalid user inputs that you might have not been able to tackle before, like "10 0 /" and do the actual processing.
Learn to use the debugger, it will help you understand when things go south what are the reasons. The debugger would take less than one second to point at the specific problem in your code above, it will not tell you why it died, but it will show you how it died and what the state of the program was there. If my hunch is correct, then it will point you at the operation.top() instruction as the culprit, and you will be able to see that you were trying to extract more elements than were inserted. Execute a part of your program step by step to understand what it is actually doing, and you will notice that when you read "12+" you are actually storing two seemingly unrelated integers into the stack (the ASCII values of '1' and '2'...