Robert Snyder
Robert Snyder

Reputation: 2409

What is a #define string's type?

I think I am going about this wrong. I'm working on making a SO for a MSR type object. And by default (if I read it correctly) OPOS uses unicode. So I made my C++ automated class use unicode as well and from what I understand there is no way around it. In the OPOS head class there are 2 string definitions, the third one is one my creation:

#define OPOS_ROOTKEY "SOFTWARE\\OLEforRetail\\ServiceOPOS"
#define OPOS_CLASSKEY_MSR     "MSR"
#define OPOSMSR OPOS_ROOTKEY "\\" OPOS_CLASSKEY_MSR "\\"

This is so that a person can access the registry. So I decided to make myself a registry helper class instead of having it all in my SO. Looks like I'm having a hard time trying to figure out how I should do this in the end. I copied working code from another SO I had, but I feel that that code was not made correctly, and I want my code made right the first time.

So I came up with this, but I can not figure out how to combine my string with the class name. I made the class name as a parameter in my constructor.

RegistryHelper::RegistryHelper(LPCTSTR deviceName) {
    cout << "RegistryHelper::RegistryHelper()+" << endl;
    baseOpen = true;

    CString test;
    test.Format("%s%s",OPOSMSR, theClass); //fail
    REGSAM access = KEY_READ | KEY_WOW64_64KEY;
    LONG nError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, theClass ,0, access,&hBaseKey); //not what I want, but would compile, I want test here instead of theClass

    if (nError != ERROR_SUCCESS) {
        cerr << "(E)RegistryHelper::RegistryHelper(): Failed to load base key. [" <<(int)nError << "]" << endl;
        RegCloseKey(hBaseKey);
        baseOpen = false;
    }

    cout << "RegistryHelper::RegistryHelper()-" << endl;
}

Any tips on what I am doing wrong? since I'm on the subject: I'm going to post all my code for this. How bad is it?

What I'm after is something like this

unsigned int baud;
char* parity;

bool MSRSO::LoadRegistryValuesIntoMemory(LPCSTR deviceName) {
    RegistryHelper reg(deviceName);
    bool required = reg.LoadDWORD("BaudRate", 19200, baud);
    required = required && reg.LoadREGSZ("Parity", "NONE", parity);
    //other values
    reg.Close();
    return required;
}

Keep in mind I'm a C# and java guy so I may have my data types wrong. I only wrote simple hello world programs and temp conversion programs for myself in C++ on a SUPER old linux box back in the day. Although I am getting better at C++ I'm still not comfortable with it. So to sum up what is the data type of the #define type? How do I combine it with LPCTSTR? Should I have done that so that I can access registry values ONLY?

Thank you.

Upvotes: 1

Views: 2231

Answers (2)

Qaz
Qaz

Reputation: 61900

Your code has inconsistencies between narrow and wide strings. A literal 'a' has the type char, and is a narrow character. A literal L'a' has the type wchar_t, and is a wide character.

Next, we can apply these to strings:
"abc" is a narrow string of type const char (&)[4].
L"abc" is a wide string of type const wchar_t (&)[4].

To reduce the hassle of supporting both, there is what is known as the TCHAR. Defined in a Windows header, this type is char or wchar_t, depending on whether UNICODE is defined. If it is defined, TCHAR will be wchar_t. If it is not defined, TCHAR will be char.

This also came with a TEXT macro that converts a string literal into characters of type TCHAR. That is, if UNICODE is defined, TEXT("abc") will be equivalent to L"abc", and if it is not defined, TEXT("abc") will be equivalent to "abc".

Strings were also given some typedefs as well:

LP[C][W|T]STR

The LP indicates a pointer, and the STR indicates "to a string". If C is included, the string will be a constant one. If W or T is included, the string will be made of characters of type wchar_t or TCHAR respectively.

For example:

LPSTR: char *
LPCSTR: const char *
LPWSTR: wchar_t *
LPCTSTR: const TCHAR *

Using this information, you can correctly understand why using TCHAR and TEXT will cause your code to become compatible with something else, whether it uses narrow or wide characters.

Here's a simple example, keeping in mind that std::string is, for our purposes, std::basic_string<char>:

std::basic_string<TCHAR> s(TEXT("abcd"));
s += TEXT("ZYXW"); //s is now `TEXT("abcdZXW")

Upvotes: 3

Vahid Farahmand
Vahid Farahmand

Reputation: 2558

Change

#define OPOS_ROOTKEY "SOFTWARE\\OLEforRetail\\ServiceOPOS"
#define OPOS_CLASSKEY_MSR     "MSR"
#define OPOSMSR OPOS_ROOTKEY "\\" OPOS_CLASSKEY_MSR "\\"

to

#define OPOS_ROOTKEY L"SOFTWARE\\OLEforRetail\\ServiceOPOS"
#define OPOS_CLASSKEY_MSR     L"MSR"
#define OPOSMSR OPOS_ROOTKEY L"\\" OPOS_CLASSKEY_MSR "\\"

Upvotes: 1

Related Questions