Adding std::string values to CListBox ends up as gibberish - mfc

OK, what is wrong with this?
void CMFCApplication1Dlg::OnBnClickedOk()
{
std::vector<std::string> vectorList;
try
{
CMSAToolsLibraryWrapper wrapper;
__int64 lResult = wrapper.SetDatabasePath(std::string("d:\\Test.xml"));
__int64 iNumPublishersRead = 0;
if (wrapper.ReadPublisherData(iNumPublishersRead))
{
vectorList = wrapper.GetPersonnelNames(true);
for (std::string& strName : vectorList)
{
m_lbNames.AddString((LPCTSTR)strName.c_str());
}
}
}
catch(_com_error *e)
{
AfxMessageBox(_T("Problem"));
}
//CDialogEx::OnOK();
}
If I place a breakpoint on the AddString call the strName value is correct. But my CListBox ends up with Chinese characters. Why ?

You're sending char strings to a function that requires wchar_t strings. The (LPCTSTR) cast is masking the error message that would have told you what was wrong.

This works:
void CMFCApplication1Dlg::OnBnClickedOk()
{
std::vector<std::string> vectorList;
try
{
CMSAToolsLibraryWrapper wrapper;
__int64 lResult = wrapper.SetDatabasePath(std::string("d:\\Test.xml"));
__int64 iNumPublishersRead = 0;
if (wrapper.ReadPublisherData(iNumPublishersRead))
{
vectorList = wrapper.GetPersonnelNames(true);
for (std::string& strName : vectorList)
{
CString strName2(strName.c_str());
m_lbNames.AddString(strName2);
}
UpdateData(FALSE);
}
}
catch(_com_error *e)
{
AfxMessageBox(_T("Problem"));
}
}
Putting the std::string into a CString first and then passing that with AddString works.

Related

Replace Function C++ vb.net

i´m new in C++ and my first function is the replace function from vb.net.
I want to know how to make this function perfect.
Should i wrote a "function" with return value instead of void?
(Sorry about my english)
void ReplaceAll(std::string &source, std::string find, std::string replace) {
if (find.length() == 0) {
return;
}
int _offset = 0;
while (true) {
_offset = source.find(find, _offset);
if (_offset == -1) {
return;
}
source.replace(_offset, find.length(), replace);
}
}

How to separate a CString in MFC

I have a string like this: DialogTitle = IDD_SETTING_DLG in a save file (i have already stored it in an array called m_TextArray).
Now i want to get the "IDD_SETTING_DLG" part(or at least " IDD_SETTING_DLG") and store it in a CString variable. I used the Tokenize method but it didn't work.
Here are my codes:
BOOL CTab1::OnInitDialog()
{
UpdateData();
ReadSaveFile();
SetTabDescription();
UpdateData(FALSE);
return TRUE;
}
void CTab1::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_SHOWDES, m_ShowDes);
}
void CTab1::ReadSaveFile()
{
if (!SaveFile.Open(SFLocation, CFile::modeRead | CFile::shareDenyWrite, &ex))
{
ReadSettingFile();
}
else
{
for (int i = 0; i < 100; i++)
{
SaveFile.ReadString(ReadLine);
m_TextArray[i] = ReadLine.GetString();
}
}
}
void CTab1::SetTabDescription() //m_TextArray[2] is where i stored the text
{
Position = 0;
Seperator = _T("=");
m_ShowDes = m_TextArray[2].Tokenize(Seperator, Position);
while (!m_ShowDes.IsEmpty())
{
// get the next token
m_ShowDes = m_TextArray[2].Tokenize(Seperator, Position);
}
}
Anyone solution or hint would be very appreciated.
Since you're merely looking for the part of the string that occurs after a token, there's no need to use Tokenize. Just find the position of the token character (your "=") and get everything after that:
void CTab1::SetTabDescription() //m_TextArray[2] is where i stored the text
{
CString separator = _T("=");
CString source = m_TextArray[2];
// Get position of token...
int position = source.Find(separator);
// If token is found...
if (position > -1 && source.GetLength() > position)
m_ShowDes = source.Mid(position + 1); // extract everything after token
}

How to define a function to return a pointer to a "" value when no matching data is found?

