LanguagesHottest Forum Q&A on CodeGuru - September 4th

Hottest Forum Q&A on CodeGuru – September 4th

Introduction:

Lots of hot topics are covered in the Discussion Forums on CodeGuru. If you missed the forums this week, you missed some interesting ways to solve a problem. Some of the hot topics this week include:


How to Work efficiently with std::sort() ?
(top)

Thread:

Ayumi was seeking help for an algorithm that allows simple sorting for an array:

Can I know how to use the <algorithm> sort function in C++?

Ayumi had the following array and needed the results that follow:

Array:

vector[0] = abc_11_xyz.txt;
vector[1] = abc_1_xyz.txt;

Desired Result:

vector[0] = abc_1_xyz.txt;
vector[1] = abc_11_xyz.txt;

rxbagain suggested to use the function qsort:

int sortfunc(const void *elem1, const void *elem2)
{
   return strcmp(*((LPSTR*)elem1), *((LPSTR*)elem2));
}

...

LPSTR strs[] = {"String4", "String1", "String3", "String2"};
qsort(&strs[0], 4, sizeof(strs[0]), sortfunc);

This function is not the best solution for sorting STL types like ‘vector’. You should avoid qsort for the following reasons:

  • qsort() is not guaranteed to work with non-POD types (structures and classes)
  • qsort() is not type-safe, casting is needed
  • qsort() is old C-Style
  • qsort() is slow in comparision to qsort(), because the C++ templates generates optimized code for a particular data-type
  • qsort() needs a function to compare the elements

The best solution to make a sort is to use the std::sort function; however, let’s get back to Ayumi’s problem of Ayumi. What do you think if Ayumi uses the std:sort function with the following code, will he get the desired result ?

#include "stdafx.h"
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <conio.h>

using namespace std;
#pragma warning(disable:4786)

int main()
{
  std::vector<string> StringArray;

  StringArray.push_back("abc_11_xyz.txt");
  StringArray.push_back("abc_1_xyz.txt");

  std::sort(StringArray.begin(), StringArray.end());
  // Print results

  for(std::vector::iterator iter = StringArray.begin();
    iter != StringArray.end();
    ++iter)
    std::cout << *iter << std::endl;

  // Wait for keystroke
  _getch();
}

Try this code and you will see that the output is the following:

abc_11_xyz.txt;
abc_1_xyz.txt;

But that is not the desired result! Do you know what went wrong? Does the sort not work like excepted?

Actually, the sort worked perfectly. Try to enter some other values in the array and you will see that the sort works, but the where is the problem?

The problem is that the underscore that comes after the ‘1‘ in the ASCII collating sequence. Thats why we got this output. But the problem is still not solved! The solution is to sort the characters between the underscore characters. In our case “11” and “1“.

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
#include <conio.h>

using namespace std;

struct sort_between_underscores
{
  int ToInt(const std::string& str)
  {
    int x;
    std::stringstream ss(str);
    ss >> x;
    return x;
  }
  int BetweenUnderscores(const std::string& StrinArray)
  {
    std::string::size_type pos1 = StrinArray.find("_");
    std::string::size_type pos2 = StrinArray.find("_",pos1+1);
    return ToInt(StrinArray.substr(pos1+1,pos2-pos1-1));
  }

  bool operator()(const std::string& lhs, const std::string& rhs)
  {
    return BetweenUnderscores(lhs) < BetweenUnderscores(rhs);
  }
};

int main()
{
  std::vector<std::string> StrinArray;
  StrinArray.push_back("abc_11_xyz.txt");
  StrinArray.push_back("abc_1_xyz.txt");
  StrinArray.push_back("abc_111_xyz.txt");
  StrinArray.push_back("abc_2_xyz.txt");

  std::sort( StrinArray.begin(), StrinArray.end(),
             sort_between_underscores());

  std::vector<std::string>::iterator it;
  for (it = StrinArray.begin(); it!=StrinArray.end(); ++it)
  { 
    std::cout << *it << std::endl;
  }
  _getch();
}

That’s it; the result is achieved. But, there are still some questions.

  • Do I need to delete the vector after usage?
  • What happens if I have an another format of the file names?

Take a look at the thread and you will get the answer to these additional questions!


How to find a specific entry in std::vector<>?
(top)

Thread:

Well, this is again a question regarding the STL. StevenS is looking for solution to find a specific entry in the vector. Actually, he is looking for the find function. Right?

How do I test to see whether or not a vector contains a specific entry? I’ve looked all over the MSDN doc on std::vector and I don’t see anything.

