Modulo in a conditional expression - c++

I'm very new to programming and am starting out with Bjourne's book: Programming principles and practice c++ 2nd edition. Exercise 8 chapter 3 he asks for:
"Write a program to test an integer value to determine if it is odd or even...Hint: See the remainder (modulo)operator in ยง3.4."
I can do that with something like:
int main() {
int n;
cout << "Enter an integer: ";
cin >> n;
if ( n%2 == 0) {
cout << n << " is even.";
}
else {
cout << n << " is odd.";
}
return 0;
}
But he gives in his website his own solution:
int main()
{
int val = 0;
cout << "Please enter an integer: ";
cin >> val;;
if (!cin) error("something went bad with the read");
string res = "even";
if (val%2) res = "odd";
cout << "The value " << val << " is an " << res << " number\n";
keep_window_open();
}
catch (runtime_error e) {
cout << e.what() << '\n';
keep_window_open("~");
}
/*
Note the technique of picking a default value for the result ("even") and changing it only
if needed.
The alternative would be to use a conditional expression and write
string res = (val%2) ? "even" : "odd";
What is
string res = "even";
if (val%2) res = "odd";
and
string res = (val%2) ? "even" : "odd";
actually doing? I haven't seen him explaining those before in the book. Also, the last code, It gives me "odd" result when I type an even value and gives an "even " result when I type and odd one. what is going on? Sorry for the long post, hope I could explain what I need...

The ? : is the ternary operator.
if (val%2) res = "odd";
is just a rather terse version of
if (val%2) {
res = "odd";
}
And note that if(...) actually doesn't care whether the value is "true" or "false." It just checks for zero or nonzero. So it's equivalent to
if( val%2 != 0)
The second command line : string res = (val%2) ? "even" : "odd"; similary is a short way for writing:
string res;
if(val%2 != 0){
res = "even";
}
else{
res = "odd";
}
The syntax for those kind of commands is condition ? value_if_true : value_if_false

Adding to the previous answers, you have to note the boolean (or "true" values) are 0s and 1s, (0 being false and 1 being true in boolean algebra)
So, when
string res = (val % 2) ? "even" : "odd";
Note that when you give and odd value it will always return number 1 which is "true", and viceversa for even numbers.
You would have to turn those around for the program to work.

He just instead of writing multiple brackets, does not use them at all
string res = "even"; //default value
if (val%2) res = "odd"; //in case it is odd, value changes
//output or threat in some way value.
instead
string res = (val%2) ? "even" : "odd";
Simply a short way of writing the same if/else you wrote before.

Related

Determining if user input is palindrome with C++

First of all, I very much appreciate any help you are willing to provide. I am new to C++ and have been scouring this website as well as other resources for the solution to my problem.
Further, this was indeed a portion of a homework assignment. However, the assignment has been turned in (upsettingly, without getting this code to work). It would be great to get an explanation for what the problem in my specific code is and how to fix my current code, rather than the just rewritten code with a different way to approach to problem. I certainly found plenty of ways to solve this problem on this wonderful site!
I am getting no errors with my code, however the reversal output is not showing the reversed character array. This results in my little program here always showing "Your string is not a palindrome! :(" no matter what the input is.
#include <iostream>
#include <string>
using namespace std;
int isPalindrome(char *input, char *input2);
char reverseString(char *input);
int main ()
{
char input[50];
char input2[50];
cout << "Please enter a string of characters no larger than 50." << endl;
cin.getline(input, 50);
reverseString(input);
cout << "The reversed string is " << input2 << endl;
int result;
result = isPalindrome(input, input2);
if(result == 0)
cout << "Your string is a palindrome!" << endl;
else
cout << "Your string is not a palindrome! :( " << endl;
return 0;
}
int isPalindrome(char* first, char* second)
{
if (*first == *second)
return 0;
else
return 1;
}
char reverseString(char* input2)
{
int size = sizeof(input2);
for (int i = 0; i < (size/2); i ++)
swap(input2[i], input2[size-i-1]);
return *input2;
}
Again, I appreciate any help you can provide! I apologize if this is a simple error that I am overlooking and should have been able to find elsewhere.
Checking for a palindrome does not take this much effort.
bool isPalindrome(const char* s) // this function is self-contained.
{ // the caller does not need to provide
size_t n = strlen(s); // any pre-computed value.
if (n == 0)
return false;
const char* e = s + n - 1;
while (s < e)
if (*s++ != *e--)
return false;
return true;
}
int main ()
{
char input[50];
cout << "Please enter a string of characters no larger than 50." << endl;
cin.getline(input, 50);
bool result = isPalindrome(input);
cout << "Your string is"
<< ((result) ? " " : " not ")
<< "a palindrome!\n";
return (result) ? 1 : 0;
}
In your reverseString function:
char reverseString(char* input2)
{
int size = sizeof(input2); // <-- ?? sizeof(char*) != strlen(input2)
size_t size = strlen(input2); // <-- should read.
for (int i = 0; i < (size/2); i ++)
swap(input2[i], input2[size-i-1]);
return *input2; // what's this? returning first char? why?
}

Program doesn't work, add print statement it works, why? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
We have to write a gcd calculator, iteratively and recursively, and we are given a test script and my program fails 2/10 tests(gcd_iterative(1000, 48) = 1000, gcd_iterative(48, 24) = 48). so I showered my program with print statements 'and it worked. I started removing 1 statement at a time and there is 1 line where if I remove the statement it produces the wrong answer. Why does this happen and how can I fix it?
using namespace std;
#include <sstream>
#include <string>
#include <iostream>
#include <cstdlib>
int gcd_iterative(int m, int n)
{
int r;
while(r != 0)
{
r = m % n;
m = n;
n = r;
}
return m;
}
int gcd_recursive(int m, int n)
{
if(n == 0)
{
return m;
}
else
{
return gcd_recursive(n, m % n);
}
}
int main(int argc, char *argv[])
{
if (argc != 3)
{
cerr << "Usage: " << argv[0] << " <integer m> <integer n>" << endl;
return 1;
}
istringstream iss;
iss.str(argv[1]);
int m;
if (!(iss >> m))
{
cerr << "Error: The first argument is not a valid integer." << endl;
return 1;
}
iss.clear();
iss.str(argv[2]);
int n;
if (!(iss >> n))
{
cerr << "Error: The second argument is not a valid integer." << endl;
return 1;
}
cout << "" << endl;
cout << "Iterative: gcd(" << m << ", " << n << ") = " << gcd_iterative(m, n) << endl;
cout << "Recursive: gcd(" << m << ", " << n << ") = " << gcd_recursive(m, n) << endl;
return 0;
}
the print statement is cout << "" << endl;.
The problem is in here:
int r;
while(r != 0)
{
r = m % n;
m = n;
n = r;
}
return m;
The value of r is not initialized to anything, so if the initial value is zero, the algorithm will terminate on the while loop and just return the value of m unchanged.
C++ is not required to initialize the values of stack variables to any default value or anything else, so the value in the r variable is whatever was left on the stack by the previous function call. It would seem that it just so happens that cout << endl; leaves a nonzero value in the correct stack position for r to have a nonzero value, and actually run the algorithm. (Note that if C++ did supply a default value, the default value would presumably be zero anyway, so you would still be forced to initialize).
In general, you should initialize the default values of stack variables to a safe value, rather than relying on their default values. So in this case, the fix is to set r to any nonzero value when you first declare it. E.g. int r = 1;
Side note: In C/C++ any integer value can be used as a boolean, and zero is false, so your while condition can be simplified to just while(r) rather than while(r != 0); these are completely equivalent expressions as far as the while loop is concerned.
when program's result changes like this, it is likely you forgot to initalize some variable. In your case, it looks you forgot to initialize r:
int r;
while(r != 0)
'r' will get an arbitrary value (whatever happens to be in the CPU register). It is likely that without print statements, r is zero and thus the while() loop never runs. You want to set to non-zero value explicitly.

C++ Strings Matching Returning False

I'm working on my C++ assignment. I'm having an issue with string comparison.
I'm comparing two apparently identical strings using == operating but the condition returns false. The debugger also shows that both strings (stored in different variables) are identical. I must be missing something.
Here is my code:
void classCounter() {
ifstream fread;
string linetxt;
char *records[50];
char myLine[100];
char delims[] = "|";
int btotal=0,etotal=0,total=0;
fread.open("F:\\myfile.txt");
while(!fread.eof()) {
getline(fread,linetxt,'\n');
int i = 0;
strcpy(myLine, linetxt.c_str());
records[i] = strtok( myLine, delims );
while( records[i] != NULL )
{
cout << records[i] << "|";
char *bu = "Business";
if(records[i] == bu) {
btotal++;
}
if(records[i] == "Economy") {
etotal++;
}
//printf("%d '%s'\n", i, records[i]);
records[++i] = strtok( NULL, delims );
break;
}
total++;
}
cout << "Total number of booked Business seats: " << btotal << endl;
cout << "Total number of booked Economy seats: " << etotal << endl;
cout << "Total number of booked seats: " << total << endl << endl;
}
Here is what debugger shows:
Both if conditions are returning false.
Please suggest what could be the issue.
You are comparing two pointers, and they will never be the same. Either heed the advice to use std::string (what I recommend too) or you use strcmp to compare strings.
if(records[i] == bu) {
and
if(records[i] == "Economy") {
compare two char*, not strings.
You can compare them as strings by using std::string or using the function strcmp.
Option 1: Use std::string
std::string records[50];
With that change,
if(records[i] == bu) {
and
if(records[i] == "Economy") {
should work.
Option 2: Use strcmp
if( strcmp(records[i], bu) == 0) {
and
if( strcmp(records[i], "Economy") == 0) {
Your debugger is telling you what you need to know.. You're using char* instead of String so your char* are pointers. Your program is comparing two pointers and 0x00c93bc0 != 0x002af824.
Use strcmp in the future to avoid this problem
So I'm going to assume your input file looks something like:
Business|Economy|Economy|Economy|Business
Economy|Economy|Economy|Business|Economy
...and so on. Correct? And you're trying to count up how many of each kind of ticket was sold?
If so, I'd write the code quite a bit differently. I'd probably do something like this:
std::map<std::string, int> tickets;
std::string name;
std::ifstream in("f:/myfile.txt");
int total = 0;
while (std::getline(in, name, '|')) {
++tickets[name];
++total;
}
for (auto t : tickets)
std::cout << "Total number of booked " << t.first << " seats is: " << t.second "\n";
std::cout << "Total number of booked tickets: " << total << "\n";

Optimized way to check the value of a variable with enum members value

Hello I have the code below:
enum {a, b, c, d, ..., z} abc;
int main()
{
int val = 20;
if (val == a || val == b ||val == c||val == d..... || val == z)
{
/*Do something*/
}
}
Is there any other way so that we can skip the OR operation because if there are 1000s of enum members then how can we do ahead with checking with all members.
Please help.
A modern compiler should just be able to optimize such code if, as in your case, the value of the expression is known at compile time. For readability and error checking I think that using a switch would be better:
switch (val) {
case a:;
case b:;
....
// your code goes here
}
As said, performance wise there shouldn't be much difference, the compiler will transform this to a table lookup (or other clever things) if appropriate or completely optimize it out if val is known at compile time.
But you can have the advantage of error checking compilers, here. If you don't have a default case, most compilers will warn you if you omit one of the enumeration constants. Also I think that this is clearer, since it doesn't repeat the evaluation of val all over the place.
other(faster) solution will be the following
bool isInenum (int val)
{
bool retVal = false
switch(val)
{
case a:
case b:
case c:
case d:
{
retVal = true;
}
}
return retVal;
}
Since enumerator values are assigned sequentially, putting an if statement like this would be enough:
if(val<=z)
You could use a map in C++. With a map you can write a compact test without the numerous == and ||.
But you first need to initialize a map and I'm not sure if you can do this initialization in a compact way for an arbitrary enum.
#include <iostream>
#include <map>
using namespace std;
enum abc { a = 1, b = -1, c = 3, d = 0 };
int main()
{
map<int, int> m;
m[a] = m[b] = m[c] = m[d] = 1;
cout << "b is " << ((m.find(b) == m.end()) ? "NOT " : "") << "in m" << endl;
cout << "3 is " << ((m.find(3) == m.end()) ? "NOT " : "") << "in m" << endl;
cout << "10 is " << ((m.find(10) == m.end()) ? "NOT " : "") << "in m" << endl;
return 0;
}
Output (ideone):
b is in m
3 is in m
10 is NOT in m

