How to compare std::string and TCHAR* in an if statement? - c++

I'm new at C++ coding, and I have this code:
std::string user_name = "raso";
// User Name
TCHAR username[UNLEN + 1];
DWORD username_len = UNLEN + 1;
GetUserName((TCHAR*)username, &username_len);
if (user_name == username)
{
std::cout << "You found the user name!";
}
It gives me an error. It basically finds the user name of the PC and compares it with the string user_name, but user_name is a std::string and username is a TCHAR* type, right? So, how can I compare both in an if statement?

Don't mix-and-match wide and narrow strings.
If your target name is std::string, use an A version of API: GetUserNameA
Also, your type casting (TCHAR*)username was not needed.
std::string user_name = "raso";
// User Name
char username[UNLEN + 1];
DWORD username_len = UNLEN;
GetUserNameA(username, &username_len);
if (user_name == username)
{
std::cout << "You found the user name!";
}

Related

Assert a BSTR with string

I have a test function as follow:
[TestMethod]
void RipMichaelJacksonTest()
{
string expected = "Hello";
BSTR actual = SysAllocString(L"Hello");
Assert::AreEqual(expected, actual);
}
The assert part will of course fail.
Is there any Assert function that i can use?
Im new to VC++.
The problem is that you are doing a AreEqual. Passing in two parameters will force AreEqual(Object^, Object^) which:
Verifies that two specified objects are equal. The assertion fails if the objects are not equal.
What you are actually looking for is the comparison of a wchar* and a char*. There is not a direct comparison function between the two so it will be necessary to convert from a string to a wstring. There are lots of examples of how to do that, such as: https://stackoverflow.com/a/7159944/2642059 and you'll need to do something similar, for example:
wstring get_wstring(const string& s) {
wstring buf;
const char* cs = s.c_str();
const size_t wn = mbsrtowcs(nullptr, &cs, 0, nullptr);
if (wn == string::npos) {
cout << "Error in mbsrtowcs(): " << errno << endl;
} else {
buf.resize(wn + 1);
if(mbsrtowcs(&*buf.begin(), &cs, wn + 1, nullptr) == string::npos) {
cout << "Error in mbsrtowcs(): " << errno << endl;
buf.resize(0);
}
}
return buf;
}
The return of get_wstring(expected) and actual will now both be wchars and can thereby be compared in the using AreEqual(String^, String^, bool)

C++ - Read data from Buffer

How can i read data from my memory buffer?
const char *buf
and then print it out like this
MessageBoxA(NULL, "Buf: " + buf, " ", MB_OK);
std::string str = "Buf: ";
str += buf; // I assume buf is a null terminated string
MessageBoxA(NULL, str.c_str(), " ", MB_OK);
You can't apply + on string literals and/or char*. One of the operands has to be a std::string to be able to take advantage of std::string's operator+ overload.
If your buf is a char array, then something like this could work:
std::string("Buf: ") + buf
This requires that buf is null-terminated.
If buf isn't null-terminated however, Tony D's solution should work.

wostringstream to LPWSTR for MessageBoxW function

