arkoenig 340 Practically a Master Poster

That is because myk45 gave you pseudocode instead of C++. If you do not know how to translate what myk45 wrote into C++, then you are probably in serious trouble, and you should consider dropping the course.

Nick Evan commented: Agreed +16
arkoenig 340 Practically a Master Poster

Yes. In fact, I'm not sure that this declaration is valid at all, because it doesn't declare any variables. The general form of a typedef declaration is

typedef <type> <declarator-list>;

and in this case, the type is

struct D3DVEFCTOR { float x; float y; float z; }

and the declarator-list is empty.

If you omit the "typedef," the declaration is valid in C, but then to use it you would have to write

struct D3DVECTOR foo;

and you sould not need the "struct" in C++.

arkoenig 340 Practically a Master Poster

Perhaps because the author wants both C and C++ programmers to be able to use the same code, and to be able to write

D3DVECTOR foo;

with the same meaning in both languages.

arkoenig 340 Practically a Master Poster

Putting it differently: If you have to ask about how to use operator new, you shouldn't be using it.

StuXYZ commented: Very true. +3
arkoenig 340 Practically a Master Poster

I think it would be a good idea to define the problem precisely. Are you looking for every sequence that repeats? Including sequences of a single element? Must the repetitions be consecutive, or can other elements separate them? Can the repetition overlap the original? Are you looking for every sequence that repeats, even if two such repetitions overlap each other?


Until the problem is defined precisely enough that these questions and others like them are easily answered, it is difficult to proceed.

arkoenig 340 Practically a Master Poster

Hmm. The first line should just be

for(int row = 1, row <= number, row++)
cout << row;

Not even close.

The first line of output is

cout << 1 << "\n";

Right?

arkoenig 340 Practically a Master Poster

One of the biggest problems with submitting homework online is that of determining whether the homework being submitted was actually done by the student--or, perhaps, was instead the result of the student going online and trying to talk someone else into doing the student's homework instead.

Which is what you appear to be doing by asking this question in the first place.

In other words, if you want people in this forum to help you with your homework, you have to start by doing it yourself, and then explaining where you've gotten stuck. Then you might get useful hints.

arkoenig 340 Practically a Master Poster

You can't subtract strings.

vasilevich commented: Helped me solve the whole problem with a very simple answer. +0
arkoenig 340 Practically a Master Poster

NOTE: if you have more than one (pre-)post-increments in one statement, then the behaviour is undefined, that means the following line will result in different outputs on different compilers or even wors on different runs of the same program.
VERY BAD.

m=i++ && j++ && k++ || l++;

This claim is incorrect. In fact, it's incorrect in two different ways:

1) There is nothing wrong with having as many increments or decrements you like in a single statement, so long as no two of them refer to the same variable.

2) The correct rule is that if you modify a variable's value in an expression, you are not allowed to access it (either read or write) elsewhere in the same expression unless (a) a sequence point intervenes, or (b) you are accessing it in order to compute its new value.

There is a sequence point between the left and right operands of && and || as well as between the operands of the comma operator.

So i++ + j++ is fine, so long as i and j are not references to the same variable. Moreover, i++, i++ is also fine, because there is a sequence point between the operands of the comma. Similarly, i++ && i++ and i++ || i++ are OK for the same reason. Finally, i = i * 3 - 1; is OK because i is accessed in order to compute its new value.

arkoenig 340 Practically a Master Poster

You define badDriveList in one function and expect to be able to use it in another. That won't work, period. As you've written your code, badDriveList is a local variable in TestSystem::Drive, and will be destroyed as soon as TestSystem::Drive exits.

What you probably need to do is to make badDriveList a data member of TestSystem. Until you do that, or something like it, there's little point in talking about other problems.

arkoenig 340 Practically a Master Poster

The reason that C++ has both the struct and class keywords is that Bjarne Stroustrup believes that important concepts should have names.

Consider: If C++ were to have only one of struct or class, it would have to keep struct and ditch class, because otherwise even the sipmlest C programs would not work as C++ programs. It would still be possible to write classes as structs with appropriate permissions, but then every programmer would be advised to use private labels all the time.

In that case, instead of asking why C++ has both struct and class, people would be asking "People are urged to use private labels all the time; why doesn't C++ have some way of making that the default?"

arkoenig 340 Practically a Master Poster

Yes you can solve this just with AND OR XOR NOT.

Moreover, because NOT(a) is XOR(A,A), you don't need NOT. Similar reasoning will show you tnat you don't need AND or OR, either, so long as you have XOR.

