Pointers Are Teh Devil!

OttoDestructOttoDestruct Join Date: 2002-11-08 Member: 7790Members
<div class="IPBDescription">C++ questions</div> Erm... I have no idea whats wrong with my prog. Every tutorial I've read on pointers has just ended up screwing my program up worse, so heres the code and errors which I'm getting. Any suggestions are appreciated. Oh yea.. the program is supposed to create an array of random numbers, then the two pointers of arrays are supposed to have each element point to the array, putting it in an order. Right now I've just got it to do a normal sort with values, not pointers.

<!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
#include <time.h>
#include <iostream.h>
#include <math.h>

int main (void)
{
 // Local Declaration
 int array[5];
 int *pAscending = new int[5];
 int *pDescending = new int[5];

 // Prototype Declaration
 void generatearray(int[], &int, &int);
 void sortascend (int[], &int);
 void sortdescend (int[], &int);
 void displayarray (int[], &int, &int);
 
 generatearray(array, &pAscending, &pDescending);
 sortascend (array, &pAscending);
 sortdescend (array, &pDescending);
 displayarray (array, &pAscending, &pDescending);
}

void generatearray (int array[], int *pAscending, int *pDescending)
{
 int i = 0;
 srand(clock());
 
 for (i = 0; i < 5; i++)
  array[i] = (rand()%98+1); // for

 for (i=0; i < 5; i++)
  *(pAscending+i) = array[i]; // for
 
 for (i=0; i < 5; i++)
  *(pDescending+i) = array[i]; // for
} // generatearray

void sortascend (int array[], int *pAscending)
{
 int i = 0;
 int temp = array[0];
 void exchangelargest (int*, int, int);
 
 for (i = 0; i < 5; i++)
  exchangelargest (&pAscending, i, temp);
} // sortascend  

void exchangelargest (int *pAscending, int i, int temp)
{
 int temp2;
 
 for (i=1;i < 5; i++)
  {
   if (temp > (*(pAscending+i)))
    {
    temp2 = *(pAscending+i);
    *(pAscending+i) = temp;
    temp = temp2;
    } // if
   } // for
} // exchangelargest  
 
void sortdescend (int array[], int *pDescending)
{
 int i = 0;
 int temp = array[0];
 void exchangesmallest (int*, int, int);
 
 for (i = 0; i < 5; i++)
  exchangesmallest (int &pAscending, int i, int temp);
} // sortdescend

void exchangesmallest (int *pAscending, int i, int temp)
{
 int temp2;
 
 for (i=1;i < 5; i++)
  {
   if (temp < (*(pAscending+i)))
    {
    temp2 = *(pAscending+i);
    *(pAscending+i) = temp;
    temp = temp2;
    } // if
   } // for
} // sortascend

void displayarray (int array[], int *pAscending, int *pDescending)
{
 int i;

  cout << "Program by Aaron Friedley" << endl << "Ascending" <<"\tOriginal"
        << "\tDescending" << endl;
       
 for (i = 0; i < 5; i++)
  {
   cout << *(pAscending+i) << "\t" << array[i] << "\t" << *(pDescending+i)
        << endl;
  }
}
<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

These are the errors I get:
<!--QuoteBegin--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>QUOTE</b> </td></tr><tr><td id='QUOTE'><!--QuoteEBegin-->
cxx: Error: hwk04.cxx, line 13: expected a type specifier
  void generatearray(int[], &int, &int);
----------------------------^
cxx: Error: hwk04.cxx, line 13: expected a type specifier
  void generatearray(int[], &int, &int);
----------------------------------^
cxx: Error: hwk04.cxx, line 14: expected a type specifier
  void sortascend (int[], &int);
--------------------------^
cxx: Error: hwk04.cxx, line 15: expected a type specifier
  void sortdescend (int[], &int);
---------------------------^
cxx: Error: hwk04.cxx, line 16: expected a type specifier
  void displayarray (int[], &int, &int);
----------------------------^
cxx: Error: hwk04.cxx, line 16: expected a type specifier
  void displayarray (int[], &int, &int);
----------------------------------^
cxx: Error: hwk04.cxx, line 46: argument of type "int **" is incompatible
          with parameter of type "int *"
  exchangelargest (&pAscending, i, temp);
--------------------^
cxx: Error: hwk04.cxx, line 71: type name is not allowed
  exchangesmallest (int &pAscending, int i, int temp);
---------------------^
cxx: Error: hwk04.cxx, line 71: identifier "pAscending" is undefined
  exchangesmallest (int &pAscending, int i, int temp);
--------------------------^
cxx: Error: hwk04.cxx, line 71: type name is not allowed
  exchangesmallest (int &pAscending, int i, int temp);
--------------------------------------^
cxx: Error: hwk04.cxx, line 71: too few arguments in function call
  exchangesmallest (int &pAscending, int i, int temp);
------------------------------------------^
cxx: Error: hwk04.cxx, line 71: expected a ")"
  exchangesmallest (int &pAscending, int i, int temp);
------------------------------------------^
cxx: Info: 12 errors detected in the compilation of "hwk04.cxx".
<!--QuoteEnd--></td></tr></table><div class='postcolor'><!--QuoteEEnd-->
«1

Comments

  • OttoDestructOttoDestruct Join Date: 2002-11-08 Member: 7790Members
  • SkulkBaitSkulkBait Join Date: 2003-02-11 Member: 13423Members
    edited March 2004
    why are your prototype and actual function definitions different?

    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->void generatearray(int[], &int, &int);<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->void generatearray (int array[], int *pAscending, int *pDescending)<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

    I''m pretty sure that your prototype should be:

    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->void generatearray(int[], int*, int*);<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

    (BTW, you also had the synax wrong for the other form, it should have been:
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->void generatearray(int[], int&, int&);<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->, but thats probably not what you want)

    EDIT: Oh, and IIRC the array[] syntax is not supported in C (except in the main), you have to take it as int** to get the pointer to the array (which is actually a pointer).

    EDIT 2: I might be wrong about all this, I haven't used pointers a whole lot in a while.
  • Umbraed_MonkeyUmbraed_Monkey Join Date: 2002-11-25 Member: 9922Members
    Skulkbait, he used a short-cut on em. Theres nothing syntatically wrong with those as far as I can tell. The * and &'s however, Im not so sure about...Im sorta rusty on this stuff now :/
  • OttoDestructOttoDestruct Join Date: 2002-11-08 Member: 7790Members
    I've tried every combination of * and & in the declaration / prototype. It either returns with the 12 listed errors or 20 errors, more of the ones listed.
  • 7Bistromath7Bistromath Join Date: 2003-12-04 Member: 23928Members, Constellation
    edited March 2004
    I don't know much about pointers, so I may be fixing the wrong problems here. But here's what I can see wrong straight off.<!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->int main (void)
    {
    (some stuff in here)

    (note lack of return statement)
    }<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->You've got main listed as an int, but you give no return value. From what I understand, you can't omit that return statement unless you declare void main(). Also, there shouldn't be anything inside the parentheses. You've got "void" in there, and I think when you do that, the compiler recognizes what you're doing as a function protype or definition, rather than a call.

    PS: I usually put my function prototypes outside main. I don't know if that would help, but it couldn't hurt to try.
  • OttoDestructOttoDestruct Join Date: 2002-11-08 Member: 7790Members
    Ack forgot the return, yes, but I doubt its whats causing all the problems. As for the int main (void), I've done it like that in every program I've written, no problems. And as far as the global declaration, our professor wants us to do everything local.
  • SkulkBaitSkulkBait Join Date: 2003-02-11 Member: 13423Members
    edited March 2004
    Ok, I took a closer look and managed to eliminate all the pointer errors (in my compiler at least)

    First, change your prototypes to be in the format

    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->void functionname(int[] var, int *var, int *var)<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

    as suggested erlier. Next, wherever you call these functions, remove the '&' before the variable name. Such as:

    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->exchangelargest (&pAscending, i, temp);<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
    becomes:
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->exchangelargest (pAscending, i, temp);<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

    Last but not least, fix the call in the for loop in sortdescend by removing the type specifiers from it:


    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->exchangesmallest (int &pAscending, int i, int temp);<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
    becomes:
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->exchangesmallest (pAscending, i, temp);<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

    This left me with errors related to my compiler, so it should compile for you. Note that just because it compiles doesn't mean that it won't crash while running, just that there are no syntactical errors.

    EDIT: oh, except that one related to pAscending being undeclared somewhere. Did you mean pDescending?

    <!--QuoteBegin--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>QUOTE</b> </td></tr><tr><td id='QUOTE'><!--QuoteEBegin-->You've got "void" in there, and I think when you do that, the compiler recognizes what you're doing as a function protype or definition, rather than a call.<!--QuoteEnd--></td></tr></table><div class='postcolor'><!--QuoteEEnd-->

    This depends on the compiler, most don't care. I'm not sure which is the actually standard syntax.


    EDIT 2: I'm not sure how this is supposed to output, but I didn't get any crashes so the pointer logic seems good.
  • SoulSkorpionSoulSkorpion Join Date: 2002-04-12 Member: 423Members
    edited March 2004
    Hokai. I'll post the errors as I identify them, and hopefully what's causing your program to not work will be in there <!--emo&;)--><img src='http://www.unknownworlds.com/forums/html//emoticons/wink.gif' border='0' style='vertical-align:middle' alt='wink.gif' /><!--endemo-->

    First of all, this block is troubling me:

    <!--QuoteBegin--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>QUOTE</b> </td></tr><tr><td id='QUOTE'><!--QuoteEBegin-->int array[5];
    int *pAscending = new int[5];
    int *pDescending = new int[5];
    <!--QuoteEnd--></td></tr></table><div class='postcolor'><!--QuoteEEnd-->
    What you're doing here is declaring three arrays of five integers each. One of which is normal, two of which you're allocating yourself. You haven't freed the memory for the two arrays you've allocated anywhere that I can see, and that's a bad thing. Also, there's no reason for you to have allocated the memory yourself, rather than just used arrays (and I have a suspicion that you didn't mean to make two more arrays at all). [edit]On a second look, you did mean to, so never mind. You still don't need to allocate the arrays yourself, and I'll tell you why later on[/edit]

    <!--QuoteBegin--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>QUOTE</b> </td></tr><tr><td id='QUOTE'><!--QuoteEBegin--> void generatearray(int[], &int, &int);
    void sortascend (int[], &int);
    void sortdescend (int[], &int);
    void displayarray (int[], &int, &int);

    generatearray(array, &pAscending, &pDescending);
    sortascend (array, &pAscending);
    sortdescend (array, &pDescending);
    displayarray (array, &pAscending, &pDescending);
    <!--QuoteEnd--></td></tr></table><div class='postcolor'><!--QuoteEEnd-->
    Whoa. Whoa whoa. Stop. Major problems in here, and it's definately because you're having trouble understanding pointers.

    Firstly, your prototypes are different from what you're passing to them. Secondly, they're incorrect. Let's take the first one.

    The prototype is <span style='font-family:Courier'>void generatearray(int[], &int, &int);</span>. The parameters are an integer array and two integer <b>reference variables</b>. You've called it as <span style='font-family:Courier'>(array, &pAscending, &pDescending);</span>, passing it an integer array (ok), and two <b>integer addresses</b>.

    I'll stop here and give you a brief rundown of pointers, reference variables, arrays and addresses.

    Pointers are always referred to as <span style='font-family:Courier'>type *</span>. So an integer pointer is <span style='font-family:Courier'>int *</span>. If you want to pass a pointer, the prototype should have a pointer in it; ie <span style='font-family:Courier'>int *</span> and not <span style='font-family:Courier'>int &</span>. As you should know, pointers point to a variable through its memory address.

    The ampersand operator, when <i>used on an existing variable</i> (note: NOT in a variable declaration) returns the <i>address</i> of that variable. That's important. I just mentioned that pointers refer to a variable through their memory address; this is how you get that address. You might have something like this:
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->int someNumber = 5;
    int *somePointer; //declare an integer pointer
    somePointer = &someNumber; /*assign the memory address of someNumber to somePointer, allowing somePointer to point to it*/<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
    Now the value of <span style='font-family:Courier'>somePointer</span> is some crazy hexadecimal value which is the memory location of the variable <span style='font-family:Courier'>someNumber</span>. To get at the value of whatever <span style='font-family:Courier'>somePointer</span> is pointing at, you stick an asterisk in front of it. Like this:

    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->int anotherNumber;
    anotherNumber = *somePointer; //somePointer still pointing at someNumber
    <!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
    <span style='font-family:Courier'>anotherNumber</span>'s value will now be 5. This is exactly the same as:
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
    anotherNumber = someNumber;<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

    Next. There are such things as reference variables, which you're using (I think by accident). You <i>declare</i> a reference variable the same way you declare a pointer, except you use an ampersand instead of an asterisk. Using reference variables instead of pointers, our above example would be:
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->int someNumber = 5;
    int &someReference = someNumber; //declare an integer reference var and initialise it to refer to someNumber
    <!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
    From now on, whenever we use <span style='font-family:Courier'>someReference</span>, it is <i>exactly</i> as if we'd used <span style='font-family:Courier'>someNumber</span>. It's like a pointer, but without the pointer syntax (and, as far as I know, no way of changing it to point to something else, which is why I assigned it on initialisation).

    So we don't need the * operator to get at what <span style='font-family:Courier'>someReference</span> refers to.
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->int anotherNumber;
    anotherNumber = someReference;<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

    Next. Arrays are pointers. Pointers are arrays. They are the same thing. When you have this code...
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->int array[10];<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
    ...the variable <span style='font-family:Courier'>array</span> is an integer pointer, pointing at the first integer in a contiguous block of ten integers (uh, "contigous" means one after another, with no gaps in between).

    Because C is nice to you (ha!. well, nice <i>this time</i>), it lets you use alternate syntax if you want to clarify that your pointer is supposed to be an array. That's what you're using. For example, your prototype
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->void generatearray(int[], &int, &int);<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
    is identical exactly to the prototype
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1--> void generatearray(int*, &int, &int);<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
    in every way. Except of course that yours is better, because it makes it clear to the reader that the integer pointer is supposed to be an array.

    Now, let's have another read through and see what else I can spot...
  • SoulSkorpionSoulSkorpion Join Date: 2002-04-12 Member: 423Members
    Oh dear...

    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
    void generatearray(int[], &int, &int); //prototype
    generatearray(array, &pAscending, &pDescending);//function call
    void generatearray (int array[], int *pAscending, int *pDescending) //definition
    <!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

    You're saying three different things, when they're all supposed to be the same. Your prototype is for an integer array and two integer reference variables. You're passing it an integer array and two <i>addresses of integer arrays</i>. When you're implementing it, you're asking for an integer array and two integer pointers (in other words, three integer arrays).

    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1--> for (i=0; i < 5; i++)
     *(pAscending+i) = array[i]; // for<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
    This is completely valid. It's a bit convoluted (which might have been the point of the exercise, I don't know.). Just to clarify, what you've done is identical to:
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
    for(i=0; i < 5; i++)
    pAscending[i] = array[i];
    <!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
    I'm not saying change it. I'm just making you aware of it ;).

    I'm pretty sure that the compile errors you're getting are because of the stuff I mentioned earlier. You're getting mixed up about the syntax of declaring, defining and using pointers (and arrays). I haven't traced the execution of your algorithm to verify that it's correct (that's your job :P) but I think that's your compiler errors fixed. Oh, and remember to <span style='font-family:Courier'>delete</span> that memory you allocated in <span style='font-family:Courier'>main</span>. Or better yet don't allocate it in the first place and just use normal arrays.
  • SoulSkorpionSoulSkorpion Join Date: 2002-04-12 Member: 423Members
    edited March 2004
    <!--QuoteBegin-007Bistromath+Mar 7 2004, 11:24 AM--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>QUOTE</b> (007Bistromath @ Mar 7 2004, 11:24 AM)</td></tr><tr><td id='QUOTE'><!--QuoteEBegin--> I don't know much about pointers, so I may be fixing the wrong problems here. But here's what I can see wrong straight off.<!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->int main (void)
    {
    (some stuff in here)

    (note lack of return statement)
    }<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->You've got main listed as an int, but you give no return value. From what I understand, you can't omit that return statement unless you declare void main(). Also, there shouldn't be anything inside the parentheses. You've got "void" in there, and I think when you do that, the compiler recognizes what you're doing as a function protype or definition, rather than a call. <!--QuoteEnd--></td></tr></table><div class='postcolor'><!--QuoteEEnd-->
    *Bzzt*. Wrong, but thanks for playing.

    The C standard mandates that <span style='font-family:Courier'>main</span> must be declared as returning an int. Yes, MSVC++ is <i>wrong and bad</i> for allowing you to declare it as void. That is <i>non-standard. Do <b>not</b> do it.</i>

    However, the C standard also mandates that you don't have to put in the return value for main if you don't want to. Often, although you have to declare main as returning int, you never actually want it to return anything (like here. There are times when you <i>do</i> want it to return something, but that's another story.)

    By the way, it's less typing to do it the standard way. <span style='font-family:Courier'>int</span> is less typing than <span style='font-family:Courier'>void</span> <!--emo&;)--><img src='http://www.unknownworlds.com/forums/html//emoticons/wink.gif' border='0' style='vertical-align:middle' alt='wink.gif' /><!--endemo-->

    Finally, the business about putting <span style='font-family:Courier'>void</span> in the parameter list, while deprecated, is syntactically valid and can be used anywhere you'd ordinarily have an empty parameter list. It's basically used just to make it blindingly obvious that the function doesn't take any parameters. I don't use it, myself. Oh, in some instances <span style='font-family:Courier'>main</span> actually does take (two very specific) parameters, but it's perfectly legal to treat it as if it doesn't if you don't want them.
  • 7Bistromath7Bistromath Join Date: 2003-12-04 Member: 23928Members, Constellation
    <!--QuoteBegin-SoulSkorpion+Mar 6 2004, 11:15 PM--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>QUOTE</b> (SoulSkorpion @ Mar 6 2004, 11:15 PM)</td></tr><tr><td id='QUOTE'><!--QuoteEBegin-->
    *Bzzt*. Wrong, but thanks for playing.

    The C standard mandates that <span style='font-family:Courier'>main</span> must be declared as returning an int. Yes, MSVC++ is <i>wrong and bad</i> for allowing you to declare it as void. That is <i>non-standard. Do <b>not</b> do it.</i>

    However, the C standard also mandates that you don't have to put in the return value for main if you don't want to. Often, although you have to declare main as returning int, you never actually want it to return anything (like here. There are times when you <i>do</i> want it to return something, but that's another story.) <!--QuoteEnd--> </td></tr></table><div class='postcolor'> <!--QuoteEEnd-->
    Huh. Learn something new everyday.

    I learned that the C standard is structured stupidly, and internally inconsistent. Shocking.
  • SoulSkorpionSoulSkorpion Join Date: 2002-04-12 Member: 423Members
    <!--QuoteBegin-007Bistromath+Mar 7 2004, 12:22 PM--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>QUOTE</b> (007Bistromath @ Mar 7 2004, 12:22 PM)</td></tr><tr><td id='QUOTE'><!--QuoteEBegin--> <!--QuoteBegin-SoulSkorpion+Mar 6 2004, 11:15 PM--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>QUOTE</b> (SoulSkorpion @ Mar 6 2004, 11:15 PM)</td></tr><tr><td id='QUOTE'><!--QuoteEBegin-->
    *Bzzt*. Wrong, but thanks for playing.

    The C standard mandates that <span style='font-family:Courier'>main</span> must be declared as returning an int. Yes, MSVC++ is <i>wrong and bad</i> for allowing you to declare it as void. That is <i>non-standard. Do <b>not</b> do it.</i>

    However, the C standard also mandates that you don't have to put in the return value for main if you don't want to. Often, although you have to declare main as returning int, you never actually want it to return anything (like here. There are times when you <i>do</i> want it to return something, but that's another story.) <!--QuoteEnd--></td></tr></table><div class='postcolor'><!--QuoteEEnd-->
    Huh. Learn something new everyday.

    I learned that the C standard is structured stupidly, and internally inconsistent. Shocking. <!--QuoteEnd--> </td></tr></table><div class='postcolor'> <!--QuoteEEnd-->
    Weell... there <i>are</i> reasons. Well, one main one: efficiency. C (and C++) were built with the underlying philosophy of "you only pay for what you use".

    In this case it's because all programs return a code to the operating system when they terminate. That's the return value of main. So, main always does return an int. Similarly, sometimes you run a program with command line parameters - those parameters can get passed to main().

    It's just that if you don't have any use for returning a specific error code to the OS, C does it for you and returns a "move along, people, there's nothing to see here" code if you don't specify one. And you don't always need the command line parameters, so if you don't ask for them then C doesn't waste resources retrieving them for you. It might not be completely consistent, but it isn't irrational. And above all else, it's efficient.
  • Crono5Crono5 Join Date: 2003-07-22 Member: 18357Members
    I don't understand what people find so wrong about int main()... I mean, if something goes wrong in your code, you can always just terminate it by returning a number. Of course, I never actually tried typing return void or something with a void main...

    What were we talking about again?

    P.S. I <b>finally</b> get what pointers are.
  • SkulkBaitSkulkBait Join Date: 2003-02-11 Member: 13423Members
    edited March 2004
    <!--QuoteBegin-Crono5788+Mar 6 2004, 11:52 PM--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>QUOTE</b> (Crono5788 @ Mar 6 2004, 11:52 PM)</td></tr><tr><td id='QUOTE'><!--QuoteEBegin--> I don't understand what people find so wrong about int main()... I mean, if something goes wrong in your code, you can always just terminate it by returning a number. Of course, I never actually tried typing return void or something with a void main...

    What were we talking about again?

    P.S. I <b>finally</b> get what pointers are. <!--QuoteEnd--></td></tr></table><div class='postcolor'><!--QuoteEEnd-->
    with a void main you just return like this:
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->return;<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

    This works for any void function. But like scorpy said, its not standard in main(), so don't do it.

    Personally I rather like using the void keyword for parameters. If you'd ever seen my code you'd probably see why. <--- Is a code neat freak.
  • WheeeeWheeee Join Date: 2003-02-18 Member: 13713Members, Reinforced - Shadow
    Hmm, as noted above, passing by reference ( <i>functionname(typename <b>&</b>varname) </i> ) is different than passing in pointers; in all respects <i>varname</i> is treated (at least with respect to coding syntax) as a pass-by-value, but the compiler actually keeps track of a pointer to that <i>typename</i>. Also, it's pretty pointless to use pass-by-reference on primitive data types, as there really isn't a performance gain because the overhead to make a copy of the passed data really amounts to very small amounts.
  • SoulSkorpionSoulSkorpion Join Date: 2002-04-12 Member: 423Members
    <!--QuoteBegin-Wheeee+Mar 7 2004, 01:20 PM--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>QUOTE</b> (Wheeee @ Mar 7 2004, 01:20 PM)</td></tr><tr><td id='QUOTE'><!--QuoteEBegin--> Hmm, as noted above, passing by reference ( <i>functionname(typename <b>&</b>varname) </i> ) is different than passing in pointers; in all respects <i>varname</i> is treated (at least with respect to coding syntax) as a pass-by-value, but the compiler actually keeps track of a pointer to that <i>typename</i>. Also, it's pretty pointless to use pass-by-reference on primitive data types, as there really isn't a performance gain because the overhead to make a copy of the passed data really amounts to very small amounts. <!--QuoteEnd--> </td></tr></table><div class='postcolor'> <!--QuoteEEnd-->
    Yes, but he's passing arrays. You can't pass arrays any other way than by reference. Not primitive arrays, anyway.
  • OttoDestructOttoDestruct Join Date: 2002-11-08 Member: 7790Members
    edited March 2004
    <!--QuoteBegin--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>QUOTE</b> </td></tr><tr><td id='QUOTE'><!--QuoteEBegin-->What you're doing here is declaring three arrays of five integers each. One of which is normal, two of which you're allocating yourself. You haven't freed the memory for the two arrays you've allocated anywhere that I can see, and that's a bad thing. Also, there's no reason for you to have allocated the memory yourself, rather than just used arrays (and I have a suspicion that you didn't mean to make two more arrays at all). [edit]On a second look, you did mean to, so never mind. You still don't need to allocate the arrays yourself, and I'll tell you why later on[/edit]<!--QuoteEnd--></td></tr></table><div class='postcolor'><!--QuoteEEnd-->

    That was part of the assignment to use the two pointer arrays <!--emo&;)--><img src='http://www.unknownworlds.com/forums/html//emoticons/wink.gif' border='0' style='vertical-align:middle' alt='wink.gif' /><!--endemo-->

    <!--QuoteBegin--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>QUOTE</b> </td></tr><tr><td id='QUOTE'><!--QuoteEBegin-->Whoa. Whoa whoa. Stop. Major problems in here, and it's definately because you're having trouble understanding pointers.
    <!--QuoteEnd--></td></tr></table><div class='postcolor'><!--QuoteEEnd-->

    Correct <!--emo&:D--><img src='http://www.unknownworlds.com/forums/html//emoticons/biggrin.gif' border='0' style='vertical-align:middle' alt='biggrin.gif' /><!--endemo--> Like I said I've looked at five or six tutorials all telling me to do different stuff, thus why I posted here.

    <!--QuoteBegin--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>QUOTE</b> </td></tr><tr><td id='QUOTE'><!--QuoteEBegin-->
    That's what you're using. For example, your prototype
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->void generatearray(int[], &int, &int);<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
    is identical exactly to the prototype
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1--> void generatearray(int*, &int, &int);<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
    in every way. Except of course that yours is better, because it makes it clear to the reader that the integer pointer is supposed to be an array
    <!--QuoteEnd--></td></tr></table><div class='postcolor'><!--QuoteEEnd-->

    Yea the professor wanted us to use pointer notatin instead of array notation, teaching us good programming habits and all that.

    *Edit*

    You wouldnt happen to be able to give me a crash course on how to create a pointer within my pointer arrays would you?
  • SoulSkorpionSoulSkorpion Join Date: 2002-04-12 Member: 423Members
    edited March 2004
    <!--QuoteBegin-OttoDestruct+Mar 7 2004, 01:48 PM--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>QUOTE</b> (OttoDestruct @ Mar 7 2004, 01:48 PM)</td></tr><tr><td id='QUOTE'><!--QuoteEBegin--> You wouldnt happen to be able to give me a crash course on how to create a pointer within my pointer arrays would you? <!--QuoteEnd--></td></tr></table><div class='postcolor'><!--QuoteEEnd-->
    Hm...

    Well, the short answer is that you can't. An integer, a pointer to an integer, and a pointer to a pointer to an integer (or a pointer to an integer array, if it hurts your brain less <!--emo&;)--><img src='http://www.unknownworlds.com/forums/html//emoticons/wink.gif' border='0' style='vertical-align:middle' alt='wink.gif' /><!--endemo-->) are considered completely seperate data types.

    My understanding is that you want something like this:

    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
    int *allocatedArray = new int[10];
    int someNumber;
    int *somePointer = &someNumber;

    //and then, some arbitrary element...
    allocatedArray[5] = somePointer //make one of the elements a pointer
    //and the rest of the elements in the array are normal ints

    delete[] allocatedArray;
    <!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

    C doesn't let you have different data types in the same array. Of course, there are ways around that (in pure C they mostly invove void pointers. Nasty stuff which I'm not very experienced with.)

    But if that's not what you meant, and you just wanted a pointer to point to an element of the array, you can just use it and it'll work:
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
    int someArray[10];
    int *somePointer = &someArray[5];
    //somePointer now points at the sixth element of someArray
    <!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

    Or maybe you wanted an array of arrays?
    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
    int **arrayOfArrays = new (int*)[10]; //not actually sure of the syntax here. hehe.
    for(int i=0; i<10;++i)
    arrayOfArrays[i] = new int[10];
    <!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
  • OttoDestructOttoDestruct Join Date: 2002-11-08 Member: 7790Members
    Er.. heres a crappy photoshop of what I'm trying to say I want it to do... The two pointer arrays don't actually contain any values, but rather they contain the addresses of elements in the... array (named array <!--emo&:D--><img src='http://www.unknownworlds.com/forums/html//emoticons/biggrin.gif' border='0' style='vertical-align:middle' alt='biggrin.gif' /><!--endemo--> )
  • SoulSkorpionSoulSkorpion Join Date: 2002-04-12 Member: 423Members
    edited March 2004
    Ah. An array of pointers. Nasty, evil stuff, and except for the fact that it's an exercise almost completely useless in this case.

    Unfortunately, I'm not absolutely sure of the syntax myself. I can tell you this much, though...

    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->int *pAscending = new int[5];<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
    This declares an integer pointer, allocates a block of five integers, and makes the pointer point to the beginning of them.

    I think what you want is something like this:

    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->int *ascending[5];<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

    That is, an array of five integer pointers. Nothing's being dynamically allocated (I'm pretty sure you didn't want that in the first place). Each element of <span style='font-family:Courier'>ascending</span> is itself a pointer, and can be made to point to any integer the same as a normal pointer.

    And, technically, <span style='font-family:Courier'>ascending</span> is itself an <span style='font-family:Courier'>int *</span> pointer, pointing to the first <span style='font-family:Courier'>int *</span> in a contiguous block of five <span style='font-family:Courier'>int *</span>s. That makes it an <span style='font-family:Courier'>int **</span>.

    ...I've just done a quick test, and I was right about the syntax. Good luck <!--emo&:)--><img src='http://www.unknownworlds.com/forums/html//emoticons/smile.gif' border='0' style='vertical-align:middle' alt='smile.gif' /><!--endemo-->
  • OttoDestructOttoDestruct Join Date: 2002-11-08 Member: 7790Members
    I've been pounding away and I'm at a complete loss as to how to get this algorithm working. And the pointer arrays have to be dynamically allocated, as part of the assignment <!--emo&;)--><img src='http://www.unknownworlds.com/forums/html//emoticons/wink.gif' border='0' style='vertical-align:middle' alt='wink.gif' /><!--endemo-->
  • SkulkBaitSkulkBait Join Date: 2003-02-11 Member: 13423Members
    The syntax for creating a dynamically allocated array of pointers should go something like this:

    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->int **AoP;  //A pointer to an array of pointers
    int *x;  //An int pointer

    int main(void)
    {
     AoP = new int * [5];  //Points the pointer to a newly allocated array of int pointers
     AoP[1] = new int;  //Assigns the second pointer in the array pointed to by AoP to point to x
    }<!--c2--></td></tr></table><div class='postcolor'><!--ec2-->

    I can't help you with your algorithm, since I don't know what its supposed to be doing....
  • OttoDestructOttoDestruct Join Date: 2002-11-08 Member: 7790Members
    Well heres what I have for the algorithm(getting core dumps), and I can't use array notation by the way, only pointer notation. It looks at array and sorts pAscending, which is an array of pointers accordingly.

    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
    void sortascend (int array[], int **pAscending)
    {
     int i;

     void exchangelargest (int[], int**, int);

     for (i = 0; i < 5; i++)
      exchangelargest (array, pAscending, i);
    } // sortascend  

    void exchangelargest (int array[], int **pAscending, int i)
    {
     int walker;
     int largest;
     int *temp = *pAscending;
     largest = i;
     
     for (walker = i+1; walker <= 5; walker++)
      {
       if (array[walker] > array[largest])
        largest = walker; // if

      temp = *(pAscending+i);
      *(pAscending+i) = *(pAscending+largest);
      *(pAscending+largest) = temp;
      } // for
    }
    <!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
  • SoulSkorpionSoulSkorpion Join Date: 2002-04-12 Member: 423Members
    SkulkBait's got the right idea, except I don't think you mean to allocate the integers which the pointers point to (I think you just mean to allocate the integer pointers themselves).

    "Getting core dumps"? You mean segmentation faults?
  • GeminosityGeminosity :3 Join Date: 2003-09-08 Member: 20667Members
    edited March 2004
    I look at this excercise and the point of it considering how much you seem to have been taught regarding pointers already just goes screaming over my head o.O

    Despite the fact that looking at that code hurts my head... did you make pAscending actually point to anything yet? I don't see it anywhere in the code you provided in the last post so playing around with it while it's empty would give you major errors =P

    you're also having a loop in that allows walker to be 1-5, while in all previous loops you've been playing with 0-4... accessing 5 if nothing is there would cause some code explosions too ^^;


    <b>edit:</b> yeah, I know there's probably stuff in Main to handle pAscending actually pointing to something, but just incase...
  • SoulSkorpionSoulSkorpion Join Date: 2002-04-12 Member: 423Members
    Yay! Reinforcements! <!--emo&:)--><img src='http://www.unknownworlds.com/forums/html//emoticons/smile.gif' border='0' style='vertical-align:middle' alt='smile.gif' /><!--endemo-->
  • OttoDestructOttoDestruct Join Date: 2002-11-08 Member: 7790Members
    edited March 2004
    Yea well thanks for trying to help, I just got a 0 on the assignment as I still don't have it done because it still doesnt work, and I still don't understand why.
    *Edit*

    Goodie I now have a D in the course.
  • SoulSkorpionSoulSkorpion Join Date: 2002-04-12 Member: 423Members
    <!--QuoteBegin-OttoDestruct+Mar 9 2004, 05:57 AM--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>QUOTE</b> (OttoDestruct @ Mar 9 2004, 05:57 AM)</td></tr><tr><td id='QUOTE'><!--QuoteEBegin--> Yea well thanks for trying to help, I just got a 0 on the assignment as I still don't have it done because it still doesnt work, and I still don't understand why.
    *Edit*

    Goodie I now have a D in the course. <!--QuoteEnd--> </td></tr></table><div class='postcolor'> <!--QuoteEEnd-->
    Sorry to hear that <!--emo&:(--><img src='http://www.unknownworlds.com/forums/html//emoticons/sad.gif' border='0' style='vertical-align:middle' alt='sad.gif' /><!--endemo-->
  • JavertJavert Join Date: 2003-04-30 Member: 15954Members
    edited March 2004
    Did you ask for help from classmates?
    Is there a textbook? Useful? (Mine wasn't long way back ago.)
    Now that the assignment is over, you should really ask ur teacher for the solution. It may help later *cough*finals*cough*.
  • CreepieCreepie Join Date: 2003-02-19 Member: 13734Members
    edited March 2004
    This works.

    What I think the assignment requires is the sorting of a list of pointers to ints. You start off with an original array of ints. You then set up an array of pointers, each pointer points to an integer in the value array. This array of pointers is the one to be sorted.

    And you're right, pointers are the devil.

    <!--c1--></div><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
    #include <time.h>
    #include <iostream.h>
    #include <math.h>

    // Prototype Declarations
    // Don't declare protos in functions.  Nobody in the industry ever does this (you can tell
    //  your tutor this btw).
    // Always put names in protos for all arguments.  This makes things clearer to users using
    //  your functions - even if that person happens to be you
    // I never use [] notation in function arguments.  The type of an array's object are pointers
    //  to the first element.  So I use pointers to the first element.  For example, instead of using int[],
    //  I'll use int* (in fact, I use objects, classes and pass by reference - but that's not for here).

    // generate an array.  Set contents of ppAscending and ppDescending to point to array
    void generatearray(int* array, int** ppAscending, int** ppDescending);

    // sort ppAscending pointers in ascending order.
    // note: we don't need to pass array as we've already assigned ppAscending
    void sortascend(int** ppAscending);

    // sort ppDescending pointers in descending order
    // note: we don't need to pass array as we've already assigned ppDescending
    void sortdescend(int** ppDescending);

    // output contents of arrays
    void displayarray(int* array, int** ppAscending, int** ppDescending);

    int main (void)
    {
       // Local Declaration

       // the original array.  This is on the stack
       // note: you've hard-coded the array size to 5 all over the code.  In the real world, you
       //  wouldn't do this.  What if we decided we wanted an aray size of 10 ?  You'd have to
       //  go through all the code and change all the 5s to 10s.  And one mistyped value and *bang*
       int array[5];

       // the sorted arrays.  These are on the heap.  Remember they will will need cleaning when you've done with them.
       // this is an array of pointers to integers
       int** ppAscending = new int*[5];
       
       // check the allocation
       if (ppAscending)
       {
           int** ppDescending = new int*[5];

           // check the allocation
           if (ppDescending)
           {
               // you don't need to pass the address of anything here.
               generatearray(array, ppAscending, ppDescending);
               sortascend(ppAscending);
               sortdescend(ppDescending);
               displayarray(array, ppAscending, ppDescending);

               // don't forget to clean up stuff we allocated on the heap
               // note: we're using delete[] because we used new[]
               delete[] ppDescending;
           }

           delete[] ppAscending;
       }

       return 0;
    }

    void generatearray(int* array, int** ppAscending, int** ppDescending)
    {
       int i = 0;
       
       // I've used time(NULL) here.  Go back to using clock() if this doesn't work on your compiler.
       srand(time(NULL));
       
       // always block your code.  Believe me, it's better
       for (i = 0; i < 5; i++)
       {
           array[i] = (rand()%98+1);
       } // for
       
       // copy integer pointers
       for (i=0; i < 5; i++)
       {
           ppAscending[i] = &array[i];
       } // for
       
       // copy integer pointers
       for (i=0; i < 5; i++)
       {
           ppDescending[i] = &array[i];
       } // for
    } // generatearray

    // swap int*s
    void swap(int** ppLHS, int** ppRHS)
    {
       int* pValue = (*ppRHS);
       (*ppRHS) = (*ppLHS);
       (*ppLHS) = pValue;
    }

    // put the largest int* from i at i
    void exchangelargest(int** ppDescending, int from);
    void exchangesmallest(int** ppAscending, int from);

    void sortdescend(int** ppAscending)
    {
       int i = 0;

       // if I understand you correctly here, you are sorting the array by iterating
       //  the array and putting the largest value from the array remainder at each iteration
       
       // note: we only need to iterate up to 5 - 1 because the last value will always be the smallest after 5 - 1
       //  iterations
       for (i = 0; i < 4; i++)
       {
           exchangelargest(ppAscending, i);
       }
    } // sortdescend  

    void sortascend(int** ppDescending)
    {
       int i = 0;

       // note: we only need to iterate up to 5 - 1
       for (i = 0; i < 4; i++)
       {
           exchangesmallest(ppDescending, i);
       }
    } // sortascend  

    void exchangelargest(int** ppDescending, int from)
    {
       int** largest = &ppDescending[from];

       int i = from + 1;

       while (i < 5)
       {
           if (*ppDescending[i] > **largest)
           {
               largest = &ppDescending[i];
           }

           i++;
       }

       swap(&ppDescending[from], largest);

    } // exchangelargest  

    void exchangesmallest(int** ppAscending, int from)
    {
       int** smallest = &ppAscending[from];

       int i = from + 1;

       while (i < 5)
       {
           if (*ppAscending[i] < **smallest)
           {
               smallest = &ppAscending[i];
           }

           i++;
       }

       swap(&ppAscending[from], smallest);

    } // exchangesmallest  

    void displayarray (int* array, int** ppAscending, int** ppDescending)
    {
       int i;

       // I've used printf here because it works better in my development environment.
       printf("Program by A. Friend.\nAscending (ptr)\tOriginal (ptr)\tDescending (ptr)\n");
       
       for (i = 0; i < 5; i++)
       {
           // I'm also outputting the pointers so you can see where the values in the sorted lists are coming from.
           printf("%d (%p)\t%d (%p)\t%d (%p)\n", *ppAscending[i], ppAscending[i], array[i], &array[i], *ppDescending[i], ppDescending[i]);
       }
    }

    <!--c2--></td></tr></table><div class='postcolor'><!--ec2-->
Sign In or Register to comment.