How to output a variable stored in another variable - c++

So here's my code at the moment:
#include <iostream>
using namespace std;
int main() {
string x = "_one";
int sound_one = 7;
int sound_two = 8;
cout << ("sound") + x;
}
However when I run the code, it outputs 'sound_one' instead of '7'. How do I get it to output the variable sound_one instead of just 'sound_one'? Also, I need it so I can change x to different things (eg '_two') so it will then output sound_two instead. Any help would be greatly appreciated.

C++ is not a reflective language in the sense that you can acquire a variable name at runtime (variable names are normally compiled out of the program). You can use std::map though to achieve your immediate aim:
#include <iostream>
#include <string>
#include <map>
int main() {
using std::literals::string_literals::operator""s;
std::string x = "_one";
std::map<std::string, int> data;
data["sound_one"] = 7;
data["sound_two"] = 8;
std::cout << data["sound"s + x];
}
Note the notation "sound"s: the suffixed s denotes a std::string user defined literal.

You can't a variable from a string in this way. A work around is to use if/switch statements until the variable name is matched and then print it:
if(x == "_one") {
cout << sound_one;
}
else if(x == "_two") {
cout << sound_two;
}
else {
cout << "no match";
}

You can't do that in C++. You can use a map as shown in another answer, but I feel like what you really need is an array:
#include <format>
#include <iostream>
int main()
{
int data[] { 7, 8 };
std::cout << std::format("data[{}] = {}\n", 0, data[0]);
}
Arrays are usually better for such simple ordered sequences.

Related

Trying to add elements to a Vector classified with a Struct

I'm making a program to basically show the statistics about words the user enters. The rest of the program is fine so far, but I'm having a hard time adding words to a vector of type WordCount.
I have looked around and found several answers, which I would've thought could solve my issue, but I either get a very weird compiler error or it just does not work. I have tried using emplace_back and push_back with calls I thought was right. In essence, my problem code is as follows:
#include <iostream>
#include <string>
#include <vector>
using namespace std; //for simplicity here
struct WordCount {
string word;
int count;
//I have tried using this too:
WordCount(string _word, int _count) : word{_word}, count{_count} {}
};
//...//
void wordToVector(/**...**/,string addStr, vector<WordCount>& wordStats){
/**... code that I've tested to work; basically determined if the
word was already said as I need to have unique words only...**/
wordStats.push_back(WordCount(addStr, 1));
/** also tried: (some had "#include <istream>" when using emplace_back
but that didn't seem to make a difference for me in any case)
wordStats.emplace_back(WordCount(addStr, 1));
wordStats.emplace_back({addStr, 1});
wordStats.push_back(addStr, 1)
wordStats.push_back(addStr).word; (and wordStats.push_back(1).count;)
**/
}
int main() {
vector<WordCount> wordStats(1); //"1" to initialize the size
wordStats.at(0).word = "";
wordStats.at(0).count = 0;
/**There's already a part to change the first values to what they should
be, and it worked last I tested it. Below is a part was for my
personal use to see if anything came out... if it worked**/
for (int i = 0; i < 3; i++) {
cout << wordStats.at(i).word << endl;
cout << wordStats.at(i).count << endl;
}
return 0;
}
I must use a vector for this and cannot use pointers (as I've seen suggested) or #include <algorithm> per the instructions. If I typed in "Oh happy day!", it should be able to print (when fixed, with the current cout statements):
OH
1
HAPPY
1
DAY
1
(There's an earlier part that capitalizes every letter, which I tested to work).
This is my first post here because I'm lost. Please let me know if I provided too much or not enough. **Edited formatting
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct WordCount {
string word;
int count;
};
void wordToVector(string addStr, vector<WordCount>& wordStats){
for (int i = 0; i < wordStats.size(); i++) {
if (wordStats[i].word == addStr) {
wordStats[i].count = wordStats[i].count + 1;
return;
}
}
struct WordCount wc;
wc.word = addStr;
wc.count = 1;
wordStats.push_back(wc);
}
int main() {
vector<WordCount> wordStats;
wordToVector("hehe", wordStats);
wordToVector("hehe", wordStats);
wordToVector("haha", wordStats);
for (int i = 0; i < wordStats.size(); i++) {
cout << wordStats.at(i).word << endl;
cout << wordStats.at(i).count << endl;
}
return 0;
}
Using this code I get output:
hehe
2
haha
1
Is there anything else that needs to be added?
If you want to split the input by the spaces and check for occurrences of every word in the input it could be quite inefficient for longer texts to check for every word (Would be linear I think with M*N complexity), so if you are allowed I do suggest to use a map with word as key and value as the amount of occurrences - or something in that fashion.

How to initialize items in a range in a captureless lambda, C++

My code is below. This works, It allows me to have exactly one range in my lambda.
So I guess what my question is, is how do I achieve the same results without using
"if(LOOP > 2 && LOOP < 5){int THERANGEVALUE = 2; FUNC[THERANGEVALUE]();}"?
And instead initialize an item in my captureless lambda as being ranged instead. aka, item_2 being item_range(2,4). And then also being able to continue my lambda normally, whereas Item_3 will equate to item_5.
Thank you for any help in advance, I will gladly add more input if requested.
#include <iostream>
using namespace std;
void (*FUNC[3])(void) = { //captureless lambda.
/*ITEM_0*/[](){ cout << "x" << endl;},
/*ITEM_1*/[](){cout << "y" << endl;},
/*ITEM_2->ITEM_4*/[](){cout<<"z";}
};
/*Here the [](){code;} lambda is acting as a stand-in for void FUNC() so it shouldn't touch anything outside of its scope*/
int LOOP = 4;
int main()
{
if(LOOP > 2 && LOOP < 5){int THERANGEVALUE = 2; FUNC[THERANGEVALUE]();}
FUNC[LOOP]();
return 0;
}
Adding on to this, below is the solution I came up with after asking a friend. To my surprise it was actually a lot simpler than I expected. While I couldn't initialize each item in the lambda in a range easily, I could pass it into an array and set a range inside of the array instead. So while it's not quite what I was looking for, it's...good enough for my purposes. Thanks Jaime if you see this. Otherwise I'd use PilouPili's answer below.
#include <iostream>
using namespace std;
void (*FUNC[4])(void) = { //captureless lambda.
/*ITEM_0*/ [](){ cout << "x" << endl;},
/*ITEM_1*/ [](){cout << "y" << endl;},
/*ITEM_2->ITEM_4*/[](){cout<<"z";},
/*ITEM_5*/ [](){cout<<"z";}
};
int LOOP = 4;
int main()
{
int ARR[5]={};
for(int I = 0; I < 6;I=I+1){//handling of ranged values.
if(I>2 && I<5){ARR[I]=2;} else {ARR[I]=I;}
}
FUNC[ARR[LOOP]]();
return 0;
}
I only see to way :
either extend your function array -> That's FUNC1 in the next example
change the value given in operator [] -> That's FUNC2 in the next example
#include <iostream>
#include <vector>
using namespace std;
std::vector<void (*)(void)> init_FUNC()
{
std::vector<void (*)(void)> func(5, [](){cout<<"z";});
func[0]=[](){ cout << "x" << endl;};
func[1]=[](){ cout << "y" << endl;};
return func;
}
std::vector<void (*)(void)> FUNC1= init_FUNC();
class FUNC_MAP
{
void (*_FUNC[3])(void) = { //captureless lambda.
/*ITEM_0*/[](){ cout << "x" << endl;},
/*ITEM_1*/[](){cout << "y" << endl;},
/*ITEM_2->ITEM_4*/[](){cout<<"z";}
};
typedef void (*FUNC_MAP_OUT)(void);
public:
FUNC_MAP_OUT operator[](int i)
{
if(i>2 && i<5)
{return _FUNC[2];}
else
{return _FUNC[i];}
}
};
FUNC_MAP FUNC2;
/*Here the [](){code;} lambda is acting as a stand-in for void FUNC() so it shouldn't touch anything outside of its scope*/
int LOOP = 1;
int main()
{
FUNC1[LOOP]();
FUNC2[LOOP]();
return 0;
}

How to check if an array is equal to some set of values

I know this seems a little odd to ask such a question but it's annoying me!
char winnerCheck[5];
if (winnerCheck=={'X','X','X','X','X'})
{
cout<<second<<", you won the game!";
}
it gives me ([Error] expected primary-expression before '{' token) for the second line.
Thanks in advance
Go away from the legacy C arrays. Use std::array and it's simple:
std::array<char, 5> winnerCheck;;
if (winnerCheck == std::array{'X','X','X','X','X'})
{
}
If you don't have C++17 yet you just need to add the std::array template arguments:
std::array<char, 5> winnerCheck;;
if (winnerCheck == std::array<char, 5>{'X','X','X','X','X'})
{
}
You can simply use the std::string as below:
#include <iostream>
#include <string>
using namespace std;
int main()
{
char winnerCheck[2];
winnerCheck[0] = 'X';
winnerCheck[1] = 'X';
if(std::string(winnerCheck) == std::string({'X','X'}))
{
cout<<"you won the game"<<endl;
}
return 0;
}
Most straight forward way should be:
if (winnerCheck[0] == 'A' && winnerCheck[1] == 'B' ...)
You cannot compare the content of C arrays like that. There isn't any syntax do so.
I propose you use a function to check for a winner. Here is an example, it will blow up if you give pass the function a null pointer but it stops as soon the two strings are different.
#include <iostream>
#include <vector>
bool isWinner(char *playerStr)
{
static const char winningStr[5] = { 'X','X', 'X', 'X', 'X' };
for (int i = 0; i < 5; i++)
{
if (playerStr[i] != winningStr[i])
{
return false;
}
}
return true;
}
int main()
{
std::cout << isWinner("abdce") << std::endl;
std::cout << isWinner("XYZXX") << std::endl;
std::cout << isWinner("XXXXZ") << std::endl;
std::cout << isWinner("XXXXX") << std::endl;
return 0;
}
If you want to check whether all characters are same or not like your example, you can also use std::all_of as follows:
DEMO
if (std::all_of(std::begin(winnerCheck), std::end(winnerCheck),
[](char x) { return (x == 'X'); }))
{
std::cout << "You won the game!";
}
Despite what several answers have suggested, don’t create a temporary container (std::vector or std::string) from your winnerCheck array. Constructing and destroying those containers adds a lot of thrashing. Instead, use an algorithm:
static const char winner[5] = { `X`, `X`, `X`, `X`, `X` };
char winnerCheck[5] = whatever;
if (std::equal(std::begin(winner), std::end(winner), winnerCheck))
std::cout << “You won the game\n”;

C++ Undeclared Identifier on Object creation

So I am new to c++, coming from C#. This is giving me several errors when compiling, which all seem to relate to this object declaration. Anyone able to show me the right way to do this?
I get an undeclared identifier where i declare tri(sideLength).
I have used this as a reference for object declaration, but it doesn't seem to be helping me.
Thanks.
#include <iostream> // Provides cout
#include <iomanip> // Provides setw function for setting output width
#include <cstdlib> // Provides EXIT_SUCCESS
#include <cassert> // Provides assert function
#include <stdexcept>
#include <math.h>
using namespace std; // Allows all standard library items to be used
void setup_cout_fractions(int fraction_digits)
// Precondition: fraction_digits is not negative.
// Postcondition: All double or float numbers printed to cout will now be
// rounded to the specified digits on the right of the decimal.
{
assert(fraction_digits > 0);
cout.precision(fraction_digits);
cout.setf(ios::fixed, ios::floatfield);
if (fraction_digits == 0)
cout.unsetf(ios::showpoint);
else
cout.setf(ios::showpoint);
}
int main()
{
const int MAX_SIDE_LENGTH = 6;
const int INITIAL_LENGTH = 1;
const int DIGITS = 4;
const int ARRAY_SIZE = 6;
// Set up the output for fractions and print the table headings.
setup_cout_fractions(DIGITS);
// Each iteration of the loop prints one line of the table.
for (int sideLength = 0; sideLength < MAX_SIDE_LENGTH; sideLength += 1)
{
EquilateralTriangle tri(sideLength);
//Square sq(sideLength);
//Pentagon_Reg pent(sideLength);
//Hexagon_Reg hex(sideLength);
//Heptagon_Reg hept(sideLength);
//Octagon_Reg octa(sideLength);
cout << "Type: " << tri.Name() << "has area: " << tri.Area() << " with SideLength = " << sideLength;
}
return EXIT_SUCCESS;
}
//Template
class GeometricFigure
{
public:
GeometricFigure() { }
double SideLength;
virtual double Area() { return 0; };
virtual char* Name() { return ""; };
};
class EquilateralTriangle : public GeometricFigure {
public:
EquilateralTriangle(double sideLength)
{
SideLength = sideLength;
}
char* Name() { return "Equilateral Triangle"; }
double Area() { return (sqrt(3) / 2 * pow(SideLength, 2)); }
};
In C++, the compiler reads your code from top-to-bottom, once. This is a holdover from when early C compilers only had a few kilobytes of memory to work with - C was designed so that a compiler would only need to look at a little bit of the code at a time.
Because of this, things must have been declared or defined as necessary, before you try to use them.
Move both classes somewhere before main. GeometricFigure must be before EquilateralTriangle, and EquilateralTriangle must be before main.
You would need to "declare" or tell the compiler, where to look for the EquilateralTriangle and GeometricFigure, "before" you use it first. you might want to take a look at the similar discussion at - C# declarations vs definitions

using enum for an array index in c++

#include <stdlib.h>
#include <stdio.h>
using namespace std;
void main(){
char *resolutions[] = { "720x480", "1024x600", "1280x720", "1920x1080" };
int x = 0;
enum ResMode
{
p480,
p600,
p720,
p1080
};
ResMode res = p480;
printf("\nPlease enter the resolution you wish to use now by entering a number");
printf("\n480p[0], 600p[1], 720p[2], 1080p[3]");
gets(res);
printf("\nThe resolution you have selected is %s", resolutions[res]);
}
so basically i want to be able to press 1 and have it select p600 from enum and out put it as 1024x600 in the next line. I am getting a type conversion error.
How can i fix this?
Looks like you want to associate some items with other items. Usually associations are described in lookup tables or maps.
std::map<ResMode, std::string> map_table =
{
{p480, string("720x480")},
{p600, string("1024x600")},
{p720, string("1280x720")},
{p1080, string("1920x1080")},
};
int main(void)
{
cout << map_table[p480] << "\n";
return EXIT_SUCCESS;
}
Likewise, you can map menu selections to enums.
Edit 1
std::map<unsigned int, ResMode> selection_map =
{
{0, p480}, {1, p600}, {2, p720}, {3, p1080},
};
int main(void)
{
cout << "\n"
<< "Please enter the resolution you wish to use now by entering a number\n"
<<"480p[0], 600p[1], 720p[2], 1080p[3]";
unsigned int selection = 0;
cin >> selection;
if (selection < 4)
{
Resmode resolution_index = selection_map[selection];
cout << "You chose: "
<< map_table[resolution_index]
<< "\n";
}
return EXIT_SUCCESS;
}
int's are not implicitly convertible to an enum. You will have to read in an int and then cast it yourself. Example,
int resInt;
scanf("%d", &resInt);
res = static_cast<ResMode>(resInt);//Note that this does not do bound checking.
You can use "scanf" instead of "gets", something like this:
scanf("%d",&res); // I recommend use scanf_s
Or the iostream library with std::cin. But after taking the input, always, check if the input is the correct one.
As otehrs pointed out, there is no direct way of doing this. However, there are some recipes/tricks that you can use. I modified your code as follows:
#include <stdlib.h>
#include <stdio.h>
#define SOME_ENUM(DO) \
DO(_720x480) \
DO(_1024x600) \
DO(_1280x720) \
DO(_1920x1080)
#define MAKE_ENUM(VAR) VAR,
enum class RESOLUTIONS
{
SOME_ENUM(MAKE_ENUM)
};
#define MAKE_STRINGS(VAR) #VAR,
const char* const
RESOLUTION_NAMES[] =
{
SOME_ENUM(MAKE_STRINGS)
};
const char *
GET_RESOLUTION_NAME(RESOLUTIONS type)
{
return RESOLUTION_NAMES[static_cast<int>(type)];
}
int
GET_RESOLUTION_VALUE(RESOLUTIONS type)
{
return static_cast<int>(type);
}
RESOLUTIONS
GET_RESOLUTION(int i)
{
return static_cast<RESOLUTIONS>(i);
}
using namespace std;
int main(){
printf("\nPlease enter the resolution you wish to use now by entering a number");
printf("\n480p[0], 600p[1], 720p[2], 1080p[3]");
int res_type;
cin >> res_type;
RESOLUTIONS selected_res = GET_RESOLUTION(res_type);
printf("\nThe resolution you have selected is %s\n\n", GET_RESOLUTION_NAME(selected_res));
return 0;
}
Sorry for not providing an explanation, as I have to go now. This recipe can be found here. The code works and compiles for c++11.