For example:

std::vector<int> myVector;
myVector.push_back(10);
myVector.push_back(20);
myVector.push_back(30);

Aside from looping through the vector manually, what do I do to determine if the vector contains the value 20?

As always, Paul McKenzie is one of the people on CodeGuru who suggested the right solution for StevenS’s problem. The std::find function provides the the possibility to find an entry in a vector without looping. Here is the code:

#include <vector>
#include <iostream>
#include <algorithm>

int main()
{ 
  std::vector<int> myVector;
  myVector.push_back(10);
  myVector.push_back(20);
  myVector.push_back(30);

  std::vector<int>::iterator it =
       myVector.find(myVector.begin(), myVector.End(), 20);
  if(it != myVector.end())
  {
    std::cout << "Found the element at position" <<
           std::distance(myVector.begin(), it);
    std::cout << endl;
    std::cout << *it;
  }
}

Try this code and you will see that the searched entry position is found easily.


Is ++i better than i++?
(top)

Thread:

zoltan_ie asked a very interesting question:

Postfix increment and decrement operators create a temporary object when used while prefix operators don’t.

It is therefore more efficient to use the prefix version where possible, particularly in for loop constructs as whatever is used will be called multiple times in that case, i.e., we should use:

for (int nType = 0; nType < MM_NUM_TYPES; ++nType)
{
   ?
}

Is ++i really faster then i++ ? If yes, why it is faster?

If incrementing is all that you want to do (you are not assigning the variable to something else), then yes this is a good practice, especially if you are using the increment operator on a class.

// Prefix operators are preferred in cases in the
// following common cases:

for (;checkstate(x);++x) dosomething(x);
  ++x;

For standard data types, there is no performance difference, but for classes there are! The reason is that (for most common implementations of) postfix operators retain a temporary copy of original variable and because the return value is returned by value, not by reference. The following code exemplifies this:

class MyClass
{
public:
  MyClass& operator++()       //Prefix increment operator  (++x)
  {
    //Perform increment operation
    return *this;
  } 

  MyClass  operator++(int)    //Postfix increment operator (x++)
  {
    MyClass temp = *this;
    //Perform increment operation
    return temp;
  }
};


What is the difference between const vs. enum
(top)

Thread:

Although this is again a very simple question, I think this can be very useful to many readers. In this thread, indiocolifa, we want to know whether the following definition:

enum { cg = 1 };

is better than this:

const int cg = 1;

What do you think? Well, it actually depends on whether you need a single value or multiple values. If you need a single value, you should go for a constant; whereas const can not be used in the class declaration. You can declare const either in a function or a structure. To use const in a class initialization, the constant must be a static const.

class X
{
  static const int cg = 1;
}

An enum can be defined also in a class.

class X
{
  enum {cg = 1};
}

Most coders tend to use enum because it is portable and does not use non-standard extensions of the in-class initialization.


What is the difference between delete and delete[]?
(top)

Thread:

In this thread, Hopplos, a junior member, wants to know when to use delete and delete[].

Well, actually the answer is simple. delete[] is always used whenever you allocate memory with new[].

int *pi_array = new int[10];
delete [] pi_array;

If you use delete pi_array, this will only delete pi_array[0] and all others are left undestroyed.

Whenever you allocate memory with new, then use delete.

int *pi = new int;
delete pi;

Here you can use delete pi because it is not an array. You wont get any asserts or access violations.


How to use Unicode Characters in a DC?
(top)

Thread:

In this thread post68 want to know which character should be set to display unicode characters in DC.

What character set should i use to display Unicode characters in
a DC? ie - Arial or courier?

Well, it actually depends on the type of unicode characters. According to Zhefu Zhang, you can use a font called “SimSun” that comes with Win2k, but should surely also be available to download on several Web sites. If you are going to use this font for your edit box or richedit box, you just need to call SetFont and you are ready to use it. If you are going to draw something, you can use the unicode function TextOutW or DrawTextW.


Why should I link to a lib when the header file is included?
(top)

Thread:

Dullboy is a bit confused. He wants to know why should he link a LIB file when a header file has been already inluded.

Why would we need to link a LIB file if a header file has been
included? When would we need to link a LIB file?

Actually, the header only contains the function/prototypes, wheras the real code resides in the DLL or LIB. If you just include the header without linking to the LIB or DLL, you get a fatal error. A normal LIB is always linked as static. If you specify a DLL, it gets linked dynamically.

Two main rules to remember:

  • Include header files to make the compiler happy.
  • Link the LIB files to make the linker happy.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories