mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

There is generally no difference between using an index or using a pointer. Using pointers is technically faster, but using an index will usually result in the same code once the compiler has optimized it (unless it is really bad at optimizing or that the context makes the preservation of the index value necessary).

So, the idea here is that you should use whatever feels more natural and clear in the context. For example, if I want to fill an array with sequence numbers, I would do this:

int number_seq[100];
for(int i = 0; i < 100; ++i)
  number_seq[i] = i;

Instead of this:

int number_seq[100];
for(int* p = number_seq; p != number_seq + 100; ++p)
  *p = (p - number_seq);

Because the first one is much clearer and more natural. The resulting compiled code is likely to be identical in both cases.

In other words, this is just one of these cases where you can trust the compiler to produce pretty much the best code possible, and all you have to worry about is making it "human-friendly".

Also, in C++, there is strong emphasis on the concept of "iterators", which are a kind of abstract generalization of pointers in the context of traversing a sequence of values (array, list, etc.). And in that sense, using pointers to traverse the array is a "natural" thing to do in C++, but obviously, index-based traversals are preferred in many contexts similar to the example above (and for example, …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

People, this is a signature spam post, look at the OP's signature.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I concur with the others. Without saying what the problem is (how it manifests itself), there is little chance that anyone is going to comb through the code to find the error.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Why study efficiency then? He says it is to buy those more important commodities :)

Or maybe just because it's fun ;)
It's fun and challenging to learn about and apply efficient algorithms. We're entitled to have some fun too, right? Even if it isn't objectively the best use of your "learning-time".

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Yeah, I've noticed that too, i.e., that the compressed air blows particles up under the keys, or more importantly, between the key and switch beneath it. it is a bit annoying as it causes some keys to malfunction a bit (have to press harder) for a little while until things fall back in place. I might try your trick next time.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Yes, I use compressed air as well, it is pretty much the only way to clean it, and it is also sufficient (it clears the dust, which is really the only thing that is dirty'ing up your PC). I guess the only other thing that could be used is a swab of rubbing alcohol, but that is for an extremely thorough cleaning, which you would never really need to do unless there was something major that happened.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Can I use the string data-type for the switch statement or is it limited to the if-else statement?

No. You cannot use string data-type for a switch statement (unless using a special advanced trick). You have to stick with if-else statements.

By the way, what's weird is that, my original code worked after I posted this. Then it stopped working.

Your original code was valid C++ (as in, it can compile), however, the code that the compiler would produce for it is undefined (well, actually, it is implementation-defined), and certainly not what you'd expect it would do.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

