arkoenig 340 Practically a Master Poster

s.substr(0,p) The first argument is the starting position; the second is the length. If you omit the length, you get the longest possible substring with the given starting position, which is why s.substr(p+1) works.

arkoenig 340 Practically a Master Poster

Instead of

return (static_cast<Person>(*this) == static_cast<Person>(right));

you should write

return (*static_cast<Person*>(this) == *static_cast<Person*>(&right));

because otherwise you are asking the compiler to generate code that copies the objects "right" and "*this".

arkoenig 340 Practically a Master Poster
arkoenig 340 Practically a Master Poster

Here's one way. You'll have to translate my prose into code.

1) Start with a sequence of 0 bits.
2) Repeat steps 3-5 until the sequence is all 1-bits.
3) Locate the leftmost 0 bit. (This works because the sequence
is known not to be all 1-bits)
4) Set that bit to 1.
5) Set all the bits to the left of that bit to 0.

For example, if you have 11011000, the leftmost 0 bit is the third from the left. So you set that bit to 0 and the ones to its left to 1 and you get 00111000.

Each time you go through steps 3-5, you will get a different set of bits. Try it and see.

Sodabread commented: Nice solution =) +1
arkoenig 340 Practically a Master Poster

In general, saying that an algorithm runs in O(f(n)) time means that there exists a constant k such that if you make n large enough, the run time for input of length n will never exceed k*f(n). The time units in which f(n) are expressed doesn't matter, as you can always compensate for a change in unit by changing the value of k. So, for example, if you change the unit from minutes to seconds, multiplying k by 60 will compensate for that change.

To understand the meaning of O(log n), you need only substitute log n for f(n). The base of the log doesn't matter, because you can compensate by the choice of base by scaling k appropriately.

In both examples (O(f(n)) and O(log n)), the value of k is not important; what is important is that it exists.

So, when I say that inserting a new element in an n-element data structure takes O(log n), I am saying the follogwing:

1) Pick a base for the log.
2) Pick a time unit.
3) Once you have done that, I can find a value of k such that for sufficiently large n, inserting an element in an n-element data structure takes no longer than k*log n, where time is measured in the units chosen in (1) and the log is in the base chosen in (2).

arkoenig 340 Practically a Master Poster

Your loop says for x in range(50): , so it will execute 50 times. You want to create a 50 by 50 grid, so you want it to have 2500 entries. How can you expect to create a data structure with 2500 entries if your loop executes only 50 times?

arkoenig 340 Practically a Master Poster

This is my original statement:
It does not make any reference to an if/else if construct.

There's no other real alternative to switch/case in C or C++.
In particular, on every C or C++ implementation I've seen, the overhead of calling a function is much greater than that of a switch statement, so fetching an element from an array of function pointers is very unlikely to be a more efficient substitute for a switch.

arkoenig 340 Practically a Master Poster

It is hard to compare a Python dictionary lookup with a C switch/case construct.
Also switch/case is very limited in application.

Of course.

I was responding to the specific claim that Python does not have switch statements because they're slower in C than if/else statements. I haven't commented on whether I think switch statements might be useful in Python for other reasons.

arkoenig 340 Practically a Master Poster

I think it's easy as making a case and a for loop and testing them.

Assuming you're talking about testing the speed of switch statements: I can test only the compilers I have available, and on those I can see by looking at the machine code that switch statements often generated faster code than could readily be obtained by hand coding.

Moreover, in decades of working with C and C++ compilers, I don't think I've ever encountered one that generates slower code for a switch statement than it does for the corresponding if-else statements.

So when someone makes the blanket claim that switch statements are slow, I think it's up to the person making that claim to prove it.

arkoenig 340 Practically a Master Poster

Switch/case is rather slow in C or C++ and therefore was not implemented in Python.

Switch/case is slow in C or C++? Not in my experience. Do you have evidence to support this claim?

arkoenig 340 Practically a Master Poster

My first observation is that you are sorting the entire list (or vector) every time you put a new element there. So if you have 1,000 elements, you're sorting it 1,000 times. It's hard to see how that can be particularly fast.

If you need to put new elements into the data structure while keeping it sorted, why not use a set or multiset?

arkoenig 340 Practically a Master Poster

The "for each" statement isn't part of standard C++, so I'm not familiar with its exact semantics. However, I would expect that it would have to work by making comp a copy of each element in turn of sysRelMap .

The reason is simple: If it didn't make a copy, what would happen if you changed the value of comp.first ? Presumably that would change the key of the corresponding element of the map. Would that then somehow cause the map to be reordered? By what magic would the map detect that the element had changed?

For such reasons, using an iterator to access the elements of such a map would give you elements of type pair<const int, CompCont> . The fact that your "for each" doesn't do so suggests strongly that the elements are being copied.

arkoenig 340 Practically a Master Poster

Using the standard list.sort algorithm should not take several seconds to sort a few hundred elements, so something must be wrong.

Unfortunately, I can't read the file you attached. When I try, I get "invalid or corrupted"

So perhaps you could post the relevant portions of the code, particularly your comparison function.

arkoenig 340 Practically a Master Poster

overwriteSlot < 1 && overwriteSlot > 3 is always false, because no value can be less than 1 and greater than 3 at the same time. So your loop will never terminate.

I am guessing that you meant to write || rather than &&.

arkoenig 340 Practically a Master Poster

Is there a reason that you are insisting on an AVL tree rather than just a data structure that will use an order relation to store values in a way that will keep equals together? Because if you just need the latter, you should be able to get std::set (or perhaps std::multiset) to do what you want by defining an appropriate comparison function.

arkoenig 340 Practically a Master Poster

You would be right if this thread was about iterators. It isn't, so you aren't.

Well, the general principle carries over to any kind of iteration that runs into one of the bounds of the permissible range. For example, let's change the original example just a bit:

int pro[100];
for(size_t a=99;a>=0;a--)  {
    pro[a]=a+1;
    cout<<pro[a]<<"\t";
}

All I've done here is to change the type of a from int to size_t...but now the code doesn't work, because size_t is an unsigned type, so a>=0 is always true.

Personally, I would rather not have to remember to use one style of loop for signed integer types and a different style for unsigned integers and iterators. For that reason, when I'm iterating over an asymmetric range, I tend to change loop control variables at the beginning of the loop if the end of the range is exclusive, and at the end of the loop if the end of the range is inclusive.

arkoenig 340 Practically a Master Poster

By the way, let me elaborate on what I mean about iterators. Consider iterating backward through a list<int>. You can't write

// This code does not work!
for (list<int>::iterator it = mylist.end()-1; it >= mylist.begin(); --it) {
    // stuff
}

for two reasons: (1) List iterators don't support - or >=; (2) Even if they did, the loop terminates only when it < mylist.begin(), and there are no circumstances under which that can ever be guaranteed to happen.

One correct way to write this loop is

for (list<int>::iterator it = mylist.end(); it != mylist.begin(); ) {
    --it;
    // stuff
}

As Ancient Dragon correctly points out, I could also have written it this way:

list<int>::iterator it = mylist.end();
while (it != mylist.begin()) {
    --it;
    // stuff
}

I chose not to do so for two reasons: (1) I don't want the value of it available after the loop ends; (2) Using a for makes it clearer to the reader that the purpose of the loop is to deal with every value in a range, even if the range is expressed in an unfamiliar way.

arkoenig 340 Practically a Master Poster

Unusual and unconventional approach. If you are going to do that then you might as well use a while loop instead of a for loop.

I would if I wanted the control variable to escape into the surrounding scope.

arkoenig 340 Practically a Master Poster

If you write a loop that runs backward through an array, it is a good idea to get into the habit of decrementing the control variable at the beginning of the loop:

int pro[100];
for (int a = 100; a > 0;) {
    --a;
    // whatever
}

This technique has two advantages: (1) It lets you initialize the variable directly from the array's size rather than computing the size - 1, thereby reducing the chance for error; (2) It generalizes nicely to iterators, even if they do not support ordering comparisons.

arkoenig 340 Practically a Master Poster

Most of the programmers I know--but by no means all of them--are male. I think that reflects interest much more than it reflects talent or aptitude. For that matter, I've seen some spectacularly bad male programmers as well.

arkoenig 340 Practically a Master Poster

If you want your program to be reliable, I suggest you look for a different way of solving your problem. You have a pointer to one type (uint8) and you casted it to a pointer to a different type (A). Compilers are under no obligation to make such a cast behave in any particular way, and the more aggressive the compiler is about optimizing, the less obliged its authors feel.