I seem to be missing something in regards to converting a wostringstream to a LPCWSTR.
void counter_error(const wstring& input) {
wostringstream tempss;
tempss << L"Cannot find counter " << input;
LPCWSTR temp = tempss.str().c_str();
MessageBoxW(0, temp, L"ERROR", 0);
}
The "ERROR" caption shows up fine but the text below is garbled. I thought that it might be the c_str() function returning a regular char array instead of a wchar array but intellisense is telling me it returns a wchar array.
This line looks problematic:
LPCWSTR temp = tempss.str().c_str();
tempss.str() creates a temporary string which is destroyed at the end.
Try
void counter_error(const wstring& input) {
wostringstream tempss;
tempss << L"Cannot find counter " << input;
wstring temp_str = tempss.str();
LPCWSTR temp = temp_str.c_str();
MessageBoxW(0, temp, L"ERROR", 0);
}
Or, as #JoachimPileborg suggested, consider
MessageBoxW(0, (wstring(L"Cannot find counter " + input).c_str(), ...)
It still creates a temporary variable, but it is not going to be destroyed before returning from MessageBoxW.

C++ String to byte error

So, I converted the string to byte in C++, but when it goes to add it into registry, it's stripping off the exe part but keeping the ., I have no idea what's wrong with it.
If you're wondering what NXS is, the value of it is "noerrorsplease.exe", type is char.
char szFinal[] = "";
strcat(szFinal, (const char *)ExtractDirectory(filepath).c_str());
//Not needed: strcat(szFinal, "");
strcat(szFinal, nxs);
strcat(szFinal, ".exe");
CString str;
str = szFinal;
str += ".exe";
cout << str.GetString() << endl;
const BYTE* pb = reinterpret_cast<const BYTE*>(str.GetString());
cout << pb << endl;
DWORD pathLenInBytes = *szFinal * sizeof(*szFinal);
if(RegSetValueEx(newValue, TEXT("Printing Device"), 0, REG_SZ, (LPBYTE)pb, pathLenInBytes) != ERROR_SUCCESS)
{
RegCloseKey(newValue);
cout << "error" << endl;
}
cout << "Possibly worked." << endl;
RegCloseKey(newValue);
This code
char szFinal[] = "";
strcat(szFinal, (const char *)ExtractDirectory(filepath).c_str());
is already invalid. You defined array szFina having only one character that is the terminating zero. You may not use it for copying in it any string. In these situations you should use an object of type std::string.

Heap corruption using strcat

One of my weaknesses is effectively using chars in C++ which is what I am trying to do right now. I have a player class in my game and within the player class, I create a playerCard object which displays various information. This works fine for a single instance of the player object (i.e. Player player) but when I attempt to push_back a player object in to a vector it all goes wrong.
Basically, the program continues to run but the player doesn't render to the screen. When I quit the program, I then get a breakpoint error when main tries to return MSG. The comment about the breakpoint reads:
/*
* If this ASSERT fails, a bad pointer has been passed in. It may be
* totally bogus, or it may have been allocated from another heap.
* The pointer MUST come from the 'local' heap.
*/
_ASSERTE(_CrtIsValidHeapPointer(pUserData));
I have located the error to here
strcat(nameCard, nameChar);
strcat(nameCard, genderChar);
strcat(nameCard, ageChar);
strcat(nameCard, cashHeldChar);
strcat(nameCard, productWantedChar);
within the playerCard class because when I comment this out, I do not get the error. Here is the full playerCard class (Again, it is messy and probably the wrong way for going about things but I am trying to get my head round using chars/strings etc)
#include "Headers.h";
class Playercard{
private:
RECT textbox;
LPD3DXFONT font;
std::string nameStr;
std::string genderStr;
std::string ageStr;
std::string cashHeldStr;
std::string prodWantedStr;
char nameCard[1000];
public:
Playercard()
{
}
void load(char* name, bool male, int age, double cash, char* prod)
{
if(male)
{
genderStr = "Gender: Male\n";
}
else
{
genderStr = "Gender: Female\n";
}
nameStr = "Name: " + static_cast<std::ostringstream*>( &(std::ostringstream() << name))->str() + "\n";
ageStr = "Age: " + static_cast<std::ostringstream*>( &(std::ostringstream() << age))->str() + "\n";
cashHeldStr = "Cash Held: " + static_cast<std::ostringstream*>( &(std::ostringstream() << cash))->str() + "\n";
prodWantedStr = "Product Wanted: " + static_cast<std::ostringstream*>( &(std::ostringstream() << prod))->str() + "\n";
char * nameChar = new char [nameStr.length()+1];
char * genderChar = new char [genderStr.length()+1];
char * ageChar = new char [ageStr.length()+1];
char * cashHeldChar = new char [cashHeldStr.length()+1];
char * productWantedChar = new char [prodWantedStr.length()+1];
strcpy(nameChar, nameStr.c_str());
strcpy(genderChar, genderStr.c_str());
strcpy(ageChar, ageStr.c_str());
strcpy(cashHeldChar, cashHeldStr.c_str());
strcpy(productWantedChar, prodWantedStr.c_str());
strcat(nameCard, nameChar);
strcat(nameCard, genderChar);
strcat(nameCard, ageChar);
strcat(nameCard, cashHeldChar);
strcat(nameCard, productWantedChar);
diagFile.open("Diag.txt");
diagFile.write("Test", 100);
diagFile.close();
}
void setUp(int L, int T, int R, int B)
{
SetRect(&textbox, L,T,R,B);
}
void draw()
{
font->DrawTextA(d3dSprite, nameCard, -1, &textbox, DT_LEFT, D3DCOLOR_XRGB(255, 255, 255));
}
LPCSTR plCard()
{
return nameCard;
}
};
Any help would be greatly appreciated. Thank you.
Your nameCard is uninitialized. Replace the first strcat with strcpy, or initialize it with a zero string.
Now, how about using std::string exclusively?
Your main problem is that nameCard is uninitialized. strcat requires a null-terminated string to do its magic, and there's no guarantee that the first, or any, character in nameCard is a null.
However, C strings are unnecessary. Just use std::string all the time. After changing nameCard to a string, I'd change load to (file writing excluded):
void load(const std::string &name, bool male, int age, double cash, const std::string &prod)
{
nameStr = "Name: " + name + "\n";
genderStr = "Gender: " + (male ? "Male" : "Female") + "\n";
ageStr = "Age: " + std::to_string(age) + "\n";
cashHeldStr = "Cash Held: " + std::to_string(cash) + "\n";
prodWantedStr = "Product Wanted: " + prod + "\n";
nameCard = nameStr + genderStr + ageStr + cashHeldStr + prodWantedStr;
}
I would actually just make nameCard a data member, removing the others, and use this:
nameCard.clear();
nameCard += "Name: " + name + "\n";
//add on other parts
Other than that, make plCard() return a std::string and in draw(), use nameCard.c_str(). I hope that clears up what you can do with strings a bit more.
Do note, however, that std::to_string is C++11. C++03 has two common solutions:
std::string str = boost::lexical_cast<std::string>(someNumber);
Or
std::ostringstream oss;
oss << someNumber;
std::string str = oss.str();
I find the three-liner much more readable than a one-liner or two-liner.