If, on the other and, you don't have XOR, then you need NOT and either AND or OR.

acer5542 commented: he helped me to solve my self without the answer +1
arkoenig 340 Practically a Master Poster

Making it a non-member destroys inheritance.

Not at all:

bool operator==(const T& a, const T& b) { return a.equal(b); }

causes a==b to have the same inheritance properties as a.equal(b) whenever a and b have type T or any type derived from T (assuming, of course, that the equal function is virtual and returns bool).

arkoenig 340 Practically a Master Poster

I think the equality operator should be a member function of the class it will be operating on. Otherwise, it will have to be a friend function, which I avoid unless necessary.

I still disagree.

If you make the equality operator a member, it is somewhere between difficult and impossible in general to avoid situations in which a==b compiles but b==a doesn't. Moreover, if you make the "equal" member function public--which I see no reason not to do, there is no need to make the equality operator a friend.

arkoenig 340 Practically a Master Poster

I think you want std::uninitialized_copy .

NicAx64 commented: good to know +2
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

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

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

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

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

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

Just for fun... What happens if you add the semicolon that you forgot after the } in foo.h?

arkoenig 340 Practically a Master Poster

AFAIK, the main advantage of nested functions in languages that have them is to provide support for closures. http://en.wikipedia.org/wiki/Closure_%28computer_science%29

Yes.

C++ already had function objects, which look like functions but are really first class values, they can be stored, mutated, passed as arguments and returned and bound to variable names. And therefore C++ already had a mechanism for supporting closures - several libraries eg. Boost::bind, Boost::spirit, Boost::phoenix do exploit closures extensively.

The decision not to implement member functions came long before Boost, or even STL, existed. I think (but do not remember for sure) that function objects did exist, and their existence contributed to the discussion. Essentially, one camp thought that function objects could easily substitute for nested functions; another thought that programmers would have difficulty writing such substitutions and getting them right.

In particular, one difficulty with using function objects as closures is that each time you define a function object, it is a new type. So to use them in any generality, you may find templates creeping in where they're not really needed.

In C, gcc has had an extension which provides limited support for nested functions and closures for quite some time now. http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html One can only call these functions (with closures) as long as the containing stack frame is alive:
GCC implements nested functions via a simple trampoline bounce; the nested function does not store any state information about closures, instead they are picked up directly off the stack frame.

arkoenig 340 Practically a Master Poster

Also, the form of your example:

String operator+(const String &s)

suggests that operator+ is a member function. The name of the class, String , suggests that operator+ is probably being used for concatenation. The fact that the function has one argument rather than two suggests that it is probably a member function rather than a standalone function. Using a member function for concatenation is a bad idea because it requires the left operand of a concatenation to be a String rather than a type that can be converted to String .

Moreover, the lack of const in the member-function declaration (if, indeed it is a member function) means that you cannot use a const String object as the left operand.

That's two elementary programming errors in that one example. If you saw that example in a textbook, it may be a good idea to consider a different textbook.

mrnutty commented: Good points +5
arkoenig 340 Practically a Master Poster

The reason is that it is difficult to implement nested functions in a way that maintains compatibility with C and other compilers. For example:

extern void f(void (*)());

int main()
{
    int x;
    void g() { x = 42; }
    f(g);
}

In order for this program to work, f, which is compiled separately, has to have access to information that allows it to determine the location of the local variable x inside main.

The typical implementation technique for solving this problem is to say that function pointers are two words long: One word contains the address of the function's code; the other contains the address of the most recently instantiated stack frame of the statically enclosing function.

Trouble now ensues if the function f is in a language whose compiler does not know about this convention.

It is possible to sidestep the compatibility problem by saying, essentially, that global functions and netsted functions have pointers that have two different types. Several people on the C++ committee actually sketched out an implementation strategy that would have made it possible to do so. However, after protracted discussion, the committee ultimately decided that the added implementation complexity was not worth the benefit. If I remember correctly, it was a fairly close decision.

vijayan121 commented: that was a lucid explanation. thanks. +6
arkoenig 340 Practically a Master Poster

I beg to differ with both of the previous posters.

Most computers these days (including, so far as I know, all currently manufactured Intel processors) use IEEE floating point, which requires that the results of floating-point addition, subtraction, multiplication, division, and square root be deterministic. In particular, the IEEE standard requires that the result of any of these operations be bit-for-bit identical with what the result would be if the operation were conducted in infinite precision and then rounded (according to the current rounding mode) to the given precision.

