This question already has answers here:
Why can't the switch statement be applied to strings?
(22 answers)
Closed 3 years ago.
I'm working on a small project on Dev-C++. I'm trying to make a bot to ask you some questions, but I can't use the switch statetments with the strings. Every time I try to do so it shows error! I also tried to change the srings to normal int variables but when I the code runs all at once after answering the first question! Does anyone knows how to fix any of these situations?
Here is my code:
// #include "stdafx";
#include <iostream>
#include <string>
#include <stdio.h>
#include <string.h>
using namespace std;
int main()
{
string comida;
string nome;
string idade;
string pais;
cout << "Ola, o meu nome e Aleksandar. Qual e o teu nome?" << endl; //Ask for nome
cin >> nome; //Recieve variable nome
cout << "Es de que pais, " << nome << "?" << endl; //Ask for pais
cin >> pais; //Receive pais
cout << pais << " e um pais bonito. " << "Eu sou de Portugal!" << endl;
cout << "Quantos anos tens " << nome << "?" << endl; //Ask for idade
cin >> idade; //Receive variable idade
switch (idade) {
case 21:
cout << "O meu irmao tambem tem 21 anos!" << endl;
break;
}
cout << "Eu tenho 28" << endl;
cout << "Qual e a tua comida preferida?" << endl; //Ask for comida
cin >> comida; //Receive variable comida
cout << "Tambem gosto muito de " << comida << ". Mas gosto mesmo e de Vatruchka!" << endl;
cout << "Xau " << nome << "!" << endl;
}
If the string contains a number, switch(std::stoi(idade)) will work. But that doesn't work if idade contains something else.
A switch will not compile when non-intergal (i.e. string, float, bool, vector, etc...) data-types are assigned to the switch's case: statements. Furthermore, its necessary that the values assigned to the case: statements are const.
In other words:
Switches must use "constant integral data-types" (i.e. 'enum', 'int', 'char', etc...), and cannot implament strings as conditional statements, however; that is not the same as saying that strings cannot be used in a conditional statement, they very much can be & often are — see the example below:
std::string s;
std::cin >> s;
if (s == "Yes")
{
std::cout << "You said yes!" << std::endl;
}
else if (s == "No")
{
std::cout << "You said no?" << std::endl;
}
else
{
std::cout << "You said something I don't understand" << std::endl;
}
So to finish this answer, you can see that you can achieve the same thing you could with a switch statement using if/else blocks. It may, or it may not, be ideal for your situation, but this is how C++, and switch statements work, so your stuck with it — like it, or not...
You can't use strings — switch only works for integral case types (i.e. integers and enums).
You could use something like this, instead:
if (idade == "21") { cout << "...\n"; }
else if (idade == "something else") { cout << "...\n"; }
You describe that the code runs all at once when you change to using integers. It's possible you're forgetting to include break in each case clause.
If you have a set of different strings that you are expecting then you can set up an enum and a map (I use the word map loosely here - I don't mean the actual map in C++, although I know it is possible to do something similar with it)
Use this to turn the input into an enum and then you can run a switch on the enum
E.g.
enum class ANSWER
{
ANSWER_1,
ANSWER_2
};
class AnswerMap \\set up this class like a singleton
{
std::vector<std::pair<std::string, ANSWER>> _answer_map = {
std::make_pair("Answer 1 string", ANSWER::ANSWER_1),
std::make_pair("Answer 2 string", ANSWER::ANSWER_2)
}
std::string String(ANSWER answer); \\have this function loop through this->_answer_map until finding the pair with the second item as the given enum and return the corresponding string
ANSWER Enum(std::string answer); \\have this function do the same as this->String but find the pair where the string matches and then return the corresponding enum
}
Related
I'm trying to learn C++ to help my sibling with their assignment. So I'm attempting the assignment. It's a simple program to load a dictionary test file with words, their type, and definition to an array of Word type objects. I was able to get started with a normal string array instead of an object array as requested. But as soon as I defined the Word class and the array the code builds without an issue. When I try to run the code the cursor simply blinks for a few seconds and returns to the normal terminal.
Am I doing something wrong with my Class constructor ??
#include <fstream>
#include <string>
using namespace std;
class Word {
public:
string WordEntry;
string Type;
string Definition;
//constructor
Word(string word, string type, string definition){
WordEntry=word;
Type=type;
Definition=definition;
}
};
int main(){
cout << "Test1";
Word *wordArray[318555];
int count=0;
string word, type, definition,blank;
cout << "TEST" << count << "\n";
ifstream file("dictionary2021 (1).txt");
if (file.is_open()){
cout << "File dictionary2021.txt has been opened \n";
while (!file.eof()){
getline(file,word);
getline(file,type);
getline(file,definition);
getline(file,blank);
wordArray[count]= new Word(word,type,definition);
count++;
}
file.close();
cout << "File dictionary2021.txt has " << count/3 << " entries\n";
}
cout << "TEST" << count << endl;
cout << cc;
int selection;
string input;
cout << "Function List - Please hit Enter after your selection \n";
cout << " 1. Word Search \n 2. Repetitive z search \n 3. Wild Card Search\n";
cout << "Selection:";
cin >> selection;
if(selection=1){
cout << "Enter word:\n";
cin >> input;
string str("a");
for (int i = 0; i < 12; i+3)
{
cout << "1";
if (input.compare(str)== 0)
{
cout << wordArray[i+1];
return 0;
}
cout << "2";
}
}
}```
Word* wordArray[318555]; is a huge value and we're talking about 2548440 bytes (or roughly 2.4MB). This might be too large for a single stack frame and can easily be inefficient.
What I suggest is to use std::vector to store the word array and use std::vector<>::push_back() method to insert data to it.
Note: In your code snippet your not deallocating the Word object pointers once everything is done. Either explicitly delete those pointers using delete or use a smart pointer like std::unique_ptr.
I'm trying to write in C++ a function (leggiInteroEstrIncl) that prompts the user to type by keyboard an integer number included in a given range (between minimo and massimo).
Following is the function I wrote and then a statement, in the main(), to invoke it:
#include <iostream>
using namespace std;
int leggiInteroEstrIncl(string stringaDaStampare, int minimo, int massimo) {
int numInserito = 0;
bool errore = false;
do {
errore = false;
cout << stringaDaStampare << " (un numero intero compreso tra " << minimo
<< " e " << massimo << " estremi inclusi): ";
try {
cin >> numInserito;
} catch (...) {
errore = true;
cout << "Hai inserito un numero non valido, prova ancora" << endl;
}
if (errore == false && (numInserito < minimo || numInserito > massimo)) {
errore = true;
cout << "Hai inserito un numero al di fuori dell'intervallo richiesto: "
<< minimo << " <-> " << massimo << endl;
}
} while (errore);
return numInserito;
}
int main() {
int number = 0;
number = leggiInteroEstrIncl(
"Inserire la cifra in Yen da ripartire in banconote e monete", 1, 30000);
system("pause");
return 0;
}
If I type a valid integer number which is not included in the specified range, this piece of software works and asks the user to type again, but if I type something which is not a number, for example the word "hello", this software goes in a sort of loop and doesn't stop to ask the user to type again.
Could you please tell me what is wrong with it?
Thank you
You can use std::string to get input:
string insertio;
cin >> inserito;
and then use one of this function:
http://en.cppreference.com/w/cpp/string/basic_string/stol
which throws proper exception if there isn't a number in string.
If you need to check more solutions, check this one:
How to determine if a string is a number with C++?
This
cin >> numInserito;
attempts to read in a number and nothing else.
It will succeed with a number, as you have observed.
With a non-number it will fail, but not in a way to trigger the catch part.
It will instead just not read anything in and especially it will leave the non-number in the input stream.
If you then continue trying to read in a number, it will continue failing.
When reading in a number fails you need to read in whatever there is and probably ignore it.
In order to ignore the non-number, read it in as a string and do nothing with it
(as described in the answer by BartekPL):
string insertio;
cin >> inserito;
Im very new to c++ and trying to write a simple game to learn some of the basic mechanics and i'm having trouble with my code,
How do I define the function WantToPlay so that when a player enters "yes" it replies fantastic, and "no" replies boooo?
My current code gives the error that WantToPlay must be of bool type, but i'm not sure how to use a boolean function to rectify it?
Thanks!
using std::cout;
using std::cin;
using std::endl;
using std::string;
string leader;
string WantToPlay;
int main()
{
std::cout << "Dungeon Master: Welcome to my dungeon, traveller! What is your name?" << std::endl;
cin >> leader;
cout << "Dungeon Master: Well hello, " << leader << " I have a little quest for you if you're interested?" << endl;
cout << "(Please enter ""yes"" or ""no"")" << endl;
cin >> WantToPlay;
if (WantToPlay = "yes")
cout << "Fantastic!" << endl;
else if (WantToPlay = "no")
cout << "boooo" << endl;
return 0;
}
you need use the o̶p̶e̶r̶a̶t̶o̶r̶ c̶o̶m̶p̶a̶r̶a̶t̶o̶r̶ equality operator. "=="
What you are doing is assigning, not comparing.
(WantToPlay = "Yes") means assigning the string value "Yes" to the string variable WantToPlay
Since you are comparing the value of the variable with "Yes", you should use "==", because (WantToPlay == "Yes") means the string value "Yes" is the same as the value in string variable WantToPlay.
Did you know the difference between "=" and "==" ? Check your if statement, and correct it.
Tip: you can't use assignment in if condition.
I am in the process of making a chat bot and i am just experimenting at this point. but my "if" commands are not working and when i enter "moodToday" it just skips right to the else command.
(capitalization of "moodToday" is not the error)
any and all help would be appreciated
#include <fstream>
#include <cmath>
using namespace std;
int main() {
char name[50], moodToday[50];
cout << "A few things you should know at this time..." << endl << "1. I can't process last names." << endl << "2. I can't process acronyms." << endl;
system("pause");
cout << endl << endl << "What is your name?" << endl;
cin >> name;
cout << "Hello " << name << "." << endl << "How are you today?" << endl;
cin >> moodToday;
//can't figure this out...
if ((moodToday == "sad") || (moodToday == "bad") || (moodToday == "horrible")) {
cout << "That's not good." << endl << "Why are you feeling " << moodToday << "today?" << endl;
}
else if (moodToday == "good") {
cout << "Great!" << endl;
}
else {
cout << "I'm sorry, I don't undrestand that feeling." << endl;
}
system("pause");
return 0;
}
To compare character arrays that contain strings you should use standard C functions like std::strcmp declared in header <cstring>. For example
#include <cstring>
//...
if ( std::strcmp( moodToday, "sad" ) == 0 ) std::cout << "They are equal << std::endl;
Otherwise in statements like this
if ((moodToday == "sad") ) /*...*/
there are compared two pointers: the pointer to the first character of the array moodToday and the pointer to the first character of the string literal "sad" because arrays used in expressions with rare exceptions are converted to pointers to their first characters.
Take into account that the usage of the operator >> with character arrays is unsafe
cin >> moodToday;
Use instead member function getline like this
cin.getline( moodToday, sizeof( moodToday ) );
Or instead of the character arrays you could use standard class std::string.
Consider a ppossibility to convert all letters of the entered string to the case of the string literal before comparing them. You can do this using standard C functions tolower and toupper declared in header <cctype>.
If you're doing C++, then you should be using std::string and not the old C-style buffers.
#include <string>
int main() {
std::string name, moodToday;
}
C++ strings are significantly better than C strings since they don't have buffer overflow problems and are easily compared with ==.
Also, as a tip, try to avoid using namespace std; since that can cause namespace conflicts. As annoying as it can be to type std:: all the time it does make it clear where that class or template originated from and who's responsible for it code-wise. That way your own classes and templates are obvious.
Use strcmp instead of == operators.
If you defined moodToday as a string object, then == would work.
Similar to problems in java with comparing object addresses what you are doing is comparing memory addresses. Thus you want to use strcmp(str1, "literal")==0 to see if they are equal.
#import <cstring>
if(strcmp(str1, "literal") == 0) dothis();
I'm new to C++. I decided to not watch the next tutorial and put my skills to use, by making a funny Mind Reader application. I'm pleased with myself, however, even though I've ironed out most bugs, I still have one concerning the exit function. I read the C++ documentation for it, and I'm not sure what I did wrong. I did exit(0);. I have a very weird error, which is:
no match for call to '(std::string {aka std::basic_string<char>}) (int)
I have searched online, however I am still unaware of what the problem is. My error is on line 59 (marked in the code):
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
//declaring variables to be used later
string name;
string country;
int age;
//header goes below
cout << "#######################################";
" ############ MIND READER ############"
"#######################################\n\n";
//asks if the user would like to continue and in not, terminates
cout << "Would like you to have your mind read? Enter y for yes and n for no." << endl;
cout << "If you do not choose to proceed, this program will terminate." << endl;
string exitOrNot;
//receives user's input
cin >> exitOrNot;
//deals with input if it is 'y'
if (exitOrNot == "y"){
cout << "Okay, first you will need to sync your mind with this program. You will have to answer the following questions to synchronise.\n\n";
//asks questions
cout << "Firstly, please enter your full name, with correct capitalisation:\n\n";
cin >> name;
cout << "Now please enter the country you are in at the moment:\n\n";
cin >> country;
cout << "This will be the final question; please provide your age:\n\n";
cin >> age;
//asks the user to start the sync
cout << "There is enough information to start synchronisation. Enter p to start the sync...\n\n";
string proceed;
cin >> proceed;
//checks to see if to proceed and does so
if (proceed == "p"){
//provides results of mind read
cout << "Sync complete." << endl;
cout << "Your mind has been synced and read.\n\n";
cout << "However, due to too much interference, only limited data was aquired from your mind." << endl;
cout << "Here is what was read from your mind:\n\n";
//puts variables in sentence
cout << "Your name is " << name << " and you are " << age << " years old. You are based in " << country << "." << endl << "\n\n";
cout << "Thanks for using Mind Reader, have a nice day. Enter e to exit." << endl;
//terminates the program the program
string exit;
cin >> exit;
if (exit == "e"){
exit(0); // <------------- LINE 59
}
}
}
//terminates the program if the input is 'n'
if (exitOrNot == "n"){
exit(0);
}
return 0;
}
Thanks
The local variable exit shadows other identifiers from outer scopes with the same name.
To illustrate with a smaller example:
int main()
{
int i;
{
int i;
i = 0; // assign to the "nearest" i
// the other i cannot be reached from this scope
}
}
Since the only exit visible is an object of type std::string, the compiler sees exit(0) as a call to operator()(int) and throws a hissy fit when it doesn't find one among std::string members.
You can either qualify the name (std::exit(0);) or rename the variable. And since all of your code is in main you can simply say return 0; instead.
Try using return 0; or return EXIT_SUCCESS;. It's the exact same thing. Also, you can only input one word into a cin. Instead, use getline(cin, string name); If it still doesn't work, add a cin.ignore(); before your getline(cin, string name);, like this:
//stuff
string country;
cout << "Now please enter the country you are in at the moment:\n\n";
cin.ignore();
getline(cin, country);
//stuff
return 0;
The problem is arrising because you declared a standard keyword as the name of a local variable.
Now as the local variable is of type sting it is not able to take it as its value.