AFAIK, for things like compiler lexical analyzers, they use hash tables. This is certainly an option here too (it's even possible to use a hash function in a switch-statement, thanks to constexpr (C++11)).

Another possibility is to use an associative container like std::map<std::string, int> to associate an integer to each string and to a switch based on those integer values.

Another neat little trick is to use a map of lambdas (C++11):

#include <iostream>
#include <string>
#include <functional>
#include <unordered_map>

using namespace std;

int main() {

    string choice;
    cout << "Enter a word >" << endl;
    cin >> choice;

    unordered_map< string, function< void() > > cases;

    cases["ball"] = []() {
      cout << "You entered ball" << endl;
    };
    cases["bike"] = []() {
      cout << "You entered bike" << endl;
    };

    cases[choice]();

}

But I would seem to me that the OP is a bit too early on the learning curve to start doing this kind of stuff, for his basic example, the if-else-if solution with strings is what seems most appropriate.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Die hard

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Well, if one were to go by phrenology, the shape of this "dude"'s head is very telling, and disturbing. The flat shape of the back of his skull indicates that he is devoid of any sense of morality, parenting skills, and capacity to remain faithful to his word (cheating on his wife, etc..). The position of his ears would suggest that he seeks dangerous situations (thrills) and confrontations. The proportions of his face indicate that he has no interest in intellectual pursuits but has a big stomach and a lot of heart at work.

I'm not sure that really corresponds to your average Daniweb member ;)

(in case you didn't know: phrenology is bullshit)

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The problem is that there is no such thing as a "multi-character" type. Something like 'ball' is not valid in C++ (although compilers must accept it, for some odd reason, but the value that the compiler gives to them is not defined). And because "choice" is a character, it will only read one character from the input stream (cin). That is why the whole thing will not work, you are capturing one letter from cin and then comparing it to two things that have undefined values.

I think that what you want is a "string", which is an array of characters (i.e., can represent words). In C++, the standard thing to use to represent strings is std::string from the header <string>. As so:

#include <iostream>
#include <string>

using namespace std;

int main(){
    string choice;
    cout << "Enter a word >" << endl;
    cin >> choice;
    if(choice == "ball") {
        cout << "You entered ball" << endl;
    } else if(choice == "bike") {
        cout << "You entered bike" << endl;
    }
}

Notice that I did not use a switch-statement. This is because strings are more complicated than numbers and cannot be used for switch-statements (they only work for integral number types, like int, char, std::size_t, etc.).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

To be on the safe side, you should add cin.ignore(); after each input from cin.

adil.ghori commented: thank you +0
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Also, just to add, the bulk of day-to-day programming is really really trivial from an algorithmic / computer-science point of view. So, it's hard to make an argument that this is really such an important skill that you should devote most of your "learning" to it. In my opinion, software engineering (i.e., design of the architectures and such), maintainability and quality assurance are the three most important skills to focus your learning on. Most programmers start out being passionate about solving those puzzles (like the topcoder stuff), and that initial learning is probably sufficient for the bulk of all day-to-day programming tasks. What makes the biggest difference are those three areas I mentioned.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Could reading a CLRS and working day and night at topcoder help me?

I would say that it doesn't hurt. From time to time, I pick up on some simple or classic problems to challenge myself a little bit (without having to devote too much time to it). But this is mostly a matter of reviewing the basics, which is useful as it feeds into real-world programming in the form of a place to draw new ideas (from the old ideas) and not miss out on some obviously better ways to do some simple day-to-day programming tasks. But I would not say that it is any kind of significant part of what will make you a "better" programmer in whichever sense of the word.

If one can write an algorithm that is significantly faster than a brute-force one, that is better.

Really? Did you know that you often need quite a large amount of data before a binary search starts to out-perform a simple linear search? A large part of being a good programmer is being able to judge when the effort is worth it and when it is not. This is the hardest thing to learn, and I would say I've still got plenty to learn in that domain. If you can come up with the best possible algorithm for every single problem you face, and you don't have enough common sense to restrain yourself, you are likely to waste inordinate amounts of time for …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

There are really only three options (in C++03, pre-C++11) to pass a parameter: by value, by reference or by const-reference. In the case of the copy-constructor, you cannot pass the parameter by value because to be able to do the copy (of the passed object), you need a copy-constructor, so that's impossible. The remaining options are by reference or const-reference, which I think you know already.

So, this boils down to the difference between a reference and a const-reference. As you said, a reference is a kind of const-pointer in disguise. However, like a pointer, it can refer to either a const or non-const object. So, what a const-reference really means is that you obtain a reference to an object that you are not allowed to modify, which is usually fine for a copy-constructor (i.e., a "copy" usually should not modify the original object). And as per the principle of minimum requirements, you should not require that the object be modifiable if you really don't need to modify it, and that is why you would almost always use a const-reference for the parameter of the copy-constructor (although, technically, you could use a non-const reference too, but you will have some rvalue/lvalue issues).

A const-reference is generally preferred whenever the object could be expensive to copy (or cannot be copied at all, like when it is a parameter to a copy-constructor) and all you really need is to be able to "look" at the object (read-only operations). Non-const references should only …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

This may help, I've compiled with maximum warning levels, using Clang compiler, I get the following warnings:

sales_receipt_prog.cpp:238:1: warning: control may reach end of non-void function [-Wreturn-type]
}
^
sales_receipt_prog.cpp:314:1: warning: control may reach end of non-void function [-Wreturn-type]
}
^
sales_receipt_prog.cpp:263:15: warning: variable 'last' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
          if (s>0)
              ^~~
sales_receipt_prog.cpp:297:50: note: uninitialized use occurs here
          cout<<"*******"<<setw(23)<<first<<" "<<last<<setw(26-len5)<<"********"<<endl;
                                                 ^~~~
sales_receipt_prog.cpp:263:11: note: remove the 'if' if its condition is always true
          if (s>0)
          ^~~~~~~~
sales_receipt_prog.cpp:247:26: note: initialize the variable 'last' to silence this warning
          char first,last;
                         ^
                          = '\0'
sales_receipt_prog.cpp:453:1: warning: control may reach end of non-void function [-Wreturn-type]
}
^
sales_receipt_prog.cpp:523:1: warning: control may reach end of non-void function [-Wreturn-type]
}
^
5 warnings generated.

Addressing those warnings will be a good start to solving the problems (it probably will).

adil.ghori commented: always grateful to you +1
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Is that based on evidence or opinion

Well, I haven't really looked into any "evidence" of that. But I'm sure that any psychologist would concur.