I want my function() to always return a "" string under error conditions else return a string that is converted to string from an unsigned long integer variable.
My initial implementation is as follows:
uint32 cfgVariable_1 = 4;
uint32 cfgVariable_2 = 1;
const char* getCfgVariable (const char* msg)
{
char* retValue = "";
if(strcmp("cfgVariable_1", msg)==0)
{
// Since I want my function to return a const char* and returning uint32_t is not an option
sprintf((retValue), "%lu", cfgVariable_1);
return (const char*)retValue;
}
else if(strcmp("cfgVariable_2", msg)==0)
{
// Since I want my function to return a const char* and returning uint32_t is not an option
sprintf((retValue), "%lu", cfgVariable_2);
return (const char*)retValue;
}
else
{
//error
}
return (const char*) retValue;
}
When the function is called at different instances to get the cfgVariables, I expect my function getCfgVariable() to return "" on error condition, when no match found.
Somewhere in code:
const char* CfgValue = NULL;
CfgValue = getCfgVariable("cfgVariable_1");
Here CfgValue gets pointed to location which contains 4
later
const char* CfgValue = NULL;
CfgValue = getCfgVariable("cfgVariable_3");
I expect to get a "" back but I get 4 instead (CfgValue gets the same address as before).
Fix implemented by me works, but I fail to understand the logic behind it, fix:
const char* getCfgVariable (const char* msg)
{
const char* defValue = "";
char* retValue = "\0";
if(strcmp("cfgVariable_1", msg)==0)
{
// Since I want my function to return a const char* and returning uint32_t is not an option
sprintf((retValue), "%lu", cfgVariable_1);
return (const char*)retValue;
}
else if(strcmp("cfgVariable_2", msg)==0)
{
// Since I want my function to return a const char* and returning uint32_t is not an option
sprintf((retValue), "%lu", cfgVariable_2);
return (const char*)retValue;
}
else
{
//error
}
return defValue;
}
I see during debugging that defValue and retValue get pointed to two different locations that do not get overwritten. defValue always gets pointed to the same address when its initialized with "" and retValue gets pointed to a different address when initialized with "\0". Can anyone explain the logic behind this ? Is there a better implementation for my use case ?
My Solution after considering the comments:
const char* getCfgVariable (const char* msg)
{
const char* retValue = "";
std::ostringstream oss;
if(!strcmp("cfgVariable_1", msg))
{
oss << cfgVariable_1;
}
else if(!strcmp("cfgVariable_2", msg))
{
oss << cfgVariable_2;
}
else
{
//error
return retValue;
}
const std::string tmp = oss.str();
retValue = tmp.c_str();
return retValue;
}
Thanks for the comments so far and this solution is still open to further improvement suggestions.
Constexpr strings such as "\0", "", "cfgVariable_1", etc. These are constant strings in memory compiled into your resulting executable. Attempting to write values into those strings is downright dangerous! In old style C, you'd have to use malloc to allocate a bit of memory to use for your string. This is a real pain to deal with in practice (and not ideal for someone who's learning C++).
A far simpler solution is to start using the C++ string object, std::string (which handles all of the dynamic memory allocation for you!). This should reduce your problem to something a little simpler (and most importantly, safer!):
#include <string>
#include <sstream>
std::string getCfgVariable (const char* const msg)
{
std::ostringstream oss;
if(!strcmp("cfgVariable_1", msg))
{
oss << cfgVariable_1;
}
else
if(!strcmp("cfgVariable_2", msg))
{
oss << cfgVariable_2;
}
return oss.str();
}
Doing this in C, you have 2 choices. Allocate the memory for the returned string, or use a static buffer that is always available (which is what this example does).
uint32 cfgVariable_1 = 4;
uint32 cfgVariable_2 = 1;
const char* getCfgVariable (const char* msg)
{
static char retValue[32] = {0};
if(strcmp("cfgVariable_1", msg)==0)
{
// Since I want my function to return a const char* and returning uint32_t is not an option
sprintf(retValue, "%lu", cfgVariable_1);
return retValue;
}
else if(strcmp("cfgVariable_2", msg)==0)
{
// Since I want my function to return a const char* and returning uint32_t is not an option
sprintf(retValue, "%lu", cfgVariable_2);
return retValue;
}
else
{
//error
}
return retValue;
}
However, because now the retValue is an array fixed in memory, the string returned would only be valid until the next call to getCfgVariable, which could be a little strange....
const char* A = getCfgVariable("cfgVariable_1");
printf("%s\n", A); // prints '4'
const char* B = getCfgVariable("cfgVariable_2");
printf("%s\n", B); // prints '1'
printf("%s\n", A); // now this will print '1', and not '4'.
const char* C = getCfgVariable("anythingElse");
printf("%s\n", C); // prints ""
printf("%s\n", B); // prints ""
printf("%s\n", A); // aso prints ""

