i keep running into problems with if elif and else in c++ - c++

question: every time I run the program and I input who are you it says Error Value of a is not matching what is going on? (yes I am a noob to c++)
code:
#include <iostream>
using namespace std;
int main () {
// local variable declaration:
string a;
cin >> a;
// check the boolean condition
if( a == "hello" ) {
// if condition is true then print the following
cout << "hi" << endl;
} else if( a == "who are you" ) {
// if else if condition is true
cout << "a better question is who are you?" << endl;
} else if( a == "what am i doing" ) {
// if else if condition is true
cout << "reading this output " << endl;
}else {
// if none of the conditions is true
cout << "Error Value of a is not matching" << endl;
}
return 0;
}

The operator >> for streams and strings inputs words separated by white spaces. You should use a function that can read at once several words up to the Enter key will be pressed. For example you can use standard function std::getline
Also you need to include header <string>.
Here you are
#include <iostream>
#include <string>
int main()
{
std::string s;
if ( std::getline( std::cin, s ) )
{
// check the boolean condition
if ( s == "hello" )
{
// if condition is true then print the following
std::cout << "hi" << std::endl;
}
else if ( s == "who are you" )
{
// if else if condition is true
std::cout << "a better question is who are you?" << std::endl;
}
else if ( s == "what am i doing" )
{
// if else if condition is true
std::cout << "reading this output " << std::endl;
}
else
{
// if none of the conditions is true
std::cout << "Error Value of a is not matching" << std::endl;
}
}
return 0;
}

Related

Way to reduce else if statements when using string as condition