Mostly, I based it on the long-standing tradition of human rights. The right to privacy has been explicitly stated in just about any document of that nature since the dawn of time. The US constitution, the Magna Carta, the Universal Declaration of Human Rights, and I believe even the Code of Hammurabi (1750 BC). I think it is a pretty unaminously recognized.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I'm sorry to say, but without knowledge of basic calculus you can't really do much. It's like asking about how to learn to build a house without knowing how to operate a hammer.

I took some machine learning classes back in the day too, and I don't remember it being very heavy on the calculus (except for "gradient-descent" kinds of methods). The bulk of the math is actually probability theory (Bayesian theory, Markov processes, etc..). And a lot of it is also discrete, in which derivatives don't apply (calculus is for "continuous" variables).

Off the top of my head, I would say that certainly genetic algorithms don't involve any complicated math (at least, to implement the methods), so that's one thing to look into. Another area is, as I've mentioned, discrete systems like Markov Decision Processes (MDP), or Markov chains and hidden Markov models. Markov models are quite simple to understand: you just reduce the agents (actors) down to a few key "states" (e.g., in a computer game, you could have bot states or modes like "hide", "attack", "run away", "seek cover", ..), and then you start to model the way these states transition under different conditions (e.g., if you face an enemy holding an RPG, you might want to transition into the "run away" state!). The whole point of the "learning" part of an MDP is figuring out the best strategy to decide when to switch between states. Similarly, a Hidden Markov Model (HMM) is basically just the reverse, …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

@Klahr_R:

If I understand you correctly, you are saying that people's private information (or more generally, all information) is the new hot commodity on the market, and like any hot commodity it will spurr an economy around it. I certainly agree that this is a fact, I can't say that I'm happy with that reality though.

Information (private or otherwise) has always been a "hot commodity", whether it takes the form of knowing before anyone else that Napoleon fell at Waterloo, or doing insider trading, or doing corporate espionage. But the game has changed now because the means by which one can gather, store, and analyse information at relatively low cost has sky-rocketed. Effectively, as you say, this has created a new economy of its own, i.e., a commodity's market. Whoever has the most means of collecting / storing / analysing information holds the bigger end of the stick. This is certainly frightning to me.

On humanist grounds, I have a problem with the idea of turning something that is essential to any person into a commodity that is open for trade. I equate this to the whole business of privatizing water supplies by simply stating that water is a commercial commodity like any other, and thus, should be owned and distributed with a price-tag. Regardless of the jobs or economy that this can "create" (in fact, it does not), the truth is, it puts a price-tag on people's lives, i.e., if you are not "worth" the air you breath, …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The declarations are marked as const, which is correct. However, your definitions (in cpp file) are not marked const, which makes the declarations incompatible with the definitions. You need to match them exactly:

Declarations:

string get_name() const ;
int get_age() const ;

Definitions:

string person :: get_name() const // <-- notice the 'const' here.
{
    return name;  //<-- notice, you cannot modify 'name' inside this function.
}

int person :: get_age() const // <-- notice the 'const' here.
{
    return age;  //<-- notice, you cannot modify 'age' inside this function.
}

When a function is marked as const, it means that within it, the data members of the object cannot be modified. This is why I removed your code that prompts the user to enter the name or age. You need to do those things in a separate set of functions:

Declarations:

void prompt_for_name();
void prompt_for_age();

Definitions:

void person :: prompt_for_name()
{
    cout << "Please enter the name of the person ";
    getline(cin,name) ;
}
void person :: prompt_for_age()
{
    cout << "Please enter the age of the person " ;
    cin >> age ;
}

That's pretty much it. Enjoy!

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Asking about what they are looking for is pretty bad. It is literally like saying "hey, tell me what you want to hear and I'll echo it right back to you.". It's a very old used-car-salesman trick: tell me what kind of car you need and, just like magic, I'll have exactly the right car for you in my lot. Insulting your interviewer's intelligence like that is not a good idea.

People tend to caution against over-confidence, but I'm not one of them. I think the right attitude coming in an interview is "I'm the best candidate, I just need to make sure they understand that". And as far as knowing what they need in a candidate or what they are looking for, the answer is you, they just don't know it yet, so you have to convince them. And most of the work of an interview is before the interview, when you figure out what the job is, the company is, the things they want to hear are, etc.. You can't come to an interview like you would to a blind date: "just to see if you like each other".

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

they remove use of things like virtual functions (including destructors) that cannot be deterministic.

