lundi 28 janvier 2019

Sorting or printing of set of objects is incorrect

I truly don't know whether my sorting or my printing of a set of obejcts is wrong but when I print the whole set, the result is unsorted AND it contains one duplicate. The object Person has a surname, a familyname and year of birth (all 3 are strings). I first sort by year of birth, then by familyname and then by surname. Per se, there are no identical persons (but even if was the case, it should be eliminated as they get inserted into the set ).

To be more concrete, I create a set of persons like this:

std::set <Person> greatUncles; 

and insert them like this:

greatUncles.insert(Person("bla", "bla", "1900"));

Here's are the essential things from class Person:

class Person {
public:
  ...

  Person(std::string s, std::string f, std::string y)
    :surname(s), familyname(f), yearOfBirth(y)
  {
  }

  ...

  std::string getSurname() const {
    return surname;
  }

  std::string getFamilyname() const {
    return familyname;
  }

  std::string getYearOfBirth() const {
    return yearOfBirth;
  }

private:
  std::string surname;
  std::string familyname;
  std::string yearOfBirth;
};

//to print the set, overload the '<<' operator
std::ostream &operator<<(std::ostream &o, const Person &person) {
  o << person.getSurname() << " "
    << person.getFamilyname() << " "
    << person.getYearOfBirth() << std::endl;
  return o;
}

//to order the set, overload the '<' operator
bool operator< (Person const &p1, Person const &p2) {
  int compareYearOfBirth = p1.getYearOfBirth().compare(p2.getYearOfBirth());

  if (compareYearOfBirth == 0) {
    int compareFamilyname = p1.getFamilyname().compare(p2.getFamilyname());
    if (compareFamilyname == 0) {
      return p1.getSurname().compare(p2.getSurname());
    } else
      return compareFamilyname;
  } else
    return compareYearOfBirth;
}

and here is how I print the set of great-uncles:

void printGreatUncles(std::set <Person> &greatUncles) {
    std::ofstream outputFile;
    outputFile.open("greatuncle.dat");

    if (outputFile.is_open()) {
      for(Person const & person:greatUncles) {
        outputFile << person;
      }
      outputFile.close();
    }
  }

Now the output in a certain case should look like this (sorted by year):

Sebastian Furtweger 1942
Nikolaus Furtweger 1951
Archibald Furtweger 1967

but it looks like this:

Archibald Furtweger 1967
Sebastian Furtweger 1942
Nikolaus Furtweger 1951
Archibald Furtweger 1967

I can't figure it for my life what (things) I'm doing wrong.

C++ Operator<< Overloading to Print Member Variable Values

All -- I have checked existing discussion topics and/or questions on this, and none seems to address this. Hence posting this question. Happy to be referred to an existing link that might already be addressing this exact issue, if I overlooked it.

Below is my snippet of code:

class MyBook{
  public:
    MyBook(): bidPrices(10, 0.0),
              askPrices(10, 0.0),
              bidSizes(10, 0),
              askSizes(10, 0) {}
    std::vector<double> bidPrices;
    std::vector<double> askPrices;
    std::vector<int> bidSizes;
    std::vector<int> askSizes;
};

// Forward declaration
std::unordered_map<std::string, std::unique_ptr<MyBook>> myBookMap;

// Overload << to print.

std::ostream&* operator<<(std::ostream& os, MyBook& mbk)
{
  os << "bid price: " << mbk.bidPrices[0] <<  " "
     << "bid size: " << mbk.bidSizes[0] <<  " "
     << "ask price: " << mbk.askPrices[0] <<  " "
     << "ask size: " << mbk.askSizes[0] << endl;
  return os;
}

Later inside main():

std::unordered_map<std::string, std::unique_ptr<MyBook>>::iterator it = myBookMap.begin();
while (it != myBookMap.end())
{
  std::cout << it->first;
  std::cout << it->second;
}

At compile time, I see "error: no match for 'operator<<'" error.

It possibly couldn't be because of the differing data types between sizes and prices, and even if it is that, I don't see how I can use a template for that when I am passing in the object (mbk) as opposed to a vector (int vector vs. double vector) as the argument to the operator<< overloading function.

Thanks for any insights. Happy to be crucified, although I'm still a newbie.

Best wishes.

Can anyone tell me whats wrong with my code?

I'm new to programming and to c++. If this sounds stupid then you know why. I'm having problems with my code. For some reason, not all strings with 4 letters don't go to my array when I made a function to make that happen. Plus, strings with 6 letters also go to my array that are only supposed to store in 4 or anything that the user wants to put.

I've tried a lot that I can't even list them down.

#include <iostream>
#include <string>
#include <windows.h>

using namespace std;

