Query about a given function's use in the code - c++

i'm following this tutorial and they give us this code to test the function isLowerVowel:
#include <iostream>
bool isLowerVowel(char c, bool yIsVowel)
{
switch (c)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
return true;
case 'y':
return (yIsVowel ? true : false);
default:
return false;
}
}
int main()
{
std::cout << std::boolalpha;
std::cout << isLowerVowel('a',false) << "\n";
std::cout << isLowerVowel('a',true) << "\n";
std::cout << isLowerVowel('q',false) << "\n";
std::cout << isLowerVowel('q',true) << "\n";
std::cout << isLowerVowel('y',false) << "\n";
std::cout << isLowerVowel('y',true) << "\n";
return 0;
}
I dont understand what the use of yIsVowel is for, shouldnt just testing isLowerVowel be enough? Sorry i asked them but got no replies

I dont understand what the use of yIsVowel is for, shouldnt just testing isLowerVowel be enough?
If you were to use the isLowerVowel fuction to implement the isLowerVowel function you would have recursion. It is unclear how this recursion should be terminated.
yIsVowel appears to be used to set whether y is a vowel or not.

Related

C++ Player Creation Menu

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();
}

fast string parser C++

I have an idea to make super fast command parser.
I have more than 100 pairs of command - function, and some commands have same prefixes.
Down below there is example of my idea. I can make a program that will generate C++ code like in this example, but i think this can be realized with templates.
I'm not strong in templates. May be some one can help with it?
static const string_view s1{"hello"};
void f1() { cout << "f1" << endl; }
static const string_view s2{"helly"};
void f2() { cout << "f2" << endl; }
static const string_view s3{"hi jo"};
void f3() { cout << "f3" << endl; }
static const string_view s4{"hoyMo"};
void f4() { cout << "f4" << endl; }
void sw(string_view& hw){
switch(hw.size()){
case 5: {
switch(hw[0]){
case 'h': {
switch(hw[1]){
case 'e': {
switch(hw[2]){
case 'l': {
switch(hw[3]){
case 'l': {
switch(hw[4]){
case 'o': {
f1();
break;
}
case 'y': {
f2();
break;
}
default: cout << "command not found" << endl; break;
}
break;
}
default: cout << "command not found" << endl; break;
}
break;
}
default: cout << "command not found" << endl; break;
}
break;
}
case 'i': {
if(hw.substr(2) == s3.substr(2)){
f3();
}
break;
}
case 'o': {
if(hw.substr(2) == s4.substr(2)){
f4();
}
break;
}
default: cout << "command not found" << endl; break;
}
break;
}
default: cout << "command not found" << endl; break;
}
break;
}
case 6: {
//...
break;
}
default: cout << "command not found" << endl; break;
}
}
int main(){
string_view myCommand("hi jo");
sw(myCommand);
string_view myCommand2("hoyMo");
sw(myCommand2);
string_view myCommand3("ha ha");
sw(myCommand3);
}
You should probably be using a parser library, such as Boost.Spirit. This wil allow you to write simple code, like
string("hello")
| string("helly")
| string("hi jo")
| string("hoyMo")
and do all the heavy lifting for you to generate a parser that will probably be faster than something you would write yourself.

Switch case for Rapidjson::Type

JSON that I'm trying to parse looks something like this is:
{
"testBool": true,
"testString": "eu"
}
And my current parser looks really ugly and it really feels like there is a more elegant way to solve this problem. I tried looking into rapidjson::Type for a switch case using document.GetObject().GetType() but it doesn't provide the same type precision that you can achieve by using Get%TypeName%() functions. hashmap is nothing but a wrapper around std::unordered_map<std::string, std::any>.
rapidjson::Document document;
document.Parse(tmp_string.c_str());
for (auto& member : document.GetObject())
{
if (member.value.IsBool())
{
hashmap->addEntry<bool>(member.name.GetString(), member.value.GetBool());
}
else if (member.value.IsString())
{
hashmap->addEntry<std::string>(member.name.GetString(), member.value.GetString());
}
else if (member.value.IsInt())
{
hashmap->addEntry<int>(member.name.GetString(), member.value.GetInt());
}
.....
//And so on
.....
}
my current parser looks really ugly
Beauty is in the eye of the be(er)holder...here's my code:
static void
printField(const Value& e, const string& fld, bool print_newline = true) {
const Value &v = fld.empty() ? e : e[fld];
if (print_newline)
cout << endl << "\t";
if (not fld.empty())
cout << fld << ": ";
if ( /* custom stuff required? */ ) {
// Do custom stuff
else {
switch (v.GetType()) {
case kNullType:
cout << "Null";
break;
case kFalseType:
case kTrueType:
cout << v.GetBool();
break;
case kObjectType: {
bool first = true;
cout << "{ ";
for (const auto &subfield: v.GetObject()) {
if (first)
first = false;
else
cout << ", ";
printField(v, subfield.name.GetString(), false);
}
cout << " }";
break;
}
case kArrayType: {
bool first = true;
cout << "[ ";
for (const auto &arrEntry: v.GetArray()) {
if (first)
first = false;
else
cout << ", ";
printField(arrEntry, "", false);
}
cout << " ]";
break;
}
case kStringType:
cout << v.GetString();
break;
case kNumberType:
if (v.IsInt64())
cout << v.GetInt64();
else if (v.IsUint64())
cout << v.GetUint64();
else
cout << v.GetDouble();
break;
default:
stringstream msg;
msg << "Unexpected RapidJSON Value type: " << v.GetType();
throw logic_error(msg.str());
}
}
}
This uses the stringize stuff to solve some problems, but, if you don't like that, you can get the same effect manually. It subdivides the IsNumber case using a cascading if; if you need more resolution, you can add the other cases to that.

c++ switch statement: group cases and give particular instruction for each case

Consider the following code:
int main()
{
const int a = 9;
switch (a)
{
case 9:
// since a is 9, this ("good") should be printed
std::cout << " good " << std::endl;
case 4:
// since a is not 4, this ("bad") should not be printed
std::cout << " bad " << std::endl;
// for both a==9 or a==4, this should be printed
{
std::cout << " always print me " << std::endl;
break;
}
}
}
The result should then be:
good
always print me
However this is not working. It there a way to do that in C++? Thanks!
There is no way of doing what you ask for inside a switch-statement short of using goto:
#include <iostream>
int main()
{
const int a{ 9 };
switch (a)
{
case 9:
std::cout << "good\n";
goto foo;
case 4:
std::cout << "bad\n";
goto foo;
foo:
std::cout << "always print me\n";
break;
}
}

MsiEnumRelatedProducts Invalid Parameter

Attempting to use MsiEnumRelatedProducts with various input is constantly returning only ERROR_INVALID_PARAMETERS for me. The documentation doesn't give any details on what the source of the invalid parameter could be but I've tried many different options. Currently I have this code below to demonstrate the problem. Replace the with a valid upgrade guid.
int _tmain(int argc, _TCHAR* argv[])
{
const wchar_t* upgrade = L"812D9038-YOUR-GUID-B2EB-64F4E0B3FB3D";
wchar_t product[39];
DWORD index = 0;
switch (MsiEnumRelatedProducts(upgrade, 0, index++, product)) {
case ERROR_SUCCESS:
wcout << L"ERROR_SUCCESS" << endl;
break;
case ERROR_NO_MORE_ITEMS:
wcout << L"ERROR_NO_MORE_ITEMS" << endl;
break;
case ERROR_BAD_CONFIGURATION:
wcout << L"ERROR_BAD_CONFIGURATION" << endl;
break;
case ERROR_INVALID_PARAMETER:
wcout << L"ERROR_INVALID_PARAMETER" << endl;
break;
case ERROR_NOT_ENOUGH_MEMORY:
wcout << L"ERROR_NOT_ENOUGH_MEMORY" << endl;
break;
default:
wcout << L"DEFAULT" << endl;
break;
}
}
Try enclosing your upgrade code in curly brackets so it looks like {GUID}.