I'm not sure of that. It would depend on what parts of the kernel you are talking about. For example, the Linux kernel does use dynamic polymorphism (dynamic dispatching / virtual functions) for its file-system management. Virtual functions are not generally excluded from hard real-time applications or things like kernel or embedded code, because virtual function calls are deterministic. A virtual function call is no different from calling a function pointer, which will at most (AFAIK) cause one cache miss. And AFAIK, function pointers are heavily used in kernel code.

Multiple inheritance and virtual inheritance are different though, because they allow for arbitrary long dynamic dispatching paths, and thus, non-deterministic latencies.

When it comes to latency, the main thing to avoid is dispatching paths that have a non-constant dynamic complexity. A simple dynamic dispatch (virtual call) is O(1) with a statically predictable upper-bound on the latency. A cast from a derived class to a virtual base is usually O(N) in the number of occurrences of the virtual base within the inheritance graph (which is determined at run-time). For the same reason, a dynamic-cast from a base class to a derived class is usually O(N) in the total number of derived classes (also only known at run-time). I say "usually" because it's probably possible to do better (with some memory overhead) but the assumption is that it is not better than O(N) for these things.

rubberman commented: Well put - and in some regards I stand corrected. You have waxed more expressive than I was willing to do... :-) +12
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I tried this, but i get debug assertion failed.

My guess is that you shouldn't use delete to deallocate the string's memory which was allocated with strdup (which is not a standard function, btw). Conventionally, it is probably safer to assume that its memory was allocated with malloc, and thus, should be deallocated using the free function:

~CObject() { free(mName); };

Following my tutorial on the Big Five, the proper way to implement the CObject class is as such:

// since strdup is not standard, but very useful, I implement my own (uses 'new'):
char* my_strdup(const char* rhs) {
  if(rhs) {
    std::size_t len = std::strlen(rhs);
    char* result = new char[len + 1];
    std::memcpy(result, rhs, len + 1);
    return result;
  } else
    return nullptr;
};

class CObject
{
  private:
    char* mName;

  public:
    CObject(const char* name = "") : mName(my_strdup(name)) {}

    CObject(const CObject& rhs) : mName(my_strdup(rhs.mName)) {}

    CObject(CObject&& rhs) : mName(rhs.mName) { rhs.mName = nullptr;  }

    // all base-classes must have a virtual destructor:
    virtual ~CObject() { delete[] mName; }

    friend void swap(CObject& lhs, CObject& rhs) {
      char* tmp = lhs.mName;
      lhs.mName = rhs.mName;
      rhs.mName = tmp;
    }

    CObject& operator=(CObject rhs) {
      swap(*this, rhs);
      return *this;
    }

    const char* Name() const { return mName; }
};
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I think it's slightly off, but close. A typical point that is raised when discussing the idea of writing kernel code (or similar high-performance low-level code) in C++ is that operations such as new, delete and dynamic_cast (not static_cast) do not have a deterministic timing (or latency). In other words, when you are talking about simple operations, such as an integer addition (c = a + b;), the operation will translate to a few machine instructions that will execute in a finite and predictable amount of time (number of clock cycles). At the level of kernel code, this kind of predictable latency is a very important thing (e.g., if you are writing the kernel's task scheduler to switch between execution threads, then you need to be able to estimate a guaranteed upper-bound on the time required for your scheduler to do its work or for the time that it will take the wake-up a sleeping thread, and so on...).