int main()
{
    string LetterInput, LetterLoad, input;
    string Words[] = {"camera","lotion","fire","eggs","roll"};
    string PossibleAnswers[] = {};
    int Number;
    int Size;
    bool YesorNo = false;

cout << "Lets play HANGMAN! " << endl;
Sleep(500);

cout << "Think of a word and type in the number" << endl;
cout << "of letters there are" << endl;
cin >> Size;

for (int i = 1; i <= Size; i++){
    LetterLoad += "_";
}

for (int i = 0; i <= sizeof(Words)/sizeof(string); i++){
    if (Size == Words[i].size()){
        PossibleAnswers[i] = Words[i];
    }
}

cout << PossibleAnswers[0] << endl;
cout << PossibleAnswers[1] << endl;

My expected results are for the array to only show "fire","eggs","rolls" in that order. But the actual results are, "camera","lotion","fire","eggs". Lol what is the problem.

A variadic function that accepts Strings and Ints, Format the latter and concatenate all?

I'm trying to use the answer from DanielKO in this question for my needs but i'm not familiar with templates and variadic functions, and i don't get what should i do.

What i'd need is a variadic c++(11) function which i can call like this:

 String NewMsg = CreateMessage("SET",16,1,17,0,"RED",47);

and have NewMsg= "SET,0010,0001,0011,0000,RED,002F".

I'm not even able to get where should i add the comma between the arguments. And then: How could i distinguish between integers and string while parsing the args, so to format each integer to hexadecimal strings?

how enable to enable diffrent output directory with diffrent envirement build settings in vscode?

I have a cmake program that run on both x86 and arm, so i need two build configurations and two output build directories.

how is it possible to add different build directory and settings?

Using range-based for loop with CGAL types

Consider a CGAL::Arrangement_2. Right now, I have to iterate through it like this:

using MyArrangement = CGAL::Arrangement_2<MyTraits, MyDcel>;
for(MyArrangement::Face_handle face = map.faces_begin(); face != map.faces_end(); ++face)
{
    do_stuff(face);
}

If I try to migrate this to using a C++11-style range-based for loop like this:

for(auto face : gMap)
{
    do_stuff(face)
}

I get the following error (emphasis mine):

Error:(1385, 13) invalid range expression of type 'CGAL::Arrangement_2 > >, true>, std::__1::vector > >, true> >, std::__1::allocator > >, true> > > >, CGAL::Arr_consolidated_curve_data_traits_2 > >, true> >, int> >, CGAL::Arr_extended_dcel > >, true>, std::__1::vector > >, true> >, std::__1::allocator > >, true> > > >, CGAL::Arr_consolidated_curve_data_traits_2 > >, true> >, int> >, GIS_vertex_data, GIS_halfedge_data, GIS_face_data, CGAL::Arr_vertex_base > >, true> > >, CGAL::Gps_halfedge_base > >, true> >, CGAL::_Unique_list > >, CGAL::Gps_face_base> >'; no viable 'begin' function available

The error is the same if I change the for loop to use auto &face or const auto &face.

Does anyone have a workaround for this, or some nice wrapper to make it work? I'm trying to avoid having to resort to using this monstrosity with a lambda argument:

template<typename F>
void for_each_face(MyArrangement &map, F callback)
{
    for(MyArrangement::Face_handle f = map.faces_begin(); f != map.faces_end(); ++f) 
    {
        callback(f); 
    }
}

C++11 rvalue issue

I don't know how come the following example output, can anyone tell me? Thanks in advance!

#include <iostream>
#include <algorithm>

class A
{
public:

    // Simple constructor that initializes the resource.
    explicit A(size_t length)
        : mLength(length), mData(new int[length])
    {
        std::cout << "A(size_t). length = "
    << mLength << "." << std::endl;
    }

    // Destructor.
    ~A()
    {
  std::cout << "~A(). length = " << mLength << ".";

  if (mData != NULL) {
            std::cout << " Deleting resource.";
      delete[] mData;  // Delete the resource.
  }

  std::cout << std::endl;
    }

    // Copy constructor.
    A(const A& other)
      : mLength(other.mLength), mData(new int[other.mLength])
    {
  std::cout << "A(const A&). length = "
    << other.mLength << ". Copying resource." << std::endl;

  std::copy(other.mData, other.mData + mLength, mData);
    }

    // Copy assignment operator.
    A& operator=(const A& other)
    {
  std::cout << "operator=(const A&). length = "
           << other.mLength << ". Copying resource." << std::endl;

  if (this != &other) {
      delete[] mData;  // Free the existing resource.
      mLength = other.mLength;
            mData = new int[mLength];
            std::copy(other.mData, other.mData + mLength, mData);
  }
  return *this;
    }

    // Move constructor.
    A(A&& other) : mData(NULL), mLength(0)
    {
        std::cout << "A(A&&). length = " 
             << other.mLength << ". Moving resource.\n";

        // Copy the data pointer and its length from the 
        // source object.
        mData = other.mData;
        mLength = other.mLength;

        // Release the data pointer from the source object so that
        // the destructor does not free the memory multiple times.
        other.mData = NULL;
        other.mLength = 0;
    }

    // Move assignment operator.
    A& operator=(A&& other)
    {
        std::cout << "operator=(A&&). length = " 
             << other.mLength << "." << std::endl;

        if (this != &other) {
          // Free the existing resource.
          delete[] mData;

          // Copy the data pointer and its length from the 
          // source object.
          mData = other.mData;
          mLength = other.mLength;

          // Release the data pointer from the source object so that
          // the destructor does not free the memory multiple times.
          other.mData = NULL;
          other.mLength = 0;
       }
       return *this;
    }

    // Retrieves the length of the data resource.
    size_t Length() const
    {
        return mLength;
    }

private:
    size_t mLength; // The length of the resource.
    int* mData;     // The resource.
};

#include <vector>

int main()
{
   // Create a vector object and add a few elements to it.
   std::vector<A> v;
   v.push_back(A(25));
   v.push_back(A(75));

   ::std::cout << "----------------------" << std::endl;

   // Insert a new element into the second position of the vector.
   //v.insert(v.begin() + 1, A(50));
   return 0;
}

ouput:

A(size_t). length = 25.
A(A&&). length = 25. Moving resource.
~A(). length = 0.
A(size_t). length = 75.
A(A&&). length = 75. Moving resource.
A(const A&). length = 25. Copying resource.   // how come these two lines?
~A(). length = 25. Deleting resource.
~A(). length = 0.
----------------------
~A(). length = 25. Deleting resource.
~A(). length = 75. Deleting resource.