Handling an 'else' type situation within a loop

I have a homework problem for my C++ class and the problem wants us to have the user input a wavelength and then output the correct type of radiation. The point to notice is that there are more Wave Name values than there are Wave Lengths.
My solution is listed below:
const double WAVE_LENGTH[] = { 1e-11, 1e-8, 4e-7, 7e-7, 1e-3, 1e-2 };
const char* WAVE_NAME[] = { "Gamma Rays", "X Rays", "Ultraviolet", "Visible Light", "Infrared", "Microwaves", "Radio Waves" };
double waveLength;
std::cout << "Enter a wavelength in decimal or scientific notation\nWavelength: ";
std::cin >> waveLength;
for (unsigned short i = 0U; i < 6U; ++i)
{
if (waveLength < WAVE_LENGTH[i])
{
std::cout << "The type of radiation is " << WAVE_NAME[i] << std::endl;
break;
}
if (i == 5U) // Last iteration
std::cout << "The type of radiation is " << WAVE_NAME[i + 1] << std::endl;
}
My question is regarding my approach at solving the problem, specifically within the loop. I can't seem to find a way to handle all the situations without creating two conditions inside the loop which seems like it is a poor design. I realize I could use a series of if/else if statements, but I figured a loop is cleaner. Is my approach the best way or is there a cleaner way of coding this?
Thanks!
I think you can simplify your loop to this:
unsigned short i;
for (i = 0U; i < 6U; ++i)
{
if (waveLength < WAVE_LENGTH[i])
{
break;
}
}
std::cout << "The type of radiation is " << WAVE_NAME[i] << std::endl;
In my view a somewhat cleaner design is to add positive infinity as the last element of WAVE_LENGTH. This way your corner case will require no special handling:
#include <iostream>
#include <limits>
...
const double WAVE_LENGTH[] = { 1e-11, 1e-8, 4e-7, 7e-7, 1e-3, 1e-2,
std::numeric_limits<double>::infinity() };
const char* WAVE_NAME[] = { "Gamma Rays", "X Rays", "Ultraviolet", "Visible Light",
"Infrared", "Microwaves", "Radio Waves" };
double waveLength;
std::cout << "Enter a wavelength in decimal or scientific notation\nWavelength: ";
std::cin >> waveLength;
for (int i = 0; i < sizeof(WAVE_LENGTH) / sizeof(WAVE_LENGTH[0]); ++i)
{
if (waveLength < WAVE_LENGTH[i])
{
std::cout << "The type of radiation is " << WAVE_NAME[i] << std::endl;
break;
}
}
Also note how I've avoided having to hard-code the length of the array (6U in your code) in the loop's terminal condition.
You can test the last iteration in the same if. Notice there is no test anymore itn for.
for (unsigned short i = 0U; ; ++i)
{
if (i == 6 || waveLength < WAVE_LENGTH[i])
{
std::cout << "The type of radiation is " << WAVE_NAME[i] << std::endl;
break;
}
}
Alternatively, you can add a extra wavelength set to MAX_FLOAT (or whatever is called in C++) or set the last one to zero and exit if wave_length[i] == 0.0. That way you don't need to "know" the number of wave lengths.