I have some code that detects which tab is selected in a QListWidget
int currentTab=ui->tabWidget->currentIndex();
if (currentTab==0)
{
// Code here
}
else if (currentTab==1)
{
// Code here
}
else if (currentTab==2)
{
// code here
}
else if (currentTab==3)
{
// code here
}
How do i use Enums instead of if(currentTab==0) or if(currentTab==1) or if(currentTab==2) or if(currentTab==3)
I would handle the same in the following way (with using an enum type):
enum Tabs {
Tab1,
Tab2,
Tab3
};
void foo()
{
int currentTab = ui->tabWidget->currentIndex();
switch (currentTab) {
case Tab1:
// Handle the case
break;
case Tab2:
// Handle the case
break;
case Tab3:
// Handle the case
break;
default:
// Handle all the rest cases.
break;
}
}
Example to use the Enums given below.
if you want to use same enum element in two enumerations, then you can use the enum classes (strongly typed enumerations) C++11.
#include <iostream>
#include <cstdint>
using namespace std;
//enumeration with type and size
enum class employee_tab : std::int8_t {
first=0 /*default*/, second, third, last /*last tab*/
};
enum class employee_test : std::int16_t {
first=10 /*start value*/, second, third, last /*last tab*/
};
enum class employee_name : char {
first='F', middle='M', last='L'
};
int main(int argc, char** argv) {
//int currentTab=ui->tabWidget->currentIndex();
employee_tab currentTab = (employee_tab)1;
switch (currentTab) {
case employee_tab::first: //element with same name
cout << "First tab Selected" << endl;
break;
case employee_tab::second:
cout << "Second tab Selected" << endl;
break;
case employee_tab::third:
cout << "Third tab Selected" << endl;
break;
case employee_tab::last: //element with same name
cout << "Fourth tab Selected" << endl;
break;
}
employee_name currentName = (employee_name)'F';
switch (currentName) {
case employee_name::first: //element with same name
cout << "First Name Selected" << endl;
break;
case employee_name::middle:
cout << "Middle Name Selected" << endl;
break;
case employee_name::last: //element with same name
cout << "Last Name Selected" << endl;
break;
}
return 0;
}
output:
Second tab Selected
First Name Selected
Related
I am having some trouble using a switch statement with user input. Can anyone please explain what is going on? I am sorry if this is a noob question as I'm very used to Python and just started learning C++.
#include <iostream>
#include <string>
using namespace std;
#include <cstdlib>
int main()
{
string name;
cout << "Enter a name: ";
cin >> name;
switch (name){
case name == "Seth":
std::cout << "That's my name!";
return 0;
break;
case name == "seth":
std::cout << "Wow, you couldnt even put correct capitalization on my name...\n";
std::cout << "LEARN YOUR PRONOUNS AND GO BACK TO SCHOOL!";
return 0;
break;
case name == "SETH":
std::cout << "Ok ok you spelled my name right but make sure you turn off caps lock please";
return 0;
break;
default:
std::cout << "Come on get my name RIGHT!!!\n";
std::cout << "But you entered " << name;
}
return 0;
}
According to the C++ 17 Standard (9.4.2 The switch statement)
2 The condition shall be of integral type, enumeration type, or class
type. If of class type, the condition is contextually implicitly
converted (Clause 7) to an integral or enumeration type. If the
(possibly converted) type is subject to integral promotions (7.6), the
condition is converted to the promoted type. Any statement within the
switch statement can be labeled with one or more case labels as
follows: case constant-expression : where the constant-expression
shall be a converted constant expression (8.20) of the adjusted type
of the switch condition. No two of the case constants in the same
switch shall have the same value after conversion.
The class std::string does not have an implicit conversion operator that converts an object of the type std::string to an integral or enumeration type.
So the expression in this switch statement
switch (name){
is invalid.
Also case labels like this
case name == "seth":
are syntactically incorrect.
You could resolve your problem with the switch statement for example the following way
#include <iostream>
#include <string>
#include <array>
#include <iterator>
#include <algorithm>
int main()
{
std::array<const char *, 3> names =
{
"Seth", "seth", "SETH"
};
std::string name;
std::cout << "Enter a name: ";
std::cin >> name;
size_t n = std::find( std::begin( names ), std::end( names ), name ) -
std::begin( names );
switch (n)
{
case 0:
std::cout << "That's my name!";
break;
case 1:
std::cout << "Wow, you couldnt even put correct capitalization on my name...\n";
std::cout << "LEARN YOUR PRONOUNS AND GO BACK TO SCHOOL!";
break;
case 2:
std::cout << "Ok ok you spelled my name right but make sure you turn off caps lock please";
break;
default:
std::cout << "Come on get my name RIGHT!!!\n";
std::cout << "But you entered " << name;
break;
}
}
#include <iostream>
#include <string>
int main()
{
std::string name;
std::cout << "Enter a name: ";
std::cin >> name;
if(name == "Seth")
{
std::cout << "That's my name!" << std::endl;
}
else if(name == "seth")
{
std::cout << "Wow, you couldn't even put correct capitalization on my name..." << std::endl;
std::cout << "LEARN YOUR PRONOUNS AND GO BACK TO SCHOOL!" << std::endl;
}
else if(name == "SETH")
{
std::cout << "Ok ok you spelled my name right but make sure you turn off caps lock please" << std::endl;
}
else
{
std::cout << "Come on get my name RIGHT!!!" << std::endl;
std::cout << "But you entered " << name << std::endl;
}
return 0;
}
As other people have told that you can not do string comparison in switch and provided a solution. But I would like to use enum class which I found more readable and int comparison much more faster than string comparison.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <unordered_map>
int main() {
enum class Spellings { Seth, seth, SETH };
const std::unordered_map<std::string, Spellings> spellings_map{
{"Seth", Spellings::Seth},
{"seth", Spellings::seth},
{"Seth", Spellings::SETH},
};
std::string name;
std::cout << "Enter a name: ";
std::cin >> name;
auto result = spellings_map.find(name);
if (result == spellings_map.end()) {
std::cout << "Come on get my name RIGHT!!!\n";
std::cout << "But you entered " << name;
return -1;
}
switch (result->second) {
case Spellings::Seth:
std::cout << "That's my name!";
break;
case Spellings::seth:
std::cout << "Wow, you couldnt even put correct capitalization on "
"my name...\n";
std::cout << "LEARN YOUR PRONOUNS AND GO BACK TO SCHOOL!";
break;
case Spellings::SETH:
std::cout << "Ok ok you spelled my name right but make sure you "
"turn off caps lock please";
break;
}
}
I have 3 files: one with stack define by class in stack.h, second with stack's functions in stack.cpp, and last one is main.cpp. In main(), I have a switch for an interactive menu:
#include <iostream>
#include "Stack.h"
int main() {
stack s; //for calling functions from stack.cpp
char choise;
menu:
system("cls");
std::cout << "a => create stack\n" << "b => read data to stack\n" << "c => show data in stack\n" << std::endl; //so it looks like that somehow
switch(choise) {
case 'a':
s.stack(); // function in stack.cpp
std::cout << "Stack was created" << std::endl;
goto menu;
case 'b':
s.getdata(); //function in stack.cpp
goto menu;
case 'c':
s.display();
goto menu;
}
// and another...
The problem is when I'm calling, for example, 'b', the program is like skipping it and doesn't call the function from stack.cpp. So I can't write or make any other case.
Maybe you are missing "break;" in end of each case block?
Try with
do
{
system("cls");
std::cout << "a => create stack\n" << "b => read data to
stack\n" << "c => show data in stack\n" << std::endl; //so it
lookss like that somehow
std::cin >> choise //As Adrian said
switch(choise) {
case 'a':
s.stack(); // function in stack.cpp
std::cout << "Stack was created" << std::endl;
break;
case 'b':
s.getdata(); //function in stack.cpp
break;
case 'c':
s.display();
break;
}
// and another...
}while(1);
I am trying to make a text based C++ game.
I have a player class set up and I am now working on a method inside that class called displayMenu(), which will ask the user a variety of questions based on their player and send the data to the main/client code and then that data will create an object of player class via a constructor of player class.
My main question is...
I am trying to compare the input (string) from the user to the (string) they need to inputting, but I am getting an error which says "lower()" can not be resolved. I believe you have to compare each character, but I think there may be a more effective way to code this to provide simplicity and readability. What exactly am I doing wrong? What is the best way to code this?
Here is my code...
void Player::displayMenu(std::string& PlaName, std::string& cName, int& lvl, int& HP)
{
std::cout << "Player Creation Menu" << std::endl;
std::cout << "====================" << std::endl;
std::cout << std::endl;
std::cout << std::endl;
std::cout << "What is your name? " << std::endl;
std::cin >> PlaName;
std::cout << "What is your specitality? " << std::endl;
std::cin >> cName;
while(cName.lower() != "brawler" || cName.lower() != "thief" || cName.lower() != "persuader" || cName.lower()
!= "gunman")
{
std::cout << "That is not your true specitality..." << std::endl;
std::cout << "You must pick from { 'Brawler', 'Thief' , 'Persuader', 'Gunman' }" << std::endl;
std::cin >> cName;
}
}
I have several remarks on your original code:
Reading and comparing the strings seems like a bit complicated for this use-case. It is common to see usage of first character as identifier, to make it simpler.
The specialty is a classic example for enum (or enum class, which is enum that you must use always with it's name)
The displayMenu method should not be part of the Player class, since it isn't a behavior (an action) of the player. It should be part of the "Game"/"UI" class.
If you really want to use the complete string in order to identify the specialty, you can use the code examples in the first answer in the link Ayxan put in the comments.
Here is my proposed code:
#include <iostream>
constexpr char INVALID_CHARACTER_INPUT = '#';
enum class CharacterSpecialty
{
BRAWLER,
THIEF,
PERSUADER,
GUNMAN,
NUM_OF_SPECIALITY_TYPES
};
`
class Player
{
public:
Player(const std::string& player_name, CharacterSpecialty char_specialty) :
name(player_name),
specialty(char_specialty)
{
}
private:
std::string name;
CharacterSpecialty specialty;
};
Player displayMenuAndCreatePlayer()
{
std::cout << "\nPlayer Creation Menu\n" << "====================\n\n" << std::endl;
std::cout << "Enter your name: " << std::endl;
std::string player_name{};
std::cin >> player_name;
CharacterSpecialty char_specialty = CharacterSpecialty::NUM_OF_SPECIALITY_TYPES;
while(char_specialty == CharacterSpecialty::NUM_OF_SPECIALITY_TYPES)
{
std::cout << "What is your specialty?\n" << "[B]rawler, [T]hief, [P]ersuader or [G]unman"<< std::endl;
std::string char_type_input;
std::cin >> char_type_input;
char input = char_type_input.size() == 1 ? char_type_input[0] : INVALID_CHARACTER_INPUT;
switch(char_type_input)
{
case 'b':
case 'B':
char_specialty = CharacterSpecialty::BRAWLER;
break;
case 't':
case 'T':
char_specialty = CharacterSpecialty::THIEF;
break;
case 'p':
case 'P':
char_specialty = CharacterSpecialty::PERSUADER;
break;
case 'g':
case 'G':
char_specialty = CharacterSpecialty::GUNMAN;
break;
default:
std::cout << "Invalid Specialty Entered!\n" << std::endl;
break;
}
}
return Player(player_name, char_specialty);
}
int main()
{
Player player = displayMenuAndCreatePlayer();
}
I'm creating a board game (stratego) in c++ and was wondering if it considered a poor practice to return an integer from a class method in order to determine which case in a switch statement to show to the user.
Example:
In stratego, you can't attack board pieces that are part of your own army so I have a message "You cannot attack your own army" when the user tries to do so.
Same thing if a movement is performed that would result in the player jumping off the board, moving too many spaces, etc.
Each of these invalid movements has it's own unique message, but to avoid printing them from the Class.cpp file, which is where the player's moves are validated, I have the Class.cpp file returning an integer to a switch statement in the main() that it was called from.
What is the most recommended way to handle how the messages get called?
class Test
{
public:
Test()
{
}
int Validate_Move(int valid)
{
if (valid > 0 && valid < 5)
{
return 1;
}
else if (valid > 5)
{
return 2;
}
}
};
int main()
{
int entry;
std::cout << "Enter move: ";
std::cin >> entry;
Test obj;
switch (obj.Validate_Move(entry))
{
case 1:
std::cout << "Move is valid" << std::endl;
case 2:
std::cout << "Move is invalid" << std::endl;
default:
std::cout << "Error occured" << std::endl;
}
return 0;
}
There's nothing wrong with that technique. If you want to be more explicit, you could always make an enum
class Test
{
public:
Test() = default;
enum EValidity {eError, eValid, eInvalid};
EValidity Validate_Move(int valid)
{
if (valid > 0 && valid < 5)
{
return eValid;
}
else if (valid > 5)
{
return eInvalid;
}
else
{
return eError;
}
}
};
int main()
{
int entry;
std::cout << "Enter move: ";
std::cin >> entry;
Test obj;
switch (obj.Validate_Move(entry))
{
case Test::eValid:
std::cout << "Move is valid" << std::endl;
break;
case Test::eInvalid:
std::cout << "Move is invalid" << std::endl;
break;
case Test::eError:
std::cout << "Error occured" << std::endl;
break;
default:
assert(false);
}
return 0;
}
I am trying to create a library management system. I am getting a few errors which I don't understand. I am using Eclipse in Mac os.
My main code is:
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>
#include "Library.h" // include header of Library class
#include "Game.h" // include header of Game class
#include "DVD.h" // include header of DVD class
#include "Book.h" // include header of Book class
using namespace std;
void Library::insertGame( char gameName[], char platform[], int c){
strcpy( collection[numGames].name, gameName);
strcpy( collection[numGames].platform, platform);
collection[numGames].copies = c;
cout << "Game added to collection.\n";
++numGames;
}
void Library::deleteGame( char gameName[]){
int i;
for( i = 0; i < numGames; i++){
if( strcmp( gameName, collection[i].name) == 0){
collection[i].copies--;
cout << "Game deleted from collection.\n";
return;
}
}
cout << "Game not found.\n";
}
void Library::insertDVD( char dvdName[], char director[], int c){
strcpy( collection1[numDVDs].name, dvdName);
strcpy( collection1[numDVDs].director, director);
collection1[numDVDs].copies = c;
cout << "DVD added to collection.\n";
++numDVDs;
}
void Library::deleteDVD( char dvdName[]){
int i;
for( i = 0; i < numDVDs; i++){
if( strcmp( dvdName, collection1[i].name) == 0){
collection1[i].copies--;
cout << "DVD deleted from collection.\n";
return;
}
}
cout << "DVD not found.\n";
}
void Library::insertBook( char bookName[], char author[], int c){
strcpy( collection2[numBooks].name, bookName);
strcpy( collection2[numBooks].author, author);
collection2[numBooks].copies = c;
cout << "Book added to collection.\n";
++numBooks;
}
void Library::deleteBook( char bookName[]){
int i;
for( i = 0; i < numBooks; i++){
if( strcmp( bookName, collection2[i].name) == 0){
collection2[i].copies--;
cout << "Book deleted from collection.\n";
return;
}
}
cout << "Book not found.\n";
}
Game *Library::search( char gameName[]){
int i;
for( i = 0; i < numGames; i++){
if( strcmp( gameName, collection[i].name) == 0)
return &collection[i];
}
return NULL;
}
DVD *Library::search( char dvdName[]){
int i;
for( i = 0; i < numDVDs; i++){
if( strcmp( dvdName, collection1[i].name) == 0)
return &collection1[i];
}
return NULL;
}
Book *Library::search( char bookName[]){
int i;
for( i = 0; i < numBooks; i++){
if( strcmp( bookName, collection2[i].name) == 0)
return &collection2[i];
}
return NULL;
}
int main(){
Library lib;
while( 1 ){
char mainSelect;
char gameOption, name[30], platform[30], copies[10];
char dvdOption;
char bookOption;
// Ask the user to select an option
cout << "\nMain Menu:"<<endl;
cout << "D for DVDs"<<endl;
cout << "G for Games"<<endl;
cout << "B for Books"<<endl;
cout << "E to exit from the system"<<endl;
// Read user selection
cin.getline( name, 80);
mainSelect = name[0];
// Switch statement to select between the options
switch (mainSelect){
case 'd': case 'D':
break;
case 'g': case 'G':
break;
case 'b': case 'B':
break;
case 'e': case 'E':
exit(0);
break;
}
if (mainSelect == 'd','D'){
cout << "\nEnter your option:"<<endl;
cout << "A to add a new DVD"<<endl;
cout << "D to delete a DVD"<<endl;
cout << "S to search for a DVD"<<endl;
cout << "E to exit from the system"<<endl;
cin.getline( name, 80);
dvdOption = name[0];
switch (dvdOption){
case 'a': case 'A':
cout << "Enter Name of DVD: ";
cin.getline( name, 80);
cout << "Enter Director of DVD: ";
cin.getline(director, 80);
cout << "Enter no of copies: ";
cin.getline(copies, 80);
lib.insertDVD( name, director, atoi(copies));
break;
case 'd': case 'D':
cout << "Enter Name of DVD:\n";
cin.getline(name, 80);
lib.deleteDVD(name);
break;
case 's': case 'S':
cout << "Enter Name of DVD:\n";
cin.getline(name, 80);
Game *item;
item = lib.search( name );
if( item != NULL){
cout << "DVD found\n" << item->name << endl << item->platform << endl << item->copies << endl;
}
else
cout << "DVD not found\n";
break;
case 'e': case 'E':
exit(0);
break;
}
}
else if (mainSelect == 'g','G'){
cout << "\nEnter your option:"<<endl;
cout << "A to add a new game"<<endl;
cout << "D to delete a game"<<endl;
cout << "S to search for a game"<<endl;
cout << "E to exit from the system"<<endl;
cin.getline( name, 80);
gameOption = name[0];
switch (gameOption){
case 'a': case 'A':
cout << "Enter Name of Game: ";
cin.getline( name, 80);
cout << "Enter game platform: ";
cin.getline(platform, 80);
cout << "Enter no of copies: ";
cin.getline(copies, 80);
lib.insertGame( name, platform, atoi(copies));
break;
case 'd': case 'D':
cout << "Enter Name of Game:\n";
cin.getline(name, 80);
lib.deleteGame(name);
break;
case 's': case 'S':
cout << "Enter Name of Game:\n";
cin.getline(name, 80);
Game *item;
item = lib.search( name );
if( item != NULL){
cout << "Game found\n" << item->name << endl << item->platform << endl << item->copies << endl;
}
else
cout << "Game not found\n";
break;
case 'e': case 'E':
exit(0);
break;
}
}
}
}
return 0;
}
I have a library class and the code for this is:
#include "DVD.h"
#include "Game.h"
#include "Book.h"
#ifndef LIBRARY_H_
#define LIBRARY_H_
class Library{
public:
int numGames;
int numDVDs;
int numBooks;
Game collection[100];
DVD collection1[100];
Book collection2[100];
Library(){
numGames = 0;
numDVDs = 0;
numBooks = 0;
}
void insertGame( char gameName[], char platform[], int c);
void deleteGame( char gameName[]);
Game *search( char gameName[]);
void insertDVD( char dvdName[], char director[], int c);
void deleteDVD( char dvdName[]);
DVD *search( char dvdName[]);
void insertBook( char bookName[], char director[], int c);
void deleteBook( char bookName[]);
Book *search( char bookName[]);
};
#endif // end of "#ifndef" block
Media class:
#ifndef MEDIA_H_
#define MEDIA_H_
class Media{
public:
int copies;
char name[45];
};
#endif /* MEDIA_H_ */
Game class:
#include "Media.h"
#ifndef GAME_H_
#define GAME_H_
class Game : public Media{
public:
char platform[45];
};
#endif // end of "#ifndef" block
DVD class:
#include "Media.h"
#ifndef DVD_H_
#define DVD_H_
class DVD : public Media{
public:
char director[45];
};
#endif // end of "#ifndef" block
Book class:
#include "Media.h"
#ifndef BOOK_H_
#define BOOK_H_
class Book : public Media{
public:
char author[45];
};
#endif /* BOOK_H_ */
And the errors I get are:
1. Member declaration not found.
2. return type out-of-line definition of 'library::search'differs from that in the declaration.
3. Functions that differ only in their return types cannot be overloaded.
Game *search( char gameName[]);
DVD *search( char dvdName[]);
Book *search( char bookName[]);
the parameters for search in these 3 cases have exactly the same type. The only difference is the return type.
You cannot overload only on return type, as which function is called is determined by parameters, not by what you assign it to.
The easy solution is calling it searchDVD and searchGame and searchBook. At both declaration and implementation.
The crazy solution would then involve adding this class:
struct deferred_search {
Library* lib;
char const* name;
operator DVD*()const {
return lib->searchDVD(name);
}
operator Book*()const {
return lib->searchBook(name);
}
operator Game*()const {
return lib->searchGame(name);
}
}
and in Library:
deferred_search search( char const* name ) { return {this, name}; }
which is a somewhat obscure technique to do overloading on return type. I would advise against it -- just call the functions searchTYPE.
Or you could use a discriminated union + string structure.
Or three "new" string types.
Or a templatised function with three explicit implementations.
There may be more...
Or you could use a discriminated union + string structure.
Or three "new" string types.
Or a templatised function with three explicit implementations.
There may be more...
e.g. auto const* result = search(char const* const name);
with T any one of { DVD, Book, Game }
struct Media { int c; char const name[]; };
struct Book : Media { char const author[]; };
struct DVD : Media { char const director[]; };
struct Game : Media { char const platform[]; };
template struct <class T> MediaTypeId {};
template struct MediaTypeId<Book> { static const id = 0 };
template struct MediaTypeId<DVD> { static const id = 1};
template struct MediaTypeId<Game> { static const id = 2 };
template <class T>
T const* search(char const name[]) const {
// define an array of your 3 search functions
// select the correct search function based upon the index
// obtained via MediaTypeId<T>::id
// call the function and return the result.
// all library functions must return Media const*
};