Use variable inside variable name Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Use variable inside variable name

Post by Wanderer82 »

Hi

I'm programming a dictionary. I write words into wxArrayStrings which are called Dict_A, Dict_B, and so on. So for each letter I have an array. Now if the user enters a word like "ball", the program reads the first letter and now I want to look inside Dict_B. Is there a way I can use the variable "b", the first letter, to specify the according dictionary array (Dict_B)? Like for example:

char firstLetter = "b";
while(Dict_(firstLetter) != "")
etc.

Or what would be the easiest way to do this?
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Use variable inside variable name

Post by doublemax »

There is no "direct" way to do that, you'll need a hash map.

Definition:

Code: Select all

#include <unordered_map>
typedef std::unordered_map<char, wxArrayString *> DictionaryMap;
Member variables:

Code: Select all

DictionaryMap m_dictionary_map;
wxArrayString Dict_A;
wxArrayString Dict_B;
wxArrayString Dict_C;
Initialization:

Code: Select all

m_dictionary_map['A'] = &Dict_A;
m_dictionary_map['B'] = &Dict_B;
m_dictionary_map['C'] = &Dict_C;
Usage:

Code: Select all

char testChar = 'A';
wxArrayString *dict = m_dictionary_map[testChar];
// use "dict" here
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Re: Use variable inside variable name

Post by Wanderer82 »

Thanks a lot for the extensive example.

Can I set this up like a class that I can write in an .h file? So I could have the definition and member variables in an .h file and the initialization is done in the main program? I need to access the arrays only inside the function which looks up the word and in the function that loads the dictionary from a file into the arrays. So where would I put these 4 parts best?
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Use variable inside variable name

Post by doublemax »

The first two parts go where the already existing wxArrayString are defined, so most likely in a header file.

The Initialization part probably in the constructor of the respective class where you use the dictionaries.

The last part is just an example on how to access the dictionaries.
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Re: Use variable inside variable name

Post by Wanderer82 »

Okay, I'll test that when I'm home :-)
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Re: Use variable inside variable name

Post by Wanderer82 »

I'm still at realizing your solution but wanted to ask if and what kind of disadvantage it would be if I just wrote a while-loop for each first letter using "switch" and "case"? I mean, my code gets blown up, sure, but would it also be slower?
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Use variable inside variable name

Post by doublemax »

Wanderer82 wrote: Fri Dec 02, 2022 11:36 pm I'm still at realizing your solution but wanted to ask if and what kind of disadvantage it would be if I just wrote a while-loop for each first letter using "switch" and "case"? I mean, my code gets blown up, sure, but would it also be slower?
The main "disadvantage" would be that it's not every elegant :)

But it's doable, performance should not be an issue.
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Re: Use variable inside variable name

Post by Wanderer82 »

Okay, I see.

So I'm facing the first problem with your solution. I get the error "'m_dictionary_map' does not name a typ"

I was just strying to put everything inside the class:

Code: Select all

#ifndef DICTIONARY_H
#define DICTIONARY_H

#include <wx/arrstr.h>
#include <wx/dynarray.h>
#include <unordered_map>

class Dictionary
{
    public:
        Dictionary();
        virtual ~Dictionary();

        wxString Language;

        typedef std::unordered_map<char, wxArrayString *> DictionaryMap;
        DictionaryMap m_dictionary_map;

        wxArrayString Dict_A;
        wxArrayString Dict_B;
        wxArrayString Dict_C;
        wxArrayString Dict_D;
        wxArrayString Dict_E;
        wxArrayString Dict_F;
        wxArrayString Dict_G;
        wxArrayString Dict_H;
        wxArrayString Dict_I;
        wxArrayString Dict_J;
        wxArrayString Dict_K;
        wxArrayString Dict_L;
        wxArrayString Dict_M;
        wxArrayString Dict_N;
        wxArrayString Dict_O;
        wxArrayString Dict_P;
        wxArrayString Dict_Q;
        wxArrayString Dict_R;
        wxArrayString Dict_S;
        wxArrayString Dict_T;
        wxArrayString Dict_U;
        wxArrayString Dict_V;
        wxArrayString Dict_W;
        wxArrayString Dict_X;
        wxArrayString Dict_Y;
        wxArrayString Dict_Z;