The standard does permit intermediate results to be computed in greater precision than the variables involved in the computation, but that liberty does not affect the program shown here.

The real reason that the output from this program is surprising is simpler: The type of the literal 0.2 is double, not float. Moreover, the value 0.2 cannot be precisely represented in an IEEE floating-point number.

Therefore, when we write

float x = 0.2;
float y = x - 0.2;

the value of x - 0.2 is computed by converting x to double, subtracting the double representation of 0.2 from it, and converting the result back to float. The result is to make y equal to the difference between the float representation of 0.2 and the double representation.

If you were to change the program as follows:

double x = 0.2;
double y = x - 0.2;

then I believe that the IEEE standard would …

arkoenig 340 Practically a Master Poster

Note that the value returned by ip.c_str() persists only until the next time you change the value of ip . So if you modify ip in any way between the time you assign the value to argv[1] and the time you use the value, the effect is undefined.

arkoenig 340 Practically a Master Poster

You need to make the destructor in the base class as virtual (otherwise the base class destructor will be called directly).

A small, pedantic, correction:

You need to make the destructor in the base class virtual, otherwise the effect is undefined (Most implementations call the base-class destructor without first calling the derived-class destructor, thereby leaving the object's memory in a partially-destroyed state).

arkoenig 340 Practically a Master Poster

I tried the following code in my Turbo C++ ..

int j=5;
cout<<++j + ++j + j++;

and got the result 20, as expected.

Your first mistake is having any expectations at all about this statement.

It tries to modify the value of j twice (or more) in the same expression (or, more accurately, between two sequence points), so the result is undefined.

This means that a C++ compiler is permitted to generate code that does anything at all when you try to execute this statement, including deleting all your files and sending hate mail to all your friends.

arkoenig 340 Practically a Master Poster

This code doesn't work:

std::list<bullet> bullet_list;
std::list<bullet>::iterator iter;

bool alive = false;
for (iter = bullet_list.begin(); iter != bullet_list.end(); ++iter) {
	bool isalive = iter->alive;
	if (isalive == true) {
		alive = iter->move(); // move is a function inside the struct "bullet"
	} 
	if (alive == false) {
		int bulletID = iter->id;
		bullet_list.erase(iter);
		dbDeleteObject(bulletID); // deletes object from game
	}
}

The problem is in line 12. Executing bullet_list.erase(iter); causes the element to which iter refers to be deleted from the list. Doing sinvalidates iter. On the next trip through the while loop, iter is invalid, so ++iter has undefined effect.

One way to deal with this problem is to increment iter only when it is known to be valid. The following rewrite is slightly sneaky, but I think it will work:

std::list<bullet> bullet_list;
std::list<bullet>::iterator iter;

bool alive = false;
for (iter = bullet_list.begin(); iter != bullet_list.end(); ) {  // No increment!
	bool isalive = iter->alive;
	if (isalive == true) {
		alive = iter->move(); // move is a function inside the struct "bullet"
	}

	// The following if statement increments iter one way or another,
	// regardless of the value of alive
	if (alive)
		++iter;
	else {
		int bulletID = iter->id;
		bullet_list.erase(iter++);
		dbDeleteObject(bulletID); // deletes object from game
	}
}

The point is that bullet_list.erase(iter++); copies iter , increments it (which causes it to refer to a value that will survive the call to erase , and then erases the element to which iter formerly referred. This …

Yiuca commented: I don't like giving broken code but it sometimes happens, thanks for correcting it. +2
arkoenig 340 Practically a Master Poster

You are exactly right about the point of the question. The question is there in order to encourage readers to stop thinking about data formats in terms of absolute sizes, and to try to write programs with output that conforms to the data being displayed.

arkoenig 340 Practically a Master Poster

If you're serious about writing C++ programs, rather than writing C programs and using a C++ compiler to compile them, std::fill is a better choice than memset because it's type-safe and works even for class types.

mrnutty commented: Thank you, finally someone pointed out the obvious! +5
arkoenig 340 Practically a Master Poster

What you should really do is use std::string instead of char arrays.

arkoenig 340 Practically a Master Poster

The answer is that the program does not work, because the line that assigns a value to c has undefined behavior. The behavior is undefined because it attempts both to fetch and store the value of a single object between sequence points.

Because the program does not work, there is no need to spend time understanding why it works.

arkoenig 340 Practically a Master Poster

I cannot resist pointing out that line 12 is unnecessary in this example, because the only way control can reach line 12 is if avail is found to be equal to new_avail in line 9.

I willl also point out that lines 5 and 8 can be collapsed into

iterator new_avail = std::copy(end, avail, begin);

because std::copy returns an iterator that refers to the position after the last element copied.

Finally, the test

if(begin)

in line 3 doesn't seem to do anything useful, because there is no general rule for what it means to use an iterator as a condition.

As before, I have not tested the code that corresponds to these comments, but hope you find them useful anyway.

arkoenig 340 Practically a Master Poster

If every element points to a subsequent element, where does the last element point? By definition, no element can be subsequent to the last one.

So the problem as stated makes no sense. Once we have figured out exactly what the problem is, it may be possible to come up with a solution.

arkoenig 340 Practically a Master Poster

You will find your answers here.

Lusiphur commented: Exactly!! +1
arkoenig 340 Practically a Master Poster

Your code has an interesting strategy, but it has a few problems.

First, the C++ standard defines erase to work by copying elements from the part of the vector after the erasure on top of the elements being erased, then destroying the elements at the end of the original vector. It does this for several reasons.

One reason is that this strategy makes it unnecessary to have enough memory to contain two copies of the entire vector, which would otherwise be necessary if you were erasing, say, a single element. It also makes it unnecessary to copy the elements before the point of the erasure, which might be important if you are erasing only a few elements near the end of the vector.

Still, your strategy is an interesting one, and it has the advantage that if you are erasing a large part of the vector, you wind up using less memory after the smoke has cleared. So let's look at the code and see if there are any problems.

My first observation is that the parameters begin and end should be type iterator or const iterator& , not iterator& . As your code is written, it insists on accepting lvalues as arguments, and implicitly states its intention to modify those arguments--which you have no reason to want to do.

The next problem is on line 12, where the second argument to uninitialized_copy , begin-1 , should be begin . It is easy to see …

arkoenig 340 Practically a Master Poster

The gentlemen above me have done a great job & answered well. I'd just like to add that chars inside switches are in fact converted to their ASCII equivalent ints. :)

Not quite. A char is just an integer with (usually) severe constraints on its value. Operations that involve chars and other integral types have nothing to do with ASCII or any other encoding.

arkoenig 340 Practically a Master Poster

Perhaps a more interesting question is why you have a 200000-element array that needs initializing in the first place.

arkoenig 340 Practically a Master Poster

I have to say that I don't like either alternative, becuase there is a much simpler, cleaner one. There is a built-in function named getattr with the property that getattr(x, 'a') yields the value of x.a . Similarly, setattr(x, 'a', y) has the same effect as x.a = y .

arkoenig 340 Practically a Master Poster

I hate to rain on people's parades, but the original post says that it requires a bidirectional iterator. In fact, the code does <= comparisons on iterators--which means that it really requires random-access iterators.

NathanOliver commented: Thanks +2
arkoenig 340 Practically a Master Poster

You haven't actually asked a question; you've made a claim. As it happens, that claim is false, and it is false for a good reason.

Consider:

class Foo { /* something */ };

class Bar: public Foo {
public:
    void f(double);
};

// ...

void x()
{
    Bar b;
    b.f(0);       // Which function is called?
}

If C++ were to behave as you claim it does, you would not be able to answer this question, because the answer would depend on whether class Foo defined a member f that accepted an int argument. So whenever you derived a function from a class that someone else had written, you would have to know the name and argument types of every function in that base class, just in case you happened to define a function with the same name yourself.

Even worse: Suppose a newer version of the base class came along and defined a function that did not exist in a previous version? All of a sudden, you would find the meaning of your code changed.

So what C++ actually does is to say that a derived class is a new scope. Except for virtual functions, very name defined in a derived class hides the corresponding name from any base classes. Although this rule sometimes behaves in ways that seem surprising, in most cases it is safer than the alternative.

arkoenig 340 Practically a Master Poster

Here's a hint for constructing the proof.

Suppose you have read some numbers, and there are other numbers you haven't read yet so you don't know what they are.

Pick one of the numbers you've read so far. Your job is to prove that whatever that number might be, it is possible that the numbers you are about to read will make it necessary for you to keep that number. To do this, you do not have to know what the unread numbers are -- you just have to imagine what they might be.

Another part of the point of this exercise, by the way, is to get you familiar with how people think about proofs, because often the best way of convincing yourself that a program works correctly is to sketch a simple proof. It doesn't even have to have every detail filled in.