Even if you wind up getting your program to do what you want, you may have difficulty moving it to a different implementation.

So if you want to treat an integer as if it were several separate data items crammed togeher, I think you would be better off using the and, or, and shift operators to do so in a portable way.

arkoenig 340 Practically a Master Poster

What do you want to happen when you do this?

SecondChild sc;
sc.setResults("foo");

and how do you want what happens to differ from what happens when you do this?

BaseDB b;
b.setResults("foo");

In both cases, you're trying to call a member function that isn't defined.

arkoenig 340 Practically a Master Poster

Well, you can use the std::sort algorithm in "#include <algorithm>". The only little problem is that it cannot be used with a list because list provides only bidirectional iterators, not random access iterators, which is required for the sort algorithm.

The standard list class has its own sort member that uses a different algorithm from the stand-alone sort algorithm. So if myList is a list, then instead of writing

sort(myList.begin(), myList.end(), compare);

you can write

myList.sort(compare);
arkoenig 340 Practically a Master Poster

The line "car * autocar = new car[count];" makes an array of cars of size count, and autocar is a pointer to that array.

Not quite: autocar is a pointer to the initial element of the array, not a pointer to the array. This distinction is important because it means that *autocar is an element, not an array.

arkoenig 340 Practically a Master Poster

C++ doesn't really have 2d arrays. Perhaps you can explain in more detail what you want.

arkoenig 340 Practically a Master Poster

Put the try-catch inside the for loop.

arkoenig 340 Practically a Master Poster

The code I posted needs to be called repeadedly until it returns a single digit value. But your solution is a lot better and less time consuming. But I don't know if it is something that a student would want to turn in as the solution to the problem because most likely the teacher would ask him to explain it, which he may or may not be able to do.

Exactly. That's why I posted it. It solves the problem, but not in a way that the student can use without first understanding and rewriting it.

arkoenig 340 Practically a Master Poster

The current C++ standard does not support threads, so you will either have to pick a nonstandard implementation or wait until the new standard is complete.

arkoenig 340 Practically a Master Poster

>>This program doesn't quite solve the problem
I didn't intend for it to be a complete solution. We are not supposed to provide complete solutions to home work problems.

I meant that it gives a different answer in some cases than the problem requested.

(I suspect that we are working at a similar goal in different ways--because my suggestion essentially solves a different problem that happens to have the same solution as the one originally requested :) )

arkoenig 340 Practically a Master Poster

>but that's really programming in C, not C++.
No, it's just a part of C++ that should be considered more advanced due to the lower level nature. The real question is why is a book teaching such things so soon? Most likely it's ignoring the more useful parts of C++ to teach the less useful parts, which suggests either an older book or simply a poorly designed one.

It's a floor wax and a dessert topping! :)

And I completely agree with your (rhetorical) question.

arkoenig 340 Practically a Master Poster

Clever. Though I'm curious how you came up with that solution. Was it intentionally designed from the start, or did you simply notice a pattern while working out a more brute force summation?

Actually, I first encountered the idea when my father taught it to me when I was a child. It's the basis for a technique called "casting out 9's" that I doubt is used much any more, but is a good way of checking arithmetic when you do it by hand.

For example, suppose you add 1247 and 2056 and get 3293. To check the result by casting out 9's, you add the digits of 1247 to get 14, and add them again to get 5. Then you add the digits of 2056 to get 13 and add them again to get 4. 5 + 4 is 9, so you should also be able to get 9 by adding the digits of 3293. However, when you try, you will see that you get 17 and then 8, so the addition is incorrect.

This technique works because modulus distributes over addition and multiplication. In other words, (a + b) mod n is always equal to (a mod n + b mod n) mod n, and similarly for multiplication.

Now consider a 2-digit decimal number ab. This number represents (a*10) + b. Notice that 10 mod 9 is 1. Distributivity implies that (a * 10) mod 9 is equal to ((a mod 9) * (10 mod 9)) …

Narue commented: Well explained. +22
arkoenig 340 Practically a Master Poster

What I don't understand is why a book that purports to teach C++ spends so much effort on what is effectively a C program. Isn't it easier to understand this?

// read the first string
string s1;
cout << "Enter string #1: ";
getline(cin, s1);

// now the second string
string s2;	
cout << "Enter string #2: ";
getline(cin, s2); 

// concatenate a hyphen onto the first string
s1 += "-";

// now add the second string
s1 += s2;

//and display the result
cout << "\n" << s1 << "\n";

I can certainly understand why people might want to learn how to concatenate character arrays one character at a time; but that's really programming in C, not C++. So why call it C++ programming?

arkoenig 340 Practically a Master Poster

There is only one way to learn to write programs, and that is by writing programs. Just get out there and do it. If you can, work on stuff that you personally find interesting; but writing programs that bore you will still teach you more than not programming at all.

arkoenig 340 Practically a Master Poster

I just got the biased part arkoenig

Accelerated C++: Practical Programming by Example by Andrew Koenig, Barbara E. Moo

Any relation?

Note I ordered the book this morning...

Thanks!

Don't let the relatively small size fool you -- Barbara and I packed a lot more information into this book than you will find in other books three times its size.

The downside of this strategy is that you have to read it carefully; you can't just skim.
Still, I think it's better to take the time to understand 350 pages than to bleep over 2/3 of 1,000 pages.

arkoenig 340 Practically a Master Poster

Well, you would be doing it wrong. There is no need to hard code the number of digits.

int sumdigits(int n)
{
  int sum = 0;
  while( n > 0)
  {
    sum += (n%10);
    n /= 10;
  }
  return sum;
}

This program doesn't quite solve the problem, because the OP specified that if the result has more than one digit, you're supposed to sum the digits again; and so on until you reach a single digit.

Here's a solution that I think has the desired effect, although perhaps not quite by the means you might expect. I've also taken the liberty of making the argument and result unsigned, because I don't know what's supposed to happen if the argument is negative:

unsigned sumdigits(unsigned n)
{
    if (n == 0)
        return 0;
    return (n-1) % 9 + 1;
}
Ancient Dragon commented: Very nice and efficient +33
arkoenig 340 Practically a Master Poster

C++ Primer 4th edition says default constructor is used regardless where a class variable is declared - does that means variable of class type is initialized whether it is global or local?

Yes, that's what it means, as long as the class has one or more constructors.

Even if the class has no explicitly defined constructor, but has a member with a type that has a constructor, then that constructor is used to initialize that member. In addition, a variable with static lifetime (which includes all variables defined at global scope) will have all of its data members initialized to 0 before anything else happens.

For example:

struct Foo {
    int x;
    std::string s;
};

Foo f1;

int main()
{
    Foo f2;
}

Here, f1.s and f2.s will both be initialized to null strings because that's what the default constructor for the library string class does. In addition, f1.x will be initialized to zero because f1 is a variable with static lifetime. On the other hand, f2.x will have an indeterminate value, and trying to use it without giving it a new value will cause undefined behavior.

arkoenig 340 Practically a Master Poster

I'm biased, of course; but I think that Accelerated C++ is pretty close to what you're looking for; it definitely has a tutorial narrative, so it's intended to be read sequentially (unlike many that are essentially reference books) and it covers quite a bit more material than most introductory books.

arkoenig 340 Practically a Master Poster

As you suggested if i use the prgma_pack for these structures, i donot need to worry at all...

If you use any pragma, you always need to worry.

Pragma has two properties that is guaranteed to cause worry:

1) The very nature of pragma is machine-dependent.

2) An implementation that does not know what to do with a pragma is expected to ignore it.

You do the math.

arkoenig 340 Practically a Master Poster

That was directed at the OP... That's why I quoted them, not you.

Ah. So we agree :-)
Sorry about that.

arkoenig 340 Practically a Master Poster

I think you need to make an effort to take the time to read, and understand, posts better. I already answered both of these questions. Please re-read the second part of my previous post.

I'm sorry, but I was trying to be polite.

I guess I need to say it more bluntly: Adding 1 is plain flat wrong in the following context:

int map[15][15] =  {  1};
// ...
xTPos = (rand()%15)+1;
yTPos = (rand()%15)+1;
map[xTPos][yTPos];
map[xTPos][yTPos] = 5;

The reason is that rand()%15 is an integer in the range 0-14 inclusive, which means that rand()%15+1 is an integer in the range 1-15 inclusive. You have defined map as a 15x15 array, which means that whenever either xTPos or yTPos turns out to have the value 15, the effect of either of the last two statements above is undefined.

I do not need to look any further than that to know that the program is broken. In particular, I do not need to know anything about your reason(s) for writing this code; it's wrong whatever your motivation.

arkoenig 340 Practically a Master Poster
xTPos = (rand()%15)+1;
yTPos = (rand()%15)+1;

Why the +1?

arkoenig 340 Practically a Master Poster

Thanks again for the correction Arkoenig, it really is appreciated and sorry to the OP for my schoolboy error!

Hey, don't worry about it, and thanks for being a good sport!

Heck, I make elementary blunders sometimes too, and I've been programming in C++ for more than 25 years.

arkoenig 340 Practically a Master Poster

First up, the first 'if' statement in your add function:

if(num<=r->data||r==NULL)

Simply moving the 'r==NULL' comparison to the left does not solve the problem:

if(r==NULL || num<=r->data)

This is because the OR evaluates both sides of the expression before returning a value. So in cases where r is NULL, the left hand side of the expression will evaluate to true, but due to the nature of the OR it will also attempt to evaluate the right hand expression.

I am sorry to have say that you are completely mistaken about this description.
The definition of || is that it evaluates its left operand first; if that operand yields true, then the result of || is true and the right operand is not evaluated.

Similarly, && evaluates its left operand first; if that operand yields false, then the result of && is false and the right operand is not evaluated.

arkoenig 340 Practically a Master Poster

So, what is puzzling me here is how the length can be shorther than the amount of elements in the vector? I thought it was supposed to resize automatically?

You thought wrong. The size of a vector changes only if you do something that changes it. Assigning a value to an element is not such a thing.

If you write

vector<int> v;
v[0] = 42;     // No!

you have done something that has undefined behavior, namely tried to assign a value to v[0] when the vector doesn't have any elements.

If you wish to append an element to a vector, you should do something like this:

vector<int> v;
v.push_back(42);   // Yes!

Calling push_back increases the size of the vector by 1, and does so by appending a new element with the given value to the vector.

Calling resize also changes the size, of course; so you could have written

vector<int> v;
v.resize(v.size()+1);
v[v.size()-1] = 42;

but that's more roundabout, in addition to creating a new element, initializing it to 0 (because using resize to increase the size of a vector initializes the new elements), and then setting it to 42.

If you use resize to decrease the size of the vector, it throws away elements.

arkoenig 340 Practically a Master Poster

If the result is still the same, that suggests that there are similar problems elsewhere in the program. Perhaps you should look for them.

arkoenig 340 Practically a Master Poster

The first statements you execute in your main program are

p = NULL;
add(&p,5);

The first statements you execute in add are

r=*q;
if(num<=r->data||r==NULL)
// ...

Here, q is the first parameter of add, which means that the value of q is &p as computed in main. Therefore, *q is the same value as p in main, or NULL.

When you try to access r->data when r is NULL, the result is a run-time error.

I will leave it to you to figure out (a) what the problem is, (b) how to fix it, and (c) whether there are any other problems.

arkoenig 340 Practically a Master Poster

Line 16 compares the values of the two pointers, not the values of the doubles to which they point.

Also, if your argument is const double *, that means you're promising not to change the value to which the pointer points. If you now return double *, you're violating that promise.

Fix these two problems and your ComputeMaximum function looks like this:

const double *ComputeMaximum(const double *num1a, const double *num2a)
{
    return *num1a > *num2a? num1a: num2a;
}

Because you are expecting pointers rather than references, you need to pass the addresses of the numbers in line 12. Also, you have swapped value and address:

cout << "The greatest value is: " << *ComputeMaximum(&num1, &num2) << " and its pointer is: " << ComputeMaximum(&num1, &num2);

And, of course, you need to change line 4 to match the function:

const double *ComputeMaximum(const double *num1a, const double *num2a);
arkoenig 340 Practically a Master Poster

You're right.But this is read.

Really? What leads you to that conclusion?

arkoenig 340 Practically a Master Poster
ifstream in;
in.open("filename",std::ios::app);
in.seekg(in.tellg(),std::ios::end);//this places the file pointer at the end

I don't think the last line is necessary -- once you've opened it with ios::app, every write seeks to the end.

arkoenig 340 Practically a Master Poster
ofstream f(filename, ios_base::out | ios_base::app);

iosbase::app means that you want to append to the file.