        m_dictionary_map['A'] = &Dict_A;
        m_dictionary_map['B'] = &Dict_B;
        m_dictionary_map['C'] = &Dict_C;
        m_dictionary_map['D'] = &Dict_D;
        m_dictionary_map['E'] = &Dict_E;
        m_dictionary_map['F'] = &Dict_F;
        m_dictionary_map['G'] = &Dict_G;
        m_dictionary_map['H'] = &Dict_H;
        m_dictionary_map['I'] = &Dict_I;
        m_dictionary_map['J'] = &Dict_J;
        m_dictionary_map['K'] = &Dict_K;
        m_dictionary_map['L'] = &Dict_L;
        m_dictionary_map['M'] = &Dict_M;
        m_dictionary_map['N'] = &Dict_N;
        m_dictionary_map['O'] = &Dict_O;
        m_dictionary_map['P'] = &Dict_P;
        m_dictionary_map['Q'] = &Dict_Q;
        m_dictionary_map['R'] = &Dict_R;
        m_dictionary_map['S'] = &Dict_S;
        m_dictionary_map['T'] = &Dict_T;
        m_dictionary_map['U'] = &Dict_U;
        m_dictionary_map['V'] = &Dict_V;
        m_dictionary_map['W'] = &Dict_W;
        m_dictionary_map['Y'] = &Dict_X;
        m_dictionary_map['A'] = &Dict_Y;
        m_dictionary_map['Z'] = &Dict_Z;
        
        protected:

    private:
};

#endif // DICTIONARY_H
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Use variable inside variable name

Post by doublemax »

Code: Select all

m_dictionary_map['A'] = &Dict_A;
        m_dictionary_map['B'] = &Dict_B;
        m_dictionary_map['C'] = &Dict_C;
        m_dictionary_map['D'] = &Dict_D;
        m_dictionary_map['E'] = &Dict_E;
        m_dictionary_map['F'] = &Dict_F;
        m_dictionary_map['G'] = &Dict_G;
        m_dictionary_map['H'] = &Dict_H;
        m_dictionary_map['I'] = &Dict_I;
        m_dictionary_map['J'] = &Dict_J;
        m_dictionary_map['K'] = &Dict_K;
        m_dictionary_map['L'] = &Dict_L;
        m_dictionary_map['M'] = &Dict_M;
        m_dictionary_map['N'] = &Dict_N;
        m_dictionary_map['O'] = &Dict_O;
        m_dictionary_map['P'] = &Dict_P;
        m_dictionary_map['Q'] = &Dict_Q;
        m_dictionary_map['R'] = &Dict_R;
        m_dictionary_map['S'] = &Dict_S;
        m_dictionary_map['T'] = &Dict_T;
        m_dictionary_map['U'] = &Dict_U;
        m_dictionary_map['V'] = &Dict_V;
        m_dictionary_map['W'] = &Dict_W;
        m_dictionary_map['Y'] = &Dict_X;
        m_dictionary_map['A'] = &Dict_Y;
        m_dictionary_map['Z'] = &Dict_Z;
That part must go into the constructor.
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Re: Use variable inside variable name

Post by Wanderer82 »

Ok, I got rid of the error. But now I have the problem that I can't access "dict" to find a substring in one of the elements.

My program crashes with status -1073741819 even with this code:

Code: Select all

char firstLetter= wordToSearch.GetChar(0);
wxString stringtest;
wxArrayString *dict = Dictionary1.m_dictionary_map[firstLetter];
stringtest = dict->Item(0);
Anyways I'm confused why I have to use ->Item(). I have always accessed the wxArrayStrings using just

Code: Select all

stringtest = dict[0];
But in your constellation this gave me an error while compiling.
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Use variable inside variable name

Post by doublemax »

Code: Select all

wxArrayString *dict = Dictionary1.m_dictionary_map[firstLetter];
This will return a NULL pointer if there is no matching entry. You should check for that before using the pointer.

You're initializing the map with uppercase letters, is "firstLetter" always uppercase? If not you need to convert it.

Code: Select all

stringtest = dict[0];
This syntax doesn't work, because now "dict" is now a pointer.

Alternative syntaxes would be:

Code: Select all

stringtest = dict->operator[](0);
stringtest = (*dict)[0];
I think dict->Item(0) is the better option.

You could also convert the pointer to a reference (after checking for NULL):

Code: Select all

wxArrayString *dictP = Dictionary1.m_dictionary_map[firstLetter];
if ( dictP != NULL ) {
  wxArrayString &dict = *dictP;
  stringtest = dict[0];
}
Use the source, Luke!
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Re: Use variable inside variable name

Post by Wanderer82 »

This was an important information for my program. Because there might be words that start with a character that is outside the alphabet. So this check is really important.

I was thinking about the upper/lower case problem all the time but I didn't think that in this case it could be the problem... but it was :-) I have to deal with this anyways. After a full stop the translated word has to start with an upper case letter as well. So I'll have to check this, too.
Post Reply