Now, operations like new / delete (or malloc / free), which would need to be implemented differently for kernel code, cannot have a predictable latency or even a guaranteed upper-bound on it. This is because the time that it will take for the heap to find a proper chunk of memory to allocate is simply not predictable as it depends on the amount of memory currently being managed, on the amount of memory still available, and on the level of fragmentation of the RAM memory. So, any kernel coder who is …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Using C++, you can ask the operating system to set voltage values on those connectors. Some operating systems will only allow you to set it to low (usually zero volts) or high (some other value, 5V comes to mind, but it's hardware dependent). If the operating system is happy to, it will then change the voltage values on those connectors. If you have connected some other hardware to that connector, you can use those voltage changes to communicate. This is what happens when you plug something into a USB socket. You can also ask the operating system to read the voltage at those connectors.

That is a rather unfortunate explanation. I understand what you meant to explain, but the chosen example makes the explanation completely wrong. Most things like USB ports, serial ports, or any other kind of port, have many layers of circuitry (some just plain old circuits, others being programmable logic units) before it gets anywhere near the main "PC" (i.e., the CPU instructions), never mind the operating system. Usually, for a thing like a USB port, you'll have a port controller that listens to incoming data and can output data with the USB protocol, this will be a simple programmable logic unit (a very tiny micro-controller), most often a PIC (Peripheral Interface Controller). Then, there can be a number of additional steps, such as multiplexing, driving a bus (e.g., PCI / PCIe), and so on, most of which are achieved with a combination of PICs …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I don't see any reason for the ExposedA and ExposedB classes to enter the inheritance scheme at all. And also, from your simple example, I don't see any reason for B to inherit from A, but I assume that in your real this is needed.

Anyhow, the point is that ExposedA and ExposedB classes should probably just be wrappers of A and B objects. To get access to their protected / private parts, you would just need to have them either as friend classes or as nested classes. I tend to prefer the nested classes, as so:

class A
{
  protected:
    int a;

  public:
    int getA() const { 
      return a;
    }

    // nested accessor class:
    class exposed {
      protected:
        A* p_a;

      public:
        explicit exposed(A& aRA) : p_a(&aRA) { };

        const exposed& setA(int aA) const { p_a->a = aA; return *this; }
    };
};

class B : public A
{
  protected:
    int b;

  public:
    int getB() const { 
      return b;
    };

    // nested accessor class:
    class exposed : public A::exposed {
      public:
        explicit exposed(B& aRB) : A::exposed(aRB) { };

        const exposed& setB(int aB) const { static_cast<B*>(p_a)->b = aB; return *this; }
    };
};

Meaning that the main function looks like this:

int main() {
  B b_obj;
  B::exposed(b_obj).setB(1).setA(2);
  int a = b_obj.getA();
  int b = b_obj.getB();
  //I want the following two lines to fail:
  b_obj.setA(1);
  b_obj.setB(2);
};

So, this is really the simplest solution because it really does the only thing that you really need, which is to …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

There are also a number of additional serious problems with your code.

1) Your copy-constructor is wrong:

    CLibrary::CLibrary(CLibrary &B)
    {
        mA = new CArticle*[MAX];
        mA = B.mA;    // <-- Problem! Assign the pointer 'B.mA' to the pointer 'this->mA'
                      //  the memory you just allocated (with new) is leaked, and both the 
                      //  original object 'B' and this object will refer to the same memory.
                      //  This is called a shallow copy, what you need is a deep copy.
                      //  Such as:
        // std::copy(B.mA, B.mA + MAX, mA);   // copy data in [B.mA, B.mA+MAX) to [mA, mA+MAX).
        mName = strdup(B.mName);
        mNr = B.mNr;
    }

2) The destructor of a polymorphic base-class should always be declared as virtual to make sure that the correct derived-class destructor will be called when you delete the base-class object (via a pointer to it). So, declare the base-class destructor virtual as so:

class CArticle
{
    public:
        int mIndex;

        CArticle(int c = 0) {  // note: easier to have default-value instead of two constructors.
            mIndex=c;
        }

        // note: copy-constructor is not needed here (the default version is correct).

        virtual void print() = 0;

        virtual ~CArticle() {};   // virtual destructor.
};

3) The destructor of the CLibrary class is also wrong because you don't delete any of the objects that your library has ownership of, nor do you actually delete the memory you use to store that array of pointers. So, you'd need something like this:

    CLibrary::~CLibrary() {
        for (int i=0; …
deceptikon commented: I was hoping you'd chime in. I didn't have time yesterday to go into any real detail. :( +12
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I was wondering if there is a way to say do this:
...
Instead of having to do this:
...
I would have thought that if it wasn't possible that C++11 would have fixed that, given that it created the && move constructor, why couldn't it create some kind of reference re-assign operator?

Well, you came very close to the answer, sort of by accident, by mentioning the rvalue-references (&&). With your two examples, you missed out on one possibility, which is what is done in a standard class like std::reference_wrapper, i.e., the following simple trick:

class someDataClass
{// private:
    const largeDataType *data;
  public:
    someDataClass& setDataRef(const largeDataType& o) {  // take by reference
      data = &o;   // store the address
      return this;
    };
};

The only problem with the above solution is that because in C++ there is a rule to allow temporary values (rvalue) to be bound to a const-reference, which would allow people to call this function with a temporary value, of which taking the address would not be a good idea, obviously. But, with C++11, you can easily remove that possibility and that danger:

class someDataClass
{// private:
    const largeDataType *data;
  public:
    someDataClass& setDataRef(const largeDataType& o) {  // take by reference
      data = &o;   // store the address
      return this;
    };

    someDataClass& setDataRef(largeDataType&&) = delete;  // forbid calling with rvalue.
};

In the above, the rvalue-reference overload will be selected whenever an rvalue is passed, and thus, …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Version 1:
"I'm having trouble with this math problem, can you give some pointers?"
"No, I'm sorry, it wouldn't be safe. You'll have to ask my garbage collector."

Version 2:
"I'm having trouble with this math problem, can you give some pointers?"
"Only if I can trust you to increment the reference counts on them."

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The reason why your code compiles is because your compiler implements a non-standard extension called VLA (Variable Length Arrays). This is a C99 feature (1999 C language standard) which allows for "static" arrays to have a length that is determined at run-time (not a compile-time constant). It is not standard in C++ but some compilers allow it in C++ too as an extension, most notably GCC. Some compiler versions even enable it by default, which I guess is the case for your compiler.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I prefer my Generic Programming (GP) version of bubble-sort:

template <typename ForwardIter, typename Compare>
void bubble_sort(ForwardIter first, ForwardIter last, Compare comp) {
  ForwardIter current_next;
  for(bool swapped = true; (swapped && (!(swapped = false))); --last) 
    for(ForwardIter current = first; (current_next = std::next(current)) != last; ++current) 
      if ( comp(*current_next, *current) && ( swapped = true ) ) 
        std::iter_swap(current, current_next); 
};

(warning: submitting this for a homework is going to draw a lot of suspicion)

NathanOliver commented: I like the warning +11
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

It is pretty obvious that you cannot use actual recursive calls in the implementation. Any recursion can be turned into a loop of some kind, usually supported by a queue or stack data structure to hold what would have been the stack-frame if it were implemented with recursive calls. Doing so effectively is usually a case-by-case thing. In fact, it is, for the most part, assumed that recursive algorithms are not implemented by recursive calls, unless explicitely cited as being reasonable to do so (e.g., intro-sort). Presenting algorithms using recursive calls makes it easier to understand it, but you don't actually implement it as such unless you have proof that it is safe (and desirable, i.e., avoiding free-store allocations for performance reasons, like in intro-sort implementations).

Generally speaking, recursions usually fall under a few simple categories, which can all be seen as tree traversals. The most trivial case is the traversal of a unary tree (i.e., a list), which corresponds to implementations that naturally lend themselves to tail-recursions, and can be trivially turned into a loop. Then, there is the back-and-forth traversal of a unary tree, which is more rare and corresponds to cases where a tail-recursion is impossible (because you need to do things on the way back up the call-stack), and this can generally be turned into two loops (forward and back). Then, you have the classic tree traversals like breadth-first and depth-first. These are also easy to turn into a loop: the breadth-first traversal turns into a …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Yeah, I'm not super familiar with C#'s rules about what it calls "namespaces", and if they are actually just modules in disguise. The point is that C / C++ works on the basis of having "dumb" header-file inclusion that are nothing more than an instruction to find a given file and copy-paste it's content where the include-statement appears. The C++ namespaces are used to compartmentalize things to avoid name-clashes. Modules or packages work differently, an import statement tells the compiler (or interpreter) to fetch everything that belongs to that module / package. At least, that is the traditional concept of modules (called packages in Java / Python, called "units" in Delphi (Object-Pascal), etc.). Both have their merits and their problems, and I think, as with many other things of that nature, there is no need for a "pure" solution.

The main advantage of modules is that you can avoid the whole "copy-paste lots of code and parse it, even though you probably parsed it already" problem with the traditional C/C++ header files. For example, units in Delphi are very nice in that respect because they can be essentially pre-compiled and pre-linked (i.e., the so-called Delphi "smart linker") into some kind of hybrid between a C/C++ object file and a shared library, for each unit. Of course, some C/C++ compilers can mitigate that problem to some extent with pre-compiled headers, but that's not really a great solution (and often doesn't work or do any good).

The main advantage of inclusion-mechanism is …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

If you don't want anything special, just use defaults.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

If you boot from the LiveCD, you should be able to pull up a terminal and enter this:

$ sudo fdisk -l

to list the hard-drives, partitions and their formatting information. That's the first information you should fetch (and post here), to know what Ubuntu is actually seeing.

In general, I prefer to create the free space on the hard-drive before starting the Ubuntu installer. This way, you just tell the installer to use the free-space on the given hard-drive instead of telling it to take over a particular partition. So, I would suggest you go into Windows, and re-arrange the partitions on that hard-drive to free up some "unformatted" space. A comfortable space for Ubuntu is around 100Gb (no need for much more than that), minimum about 20Gb. So, if you can simply shrink one of the partitions down by about that amount, it should free up enough space.

Afterwards, you start the Ubuntu installer and you must choose to manually select / create the partitions where to install it, and then, select the free-space from your hard-drive to install the different partitions (reserve a good 1.5 times your RAM memory as swap space). Also, remember to select to install Grub on the same partition as where you install Ubuntu.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Are you using a MAC? Because a quick google search makes it pretty clear that this is a MAC OS X issue.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I remain unconvinced of the merits of D. I find many of the design decisions questionable and many others rather inconsequential. But there are certainly some nice things about the language.

Here are some specific points (omitting things that haven't been changed from C++):

Modules vs. namespaces: I disapprove
I don't like that trade-off. Namespaces are much more flexible than modules, and introducing modules smells too much like an attempt to seduce Java/C# programmers more than anything else.

Interfaces vs. Multiple Inheritance: I approve
I'm not particularly attached to the feature of multiple inheritance in C++, and I think that Java-style interfaces are quite an acceptable alternative and it certainly simplifies the binary representation underneath, which is nice.

Inner classes: I approve, but it's nothing major
I write inner classes often in C++, and they are certainly useful, but making this a native feature is little more than a bit of syntax sugar.

Properties: Ugly, and useless
There are many nice and useful versions of this concept of "properties", this isn't one of them. This is barely more than syntax sugar without much of anything useful attached to it. This seems pretty much like the Delphi (Object Pascal) implementation of "Properties", just uglier.

The new template syntax: Ugly, and for no reason
I don't see the point of changing the syntax that everyone recognizes (e.g., foo<int>) with a new thing that is weird and confusing with the NOT operator (e.g., foo!(int)). I also don't like …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

That poutine looked disgusting: uncooked fries, no proper "couic-couic" cheese, too little gravy, and with syrup on it (who puts syrup in a poutine?!? I thought I had seen every variation out there, never seen that before).

I also loved the "Canadians have an evolutionary adaptation called socialized medicine", priceless.

Canadians Explained (eh)

They say it all here, eh.

What's with all the eh's? Are you trying to find a mate? Eh?

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The standard input:

cin >> str;

will read the text that has been inputted only up to the first space character (or new-line, or tab, etc.), and it will store that resulting text (i.e., the first word) as a null-terminated string in the memory pointed to by str. So, the 0 character that your are getting right after the first word is not, in fact, the space character, but it is the null-terminating character that marks the end of the string (i.e., "null-terminated" means that the end is marked by a 0 character).

To read a full line as input, you need to use a function like std::getline() (to read into a C++ string) or cin.getline() (to read into a C-style null-terminated string). Also note that C++ strings are always preferred.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Here is the reference documentation.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

No, it is not about exception& e being const. It is about the base-class function char* what() const; not being the same function as the derived class function char* what();.

Imagine it this way, consider that a function marked as "const" has a different name. As so:

class Base {
  public:
    virtual void func_const() const;
};

class Derived : public Base {
  public:
    void func();
};

void foo( Base& b ) {
  b.func_const();
};

As you can see, when you call b.func_const();, it is clearly not going to call the derived class function func(), because they are different functions (i.e., func does not override func_const). Now, as far as the compiler is concerned, a const and a non-const member function are two different function signatures (even though they have the same name). So, in your case, the what() function that you have in your derived exception class does not match the signature of the base-class function, and thus, are two different functions and one does not override the other, period.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I'm starting to hate the whole new "convergence" and "personalized" strategies for google searches and others.

When I search for a coding issue, it is usually some obscure and very specific issue. It is true that SO often offers one or two reasonably related threads that can be useful to me, but very often there are gems to be found in more obscure sources, like less-prevalent forums, old bulletin boards, comment sections, personal pages from enthusiasts, mailing-list archives, or scholarly articles. I have noticed recently (roughly in the time frame you are referring to), that at least the top 5 results on google are almost always SO threads, and typically (for the kind of specific issues I look up), only one SO result is remotely related to the issue I looked up and the rest are unrelated or don't have any useful discussion in it. This is really annoying. I know that SO ranks high (deservingly) in general, but it should not mean that it should rank high for every specific search.

My impression is that the way it used to be, roughly-speaking, is that the top results are those that contain the best match for the search terms, with some conservative filtering out (or pushing down) of less reputable sources. Now, it seems to be reversed quite significantly, i.e., pull up the most reputable sources (most popular sites) and consider the search terms matching almost as a second thought. It is true that the way it was before (and …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Have you tried? We don't do people's homework here. Show some effort at solving the problem yourself and what specific problem you are having with it.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The compiler explains it pretty well:

error: 'i' is a protected member of 'A'

That's pretty much all there is to it. The member function g is a member of class B, and the function f is a friend of class B. They both can only have access to private / protected members of class B, not those of class A. Before you say "what a minute, the protected members of A are accessible from B", I will correct you on that and state it more precisely: "member functions or friends of B have acces to protected members of A that the objects of class B have inherited".

This boils down to a case of "all B's are A's but not all A's are B's". In other words, the access to the members of A is granted to members / friends of B on the condition that they come from an instance of B. That's why you can't get access to them directly, either by pa->i or &A::i, you must always go through B class first.

nitin1 commented: excellent!! excellent!! +3
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I'm having trouble understanding what it is necessarily used for?

Consider this piece of C++11 code:

#include <future>
#include <atomic>
#include <vector>
#include <iostream>

int main() {
  int value = 0;

  std::vector< std::future< int > > results;
  results.emplace_back( std::async( [&value]() -> int { return value += 2; } ) );
  results.emplace_back( std::async( [&value]() -> int { return value += 3; } ) );

  for(auto& x : results)
    std::cout << x.get() << " ";
  std::cout << value << std::endl;
};

If you are not familiar with C++11 concurrency features (like std::future and std::async) I recommend you look it up. In essence, this code creates two threads (via async) that will execute a function that increments a shared value (value) by either 2 or 3, respectively. Then, the results are printed out, and then, the final value of the shared value is printed too.

The million dollar question here is: What will this code print out?

The stupid answer:
It should print out 2 5 5. If you have no idea what threads are or how they work, you might think that this code is obvious: start with (value == 0), then increment it by 2 and store the result in the vector, then increment it by 3 and store the result in the vector, and finally, the value ends up with a value of 5. However, you can't rely on the "first" thread executing "first", because they can either execute simultaneously or …

JasonHippy commented: Great post! +8
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

It allows you to do atomic operations on variables.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Should I disconnect the windows drive and try to do the install first then reconnect?

No. Do not do that.

Try to repair the grub install as I instructed before.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

How effective is email snooping at picking up terrorists (I mean the real bad ones) anyway?

Probably somewhere between 0.01% and 0% effective. I think that any serious person or organization with serious things to hide wouldn't be found by these broad-brush methods that collect "private" but not "secured" data / communications.

Have the US govt. missed something here, or is it a front to do some more general snooping, bringing about a greater degree of totalitarianism?

Collecting a large amount of private data on a lot of individuals (if not everyone) can be very useful in many ways. The mildest thing is probably background checks, which I still have a problem with, but understandable in some contexts. Another purpose is smear campaigns, or worse. There is nothing easier to do if you want to eliminate a political opponent or an annoying whistleblower, or whoever else. Currently, if you have someone you want to check the background of or smear, you can just contact one of NSA's subcontractor or other "cyber-security" firms, give them a few thousand bucks and get back a full package will all info you can dream of, in perfect legality (whatever that means anymore). This is scary.

I don't think anyone has in mind the whole 1984-style totalitarian idea of monitoring everything and black-bagging anyone who diverts from accepted behavior. But it's certainly useful to be able to out anyone that is a more serious threat, e.g., people like Julian Assange, Bradley …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I raised this issue of privacy in the cyber-world a few months ago. You might want to give it a read.

GrimJack commented: I just read through it - very thoughtful. +0
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I believe you need to do a grub recovery.

The fact that you installed Ubuntu and Windows on separate hard-drives might be the root cause of this issue. How exactly did you proceed to do the installation? I know you went through the Ubuntu install menus, but what I want to know is: Did you temporarily remove the Windows hard-drive? Where did you tell Ubuntu installer to put the Grub bootloader? Are you chain-loading with the Windows bootloader (e.g., with EasyBCD?)?

If you temporarily removed the Windows hard-drive in order to install Ubuntu on the other, then I am not the least bit surprised that you have the error that you have. Upon installation, the Grub bootloader for Ubuntu is configured to point to the installed the Ubuntu OS, usually by the name of the hard-drive, and by "name", I mean the sequence number (i.e., first, second, third hard-drive). If you change the hard-drives that are plugged in afterwards, this changes, and nothing works. If Grub detects that the OS is not where it is supposed to be, it just jumps to the command-prompt to let the user boot the correct OS manually (which is hard). See this issue.

You can probably repair your grub bootloader by booting from your LiveCD and going through the repair / recovery menus.

If not, boot from the liveCD (i.e. "Try Ubuntu" menu) and re-install grub. Basically, find the identifier for the hard-drive on which you installed Ubuntu by listing the drives …