I'm making a terminal-like program (to calculate currency) with custom commands as input but I have a problem.
Every time I implement a new command, I have to add a new else if statement. This wouldn't be a problem but for a terminal-like program there can be a lot of commands.
Here is my code:
#include <iostream>
#include <string>
#include <Windows.h>
#include <math.h>
float user_balance = 0.0f;
float eur_in_czk = 24.0f; //ammount of czk in single euro
std::string currency = "czk";
bool czk_to_eur_enabled = true;
bool eur_to_czk_enabled = false;
//------------------START method definition---------------------------------------------------------
void czk_to_eur()
{
if (czk_to_eur_enabled) //to prevent using twice in a row
{
user_balance /= eur_in_czk;
user_balance = floorf(user_balance * 100) / 100; //limit to two decimal numbers
currency = "eur";
czk_to_eur_enabled = false;
eur_to_czk_enabled = true;
}
else
{
std::cout << "Your savings are already converted to " << currency << "!" << std::endl;
}
}
void eur_to_czk()
{
if (eur_to_czk_enabled) //to prevent using twice in a row
{
user_balance *= eur_in_czk;
user_balance = floorf(user_balance * 100) / 100; //limit to two decimal numbers
currency = "czk";
eur_to_czk_enabled = false;
czk_to_eur_enabled = true;
}
else
{
std::cout << "Your savings are already converted to " << currency << "!" << std::endl;
}
}
void set_balance(float new_balance)
{
user_balance = new_balance;
}
void add_balance(float new_balance)
{
user_balance += new_balance;
}
//------------------END method definition-----------------------------------------------------------
int main()
{
bool main_loop = true; //main loop enabler
float input_money;
std::string user_command = "";
std::cout << "This is currency converter v1.0 (czk to eur and back)\n\n\n" << std::endl;
while (main_loop) //main loop for currency converter
{
std::cout << "Input: ";
std::cin >> user_command;
std::cout << std::endl;
if ((user_command == "setbal") || (user_command == "SETBAL"))
{
std::cout << "Your balance is " << user_balance << " " << currency << ".\n";
std::cout << "Please enter desired value (" << currency << "): ";
std::cin >> input_money;
set_balance(input_money);
std::cout << "\n" << std::endl;
}
else if ((user_command == "addbal") || (user_command == "ADDBAL"))
{
std::cout << "Your balance is " << user_balance << " " << currency << ".\n";
std::cout << "Please enter desired value (" << currency << "): ";
std::cin >> input_money;
add_balance(input_money);
std::cout << "\n" << std::endl;
}
else if ((user_command == "balance") || (user_command == "BALANCE"))
{
std::cout << "Your balance is " << user_balance << " " << currency << "." << std::endl;
}
else if ((user_command == "curstat") || (user_command == "CURSTAT"))
{
std::cout << "Currency status is " << eur_in_czk << " czk in 1 eur." << std::endl;
}
else if ((user_command == "toeur") || (user_command == "TOEUR"))
{
czk_to_eur();
}
else if ((user_command == "toczk") || (user_command == "TOCZK"))
{
eur_to_czk();
}
else if ((user_command == "cheuv") || (user_command == "CHEUV"))
{
std::cout << "Change eur value (" << eur_in_czk << "): ";
std::cin >> eur_in_czk;
std::cout << std::endl;
}
else if ((user_command == "help") || (user_command == "HELP"))
{
std::cout << "SETBAL Sets balance.\n"
<< "ADDBAL Adds balance.\n"
<< "BALANCE Shows current balance.\n"
<< "CURSTAT Shows currency status.\n"
<< "TOEUR Converts czk to eur.\n"
<< "TOCZK Converts eur to czk.\n"
<< "CHEUV Changes eur currency value.\n"
<< "CLS Cleans terminal history.\n"
<< "EXIT Exits program.\n" << std::endl;
}
else if ((user_command == "cls") || (user_command == "CLS"))
{
system("CLS"); //funtion from Windows.h library
}
else if ((user_command == "exit") || (user_command == "EXIT"))
{
main_loop = false;
}
else
{
std::cout << "'" << user_command << "'"
<< "is not recognized as an internal or external command!\n";
std::cout << "Type 'HELP' to see available commands.\n" << std::endl;
}
}
return 0;
}
The bottom part of the code in while cycle is where the problem is.
Everything works fine but I would like to know, if there is any other way. And switch to my knowledge does not support string values as condition/dependency. (also I'm currently not using any custom classes and/or custom header files because this is just experiment.)
Is there any other way to do it?
Normally I would suggest using a std::map with a string as the key and a function as the value so that you could search the map for a command and then invoke the function associated with it. However, since that's already been mentioned in the comments I figured I'd get all fancy and provide a totally wack solution you probably shouldn't use.
This wack solution allows you to use string literals in a switch/case statement. This is possible by taking advantage of a feature of modern C++ called user defined literals that allow you to produce objects of user-defined type by defining a user-defined suffix much in the same way you append U to a integer literal to specify an unsigned value.
The first thing we'll do is define a user defined literal that produces a hash value that is calculated at compile time. Since this generates a hash value from the string it is possible to encounter collisions but that's dependant on the quality of the hash algorithm used. For our example we're going to use something simple. This following snippet defines a string literal with the suffix _C that generates our hash.
constexpr uint32_t djb2Hash(const char* str, int index = 0)
{
return !str[index]
? 0x1505
: (djb2Hash(str, index + 1) * 0x21) ^ str[index];
}
// Create a literal type for short-hand case strings
constexpr uint32_t operator"" _C(const char str[], size_t /*size*/)
{
return djb2Hash(str);
}
Now every time the compiler sees a string literal in the format of "Hello World"_C it will produce a hash value and use that in place of the string.
Now we'll apply this to your existing code. First we'll separate the code that takes the user command from cin and make the given command all lower case.
std::string get_command()
{
std::cout << "Input: ";
std::string user_command;
std::cin >> user_command;
std::cout << std::endl;
std::transform(
user_command.begin(),
user_command.end(),
user_command.begin(),
[](char ch) { return static_cast<char>(std::tolower(ch)); });
return user_command;
}
There now that we can get an all lowercase command from the user we need to process that so we'll take your original set of if/else statements and turn them into a simple switch/case statement instead. Now since we can't actually use string literals in the switch/case statement we'll have to fudge a little bit and generate the hash value of the users command for the switch part of the code. We'll also take all of your commands and add the _C suffix to them so that the compiler automatically generates our hash values for us.
int main()
{
bool main_loop = true; //main loop enabler
std::cout << "This is currency converter v1.0 (czk to eur and back)\n\n\n" << std::endl;
while (main_loop) //main loop for currency converter
{
const auto user_command(get_command());
switch(djb2Hash(user_command.c_str()))
{
case "setbal"_C:
std::cout << "Set balance command\n";
break;
case "addbal"_C:
std::cout << "Add balance command\n";
break;
case "balance"_C:
std::cout << "Get balance command\n";
break;
case "curstat"_C:
std::cout << "Get current status command\n";
break;
case "help"_C:
std::cout << "Get help command\n";
break;
case "exit"_C:
main_loop = false;
break;
default:
std::cout
<< "'" << user_command << "'"
<< "is not recognized as an internal or external command!\n"
<< "Type 'HELP' to see available commands.\n" << std::endl;
}
}
}
And there you have it. A totally wack solution! Now keep in mind that we're not really using strings in the switch/case statement, we're just hiding most of the details of generating hash values which are then used.

Calling a function multiple times but it prints only once

I'm running the following code:
#include <iostream>
using namespace std;
string response(bool isMale, bool isTall)
{
if (isMale && isTall) {
cout << "MALE AND TALL" << endl;
}
else if (isMale || isTall) {
cout << "MALE OR NOT TALL" << endl;
}
else {
cout << "ELSE" << endl;
}
}
int main()
{
response(true, true);
response(false, true);
response(false, false);
return 0;
}
the output is the following:
MALE AND TALL
Process returned -1073740940 (0xC0000374) execution time : 1.460 s
Press any key to continue.
Why isn't the output?:
MALE AND TALL
MALE OR NOT TALL
ELSE
A different forum post hinted at a global value not being reset. I don't really know what to make of that.
I would appreciate any help
void response(bool isMale, bool isTall){
if (isMale && isTall) {
cout << "MALE AND TALL" << endl;
}
else if (isMale || isTall ){
cout << "MALE OR NOT TALL" << endl;
}
else {
cout << "ELSE" << endl;
}
}
You need to change function return type "string" to "void".

Bool value returning false for some reason [duplicate]

This question already has answers here:
C++ printing boolean, what is displayed?
(2 answers)
Closed 3 years ago.
Sorry if this is obvious but I'm very new to c++, thanks in advance
#include <iostream>
bool conduct_it_support(bool on_off_attempt) {
std::cout << "Have you tried turning it off and on again? (true / false)\n";
std::cin >> on_off_attempt;
if(on_off_attempt == false) {
return false;
}
else {
return true;
}
return on_off_attempt;
}
int main() {
bool attempt;
conduct_it_support(attempt); {
std::cout << "so it was " << attempt << "?\n";
}
}
I excpect this to be either: "so it was true/false?"
Sorry if this is obvious but I'm very new to c++, thanks in advance
By default the stream class(s) will serialize bool as 0 or 1. They will also read 0 or 1 when de-serializing.
To make it print the string(s) true or false you need to use a stream modifier std::boolalpha to change the behavior of the stream to print (or read) the text version of boolean values.
See below:
#include <iostream>
#include <iomanip>
int main ()
{
bool a = false;
bool b = true;
std::cout << std::boolalpha << a << " : " << b << '\n';
std::cout << std::noboolalpha << a << " : " << b << '\n';
// If you want to read a bool as 0 or 1
bool check;
if (std::cin >> std::noboolalpha >> check) {
std::cout << "Read Worked: Got: " << check << "\n";
}
else
{
std::cout << "Read Failed\n";
}
// PS. If the above read failed.
// The next read will also fail as the stream is in a bad
// state. So make the above test work before using this code.
// If you want to read a bool as true or false
bool check;
if (std::cin >> std::boolalpha >> check) {
std::cout << "Read Worked: Got: " << check << "\n";
}
else
{
std::cout << "Read Failed\n";
}
}
This code is working fine:
bool conduct_it_support(bool init) {
bool on_off_attempt=init;
char selectVal[10] = "000000000";
std::cout << "Have you tried turning it off and on again? (true / false)\n";
std::cin >> selectVal;
if(selectVal == "false") {
on_off_attempt=false;
}
else {
on_off_attempt=true;
}
return on_off_attempt;
}
int main()
{
bool attempt;
attempt = conduct_it_support(attempt); {
std::cout << "so it was " << attempt << "?\n";
}
Try this code here.

FASTA reader written in C++?

Let me start off by stating that I am a beginner in C++. Anyways, the FASTA format goes as follows:
Any line starting with a '>' indicates the name/id of the gene sequence right below it. There is a gene sequence right below the id. This gene sequence can be 1 or multiple lines.
So... what I want to do is print: id << " : " << gene_sequence << endl;
Here is my code:
#include <iostream>
#include <fstream>
int main(int argc, char **argv) {
if (argc < 2) {
std::cerr << " Wrong format: " << argv[0] << " [infile] " << std::endl;
return -1;
}
std::ifstream input(argv[1]);
if (!input.good()) {
std::cerr << "Error opening: " << argv[1] << " . You have failed." << std::endl;
return -1;
}
std::string line, id, DNA_sequence;
while (std::getline(input, line).good()) {
if (line[0] == '>') {
id = line.substr(1);
std::cout << id << " : " << DNA_sequence << std::endl;
DNA_sequence.clear();
}
else if (line[0] != '>'){
DNA_sequence += line;
}
}
}
For the second argument inputted into the command line, here is the content of my file:
>DNA_1
GATTACA
>DNA_2
TAGACCA
TAGACCA
>DNA_3
ATAC
>DNA_4
AT
Please copy and paste into text file.
After this has been done, and the code has been executed, I want to point out the problem. The code skips inputting the sequence of DNA_1 into its correct respective place, and instead placing DNA_1 's sequence into DNA_2. The results get pushed forward 1 as a result. Any assistance or tips would be greatly appreciated?
As I've said before, I am new to C++. And the semantics are quite hard to learn compared to Python.
I see a few problems with your code.
First you loop on std::ifstream::good() which doesn't work because it won't allow for End Of File (which happens even after a good read).
Then you access line[0] without checking if the line is empty which could cause a seg-fault.
Next you output the "previous line" before you have even collected it.
Finally you don't output the final line because the loop terminates when it doesn't find another >.
I added comments to my corrections to your code:
#include <iostream>
#include <fstream>
int main(int argc, char **argv) {
if (argc < 2) {
std::cerr << " Wrong format: " << argv[0] << " [infile] " << std::endl;
return -1;
}
std::ifstream input(argv[1]);
if (!input.good()) {
std::cerr << "Error opening: " << argv[1] << " . You have failed." << std::endl;
return -1;
}
std::string line, id, DNA_sequence;
// Don't loop on good(), it doesn't allow for EOF!!
// while (std::getline(input, line).good()) {
while (std::getline(input, line)) {
// line may be empty so you *must* ignore blank lines
// or you have a crash waiting to happen with line[0]
if(line.empty())
continue;
if (line[0] == '>') {
// output previous line before overwriting id
// but ONLY if id actually contains something
if(!id.empty())
std::cout << id << " : " << DNA_sequence << std::endl;
id = line.substr(1);
DNA_sequence.clear();
}
else {// if (line[0] != '>'){ // not needed because implicit
DNA_sequence += line;
}
}
// output final entry
// but ONLY if id actually contains something
if(!id.empty())
std::cout << id << " : " << DNA_sequence << std::endl;
}
Output:
DNA_1 : GATTACA
DNA_2 : TAGACCATAGACCA
DNA_3 : ATAC
DNA_4 : AT
You're storing the new id before printing the old one:
id = line.substr(1);
std::cout << id << " : " << DNA_sequence << std::endl;
Swap the lines around for proper order. You probably also want to check if you have any id already present to skip the first entry.
working implementation is here
https://rosettacode.org/wiki/FASTA_format#C.2B.2B
only corrected
while( std::getline( input, line ).good() ){
to
while( std::getline( input, line ) ){
Code
#include <iostream>
#include <fstream>
int main( int argc, char **argv ){
if( argc <= 1 ){
std::cerr << "Usage: "<<argv[0]<<" [infile]" << std::endl;
return -1;
}
std::ifstream input(argv[1]);
if(!input.good()){
std::cerr << "Error opening '"<<argv[1]<<"'. Bailing out." << std::endl;
return -1;
}
std::string line, name, content;
while( std::getline( input, line ) ){
if( line.empty() || line[0] == '>' ){ // Identifier marker
if( !name.empty() ){ // Print out what we read from the last entry
std::cout << name << " : " << content << std::endl;
name.clear();
}
if( !line.empty() ){
name = line.substr(1);
}
content.clear();
} else if( !name.empty() ){
if( line.find(' ') != std::string::npos ){ // Invalid sequence--no spaces allowed
name.clear();
content.clear();
} else {
content += line;
}
}
}
if( !name.empty() ){ // Print out what we read from the last entry
std::cout << name << " : " << content << std::endl;
}
return 0;
}
input:
>Rosetta_Example_1
THERECANBENOSPACE
>Rosetta_Example_2
THERECANBESEVERAL
LINESBUTTHEYALLMUST
BECONCATENATED
output:
Rosetta_Example_1 : THERECANBENOSPACE
Rosetta_Example_2 : THERECANBESEVERALLINESBUTTHEYALLMUSTBECONCATENATED

Issue regarding size_t

If you go in my post history you'll see that i'm trying to develop an interpreter for a language that i'm working on. I want to use size_t using two different codes, but they all return nothing.
Here is the post of what i was trying: http://stackoverflow.com/questions/1215688/read-something-after-a-word-in-c
When i try to use the file that i'm testing it returns me nothing. Here is the sample file(only a print function that i'm trying to develop in my language):
print "This is a print function that i'm trying to develop in my language"
But remember that this is like print in Python, what the user type into the quotes(" ") is what have to be printed to all, remember that the user can choose what put into the quotes, then don't put something like a simple cout, post something that reads what is inside the quotes and print it to all. But here is the two test codes to do this, but all of they don't returns nothing to me:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
int main( int argc, char* argv[] )
{
// Error Messages
string extension = argv[ 1 ];
if(argc != 2)
{
cout << "Error syntax is incorrect!\nSyntax: " << argv[ 0 ] << " <file>\n";
return 0;
}
if(extension[extension.length()-3] != '.')
{
cout << "Extension not valid!" << endl;
cout << "Default extension *.tr" << endl;
return 0;
}
if(extension[extension.length()-2] != 't')
{
cout << "Extension not valid!" << endl;
cout << "Default extension *.tr" << endl;
return 0;
}
if(extension[extension.length()-1] != 'r')
{
cout << "Extension not valid!" << endl;
cout << "Default extension *.tr" << endl;
return 0;
}
// End of the error messages
ifstream file(argv[ 1 ]);
if (!file.good()) {
cout << "File " << argv[1] << " does not exist.\n";
return 0;
}
string linha;
while (!file.eof())
{
getline(file, linha);
if (linha == "print")
{
size_t idx = linha.find("\""); //find the first quote on the line
while ( idx != string::npos ) {
size_t idx_end = linha.find("\"",idx+1); //end of quote
string quotes;
quotes.assign(linha,idx,idx_end-idx+1);
// do not print the start and end " strings
cout << "quotes:" << quotes.substr(1,quotes.length()-2) << endl;
//check for another quote on the same line
idx = linha.find("\"",idx_end+1);
}
}
}
return 0;
}
The second:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
int main( int argc, char* argv[] )
{
// Error Messages
string extension = argv[ 1 ];
if(argc != 2)
{
cout << "Error syntax is incorrect!\nSyntax: " << argv[ 0 ] << " <file>\n";
return 0;
}
if(extension[extension.length()-3] != '.')
{
cout << "Extension not valid!" << endl;
cout << "Default extension *.tr" << endl;
return 0;
}
if(extension[extension.length()-2] != 't')
{
cout << "Extension not valid!" << endl;
cout << "Default extension *.tr" << endl;
return 0;
}
if(extension[extension.length()-1] != 'r')
{
cout << "Extension not valid!" << endl;
cout << "Default extension *.tr" << endl;
return 0;
}
// End of the error messages
ifstream file(argv[ 1 ]);
if (!file.good()) {
cout << "File " << argv[1] << " does not exist.\n";
return 0;
}
string linha;
while (!file.eof())
{
getline(file, linha);
if (linha == "print")
{
string code = " print \" hi \" ";
size_t beg = code.find("\"");
size_t end = code.find("\"", beg+1);
// end-beg-1 = the length of the string between ""
cout << code.substr(beg+1, end-beg-1);
}
}
return 0;
}
And here is what is printed in the console:
ubuntu#ubuntu-laptop:~/Desktop/Tree$ ./tree test.tr
ubuntu#ubuntu-laptop:~/Desktop/Tree$
Like i said, it prints me nothing.
See my post in D.I.C.: http://www.dreamincode.net/forums/showtopic118026.htm
Thanks,
Nathan Paulino Campos
Your problem is the line
if (linha == "print")
which assumes the entire line just read in is "print", not that the line STARTS with print.
Also, why would you use 3 separate checks for a .tr extension, vs. just checking the end of the filename for ".tr"? (You should also be checking that argv[1] is long enough before checking substrings...)
getline(file, linha) will read an entire line from the file, so linha never be equal to print.