GetText is returning a null string for a list box in a MFC program

GetText is returning a null string for a list box in a MFC program:
void CMainDlg::OnLbnSelchangeLiPt()
{
CListBox* lb;
int idx, cnt;
char* cstr;
lb = (CListBox*)GetDlgItem(IDC_LI_PT);
idx = lb->GetCurSel();
cnt = lb->GetCount();
if ((idx != LB_ERR) && (cnt > 0))
{
cstr = NULL;
lb->GetText(idx, cstr);
...
The list box has one selected item. What is wrong with this?
Don't use stuff like char a[32];
You should be using:
CString sData;
int nSel = m_NameListBox.GetCurSel();
if (nSel != LB_ERR)
{
m_NameListBox.GetText(nSel, sData);
}
you can also call m_NameListBox.GetWindowText(sData);
Please also use DataExchange MFC mechanism to map your control to a class variable:
void CSettingsGeneralPage::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_NAME_LISTBOX, m_NameListBox);
}
I found out that I needed to declare a character array with enough space to store the string:
void CMainDlg::OnLbnSelchangeLiPt()
{
CListBox* lb;
int idx, cnt;
char cstr[32];
lb = (CListBox*)GetDlgItem(IDC_LI_PT);
idx = lb->GetCurSel();
cnt = lb->GetCount();
if ((idx != LB_ERR) && (cnt > 0))
{
lb->GetText(idx, cstr);
...

Back to the position of pointer

I have such function:
bool filtruj(char* text, bool(*f)(char)) {
while(*(text)!='\0')
{
bool sprawdzWartosc = f(*(text));
if(sprawdzWartosc)
{
printf("run");
b=*(text);
while(b!='\0')
{
printf("run2");
*(text) = *(text+1);
text++;
}
}
}
return false;
}
which when the sprawdzWartosc is true, delete this char and move other characters one to the left.
The question is:
how to back to the position of pointer which is used in var sprawdzWartosc? Becuase when I'm moving characters my pointer is at the end of *(text).
I can't use int, short, long variables, only pointers.
b=*text;
while(b!='\0')
// ...
This just keeps comparing the same character b, and it will never be \0.
Perhaps you wanted to use another pointer?
Here's what I think you were trying to achieve: Live on Coliru
bool filter(char* text, bool(*pred)(char)) {
char* out = text;
while (*text)
{
if (pred(*text))
{
++text; // just skip
} else
{
*out++ = *text++; // copy out
}
}
*out = '\0';
return (out != text); // true if characters were filtered
}
#include <cctype>
#include <cstring>
#include <cstdio>
bool foo(char c)
{
return isalpha((int)(unsigned char)c);
}
void test(const char* input)
{
char* s = strdup(input);
printf("%s -> ", s);
bool b = filter(s, foo);
printf("%s (%s)\n", s, b?"true":"false");
}
int main()
{
test("12346 234890-98 .");
test("12a46 awesome-98!");
}
Printing
12346 234890-98 . -> 12346 234890-98 . (false)
12a46 awesome-98! -> 1246 -98! (true)
I think what you are trying to do is iterate over the body of a string and delete characters for which a call to f returns true.
bool filtruj(char* text, bool(*f)(char)) {
while(*(text)!='\0') {
bool sprawdzWartosc = f(*(text));
if(sprawdzWartosc) {
for (char* cur = text; *cur; ++cur) {
*cur = *(cur+1);
}
}
}
return false;
}
Note that your original code did this
b = *(text);
while (b != '\0')
The assignment, b = *(text) copies the current value at the address text currently points to into the variable b - it does not make b magically track the current value of text.
int i = 5;
int* ptr = &i;
int j = *ptr;
++i;
printf("j = %d\n", j);
prints 5, not 6.