Home > Enterprise >  Converting std::list<int> iterator to an CString (MFC)
Converting std::list<int> iterator to an CString (MFC)

Time:06-08

Newbie in world of MFC and MS Windows C .

I am trying to populate a ComboBox dynamically. But I am not able to convert the iterator pointer to CString or an std::string. Here is my sample code:

bool single_digit (const int& value) { return (value >= 60); }

int numArr[] = {10,20,30,40};
int size = sizeof(numArr)/sizeof(numArr[0]);
std::list<int> numList (numArr, numArr size);
numList.remove_if(single_digit);

for(std::list<int>::iterator it=numList.begin(); it!=numList.end();   it)
{
    std::cout << ' ' <<*it;
   /*
   std::string s2(*it); //Not sure of conversion to CString or std::string.
   string *pelement = &*it;
  */
   //End goal: _ccomboBoxnumType.AddString(*it);
}

Can anyone please suggest any other STL to satisfy this requirement?

CodePudding user response:

This is essentially asking how to convert an integer to its string representation. The simplest way to go about this is to call std::to_wstring, that provides an overload taking an int value.

The following code does what you're looking for:

for(std::list<int>::iterator it=numList.begin(); it!=numList.end();   it)
{
   // Get value by dereferencing the iterator
   int value = *it;
   // Convert integer to string
   std::wstring display = std::to_wstring(value);
   // Extract a C-style string pointer compatible with the interface
   wchar_t const* ptr = display.c_str();
   _ccomboBoxnumType.AddString(ptr);
}

Of course, you should be using a range-based for loop instead, i.e.

for(auto value : numList)
{
   _ccomboBoxnumType.AddString(std::to_wstring(value).c_str());
}

In case this doesn't compile make sure to set the character set to Unicode in the project settings. There's no reason not to.

Update to account for the C 98 requirement

std::to_wstring requires C 11. If that is not something that's available to you, you can get the same functionality through e.g. MFC's CString type by using its Format member. Things get slightly more verbose, but not much:

for(std::list<int>::iterator it=numList.begin(); it!=numList.end();   it)
{
   // Get value by dereferencing the iterator
   int value = *it;
   // Convert integer to CString
   CString display;
   display.Format(_T("%d"), value);
   // CString can implicitly be converted to LPCTSTR
   // If you like explicit, pass `display.GetString()` instead
   _ccomboBoxnumType.AddString(display);
}

Note that this is using generic-text mappings (in disguise), a holdover from the days when targeting both Windows NT and Windows 9x was relevant. It is not recommended today, but should fit right in to a code base that requires a C 98 compiler.


A few recommendations to follow:

  • A std::list has unique properties (such as constant time insertion and splicing), at the expense of having to allocate each element on the heap. Since you don't care about any of this, use a std::vector instead.
  • If you need to get the integer value back (e.g. in response to user input) you can store that value inside the Combo Box item. There's CComboBox::SetItemData for that. Alternatively use a CComboBoxEx instead, and set both the text and data in one go by calling CComboBoxEx::InsertItem.
  • Another approach would be setting the item data only, and request the control to retrieve a string representation on demand. That, too, requires using a CComboBoxEx and setting pszText to LPSTR_TEXTCALLBACK in the InsertItem call. The control parent is now responsible for handling the CBEN_GETDISPINFO notification, producing a string representation for the given item.

CodePudding user response:

Easy one.

std::string s2 = std::to_string(*it);

Seems your code could be a lot simpler though, there is no need to construct a list

for (int i : numArr)
{
    std::string s2 = std::to_string(i);
    ...
}
  • Related