#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    27
    Rep Power
    0

    Probably passing the parameter wrong, can't see what's wrong.


    So I was writing a code to simulate the results of a sport league and had to use some specific functions, but after checking what was wrong (took me a lot of time testing stuff to be honest), I found out that one of the functions, wich should modificate the number of teams, was not working correctly.

    Using some printf's I found out that in the ends of the function, the value was 1 after the first team was added, but right in the next line out of the function, the value was 0 again, even when I used a pointer as parameter.

    Here's what it looks like, I need a function "find_team" to search for a team and return it's position and in case the team is not already in the array, it creates a new team in the position *totals, wich goes +1.


    int find_team(struct Team teams[], int *totals, char team[])
    :code:
    new_team(teams,totals,team);
    //printf here says the value is 0, even after being 1 at the very end of the function.
    :code:

    void new_team(struct Team teams[], int *totals, char team[])
    :code:
    //printf here says the value is 0.
    *totals++; //last line of this funciont should make totals go to 1 at the beggining.
    //printf here says the value is 1.


    Any idea how to fix these functions? I'm almost sure I'm doing something wrong in the parameters, but I really can't see what is wrong.

    By the way, sorry for not posting the full code, but it's a school project and in case I post the full code, someone might just google the function protype given and copy it, and I'd be really in a bad situation if that happened.
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    int find_team(struct Team teams[], int *totals, char team[])
    :code:
    new_team(teams,totals,team);
    How is the totals in the function call declared? As int or as int* ?

    Assuming that that totals is an int and not a pointer, then the function call would be wrong. You would need to pass the address of totals. The address operator is &, so you would need to pass &totals, based on my asssumption stated at the beginning of this paragraph.

    A side-effect of the error of passing an int value which the function will treat as a pointer would be that you would clobber whatever memory location that happened to be. And since that location would very likely be outside your program's allocated memory space, your program should be likely to crash with an access or segmentation fault ... if you're lucky. If you're not lucky, then your program will quietly corrupt itself and present you with bizarre and inexplicable errors.

    When you attempt to use an int as a pointer or vice versa, the compiler will normally warn you about it. Be certain to always turn warnings on and to heed the warnings. Warnings are much more important than error messages, so never ignore warnings!

    void new_team(struct Team teams[], int *totals, char team[])
    :code:
    //printf here says the value is 0.
    *totals++; //last line of this funciont should make totals go to 1 at the beggining.
    //printf here says the value is 1.
    Always pay attention to the Order of Precedence of operators. You know almost instinctively that multiplication is performed before addition, but which is performed first, dereferencing or post-incrementing? Refer to the Order of Precedence to find out.

    As it turns out, post-incrementing/decrementing have the highest precedence, so it will always be performed first. So here is what the following line of code actually does:
    *totals++;
    First you increment the pointer, totals, to point to the next integer position. That means that, given 32-bit integers, totals will now point 4 bytes higher in memory. Then you dereference the new location that totals is pointing at, which doesn't do anything.

    What you want and meant to do is that you want to first dereference totals and then increment that dereferenced value, thus incrementing the value stored at the location that totals is pointing at. In order to do that, you need to use parentheses to circumvent the natural Order of Precedence and thus change the order of the operations being performed. Thus:
    (*totals)++;


    [quote]
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    27
    Rep Power
    0
    Originally Posted by dwise1_aol
    How is the totals in the function call declared? As int or as int* ?

    Assuming that that totals is an int and not a pointer, then the function call would be wrong. You would need to pass the address of totals. The address operator is &, so you would need to pass &totals, based on my asssumption stated at the beginning of this paragraph.
    In main "totals" is declared as int. Now should I change the parameter in all the functions or just how I pass the parameters in main?

    Originally Posted by dwise1_aol
    A side-effect of the error of passing an int value which the function will treat as a pointer would be that you would clobber whatever memory location that happened to be. And since that location would very likely be outside your program's allocated memory space, your program should be likely to crash with an access or segmentation fault ... if you're lucky. If you're not lucky, then your program will quietly corrupt itself and present you with bizarre and inexplicable errors.

    When you attempt to use an int as a pointer or vice versa, the compiler will normally warn you about it. Be certain to always turn warnings on and to heed the warnings. Warnings are much more important than error messages, so never ignore warnings!


    Always pay attention to the Order of Precedence of operators. You know almost instinctively that multiplication is performed before addition, but which is performed first, dereferencing or post-incrementing? Refer to the Order of Precedence to find out.

    As it turns out, post-incrementing/decrementing have the highest precedence, so it will always be performed first. So here is what the following line of code actually does:
    *totals++;
    First you increment the pointer, totals, to point to the next integer position. That means that, given 32-bit integers, totals will now point 4 bytes higher in memory. Then you dereference the new location that totals is pointing at, which doesn't do anything.

    What you want and meant to do is that you want to first dereference totals and then increment that dereferenced value, thus incrementing the value stored at the location that totals is pointing at. In order to do that, you need to use parentheses to circumvent the natural Order of Precedence and thus change the order of the operations being performed. Thus:
    (*totals)++;
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    Just change how you pass it in main(): as &totals . Think about it and you'll see why.
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    27
    Rep Power
    0
    I tried but then the function were expecting '**' as parameters and when I changed everything stopped working. I'll post the code.

    Except for some minor functions wich I'm pretty sure are not the problem, the code looks like this:

    #include <stdio.h>

    typedef struct _team {
    char name[21];
    int W;
    int L;
    int D;
    int S;
    int OS;
    } Team;

    void swap(Team *team1, Team *team2){
    Team temp;
    temp = *team1;
    *team1 = *team2;
    *team2 = temp; //I can do this with structures right? Or do I have to swap each of the components?
    }

    void bubblesort(Team teams[], int totals){
    int i,j;
    for(i=totals-1; i>0; i--){
    for(j=0; j < i; j++){
    if(compare(teams[j],teams[j+1])==0){ //function used here has no problems, so I won't bother writing it again.
    swap(&teams[j], &teams[j+1]);
    }
    }
    }
    }

    void new_team(Team teams[], int *totals, char team[]){//assume you have n teams, then the last one is on n-1 position on teams[], so the next will be on n position.
    int i=0;
    while(team[i]!='\0'){
    teams[*totals].name[i] = team[i];
    }
    teams[*totals].W = 0;
    teams[*totals].L = 0;
    teams[*totals].D = 0;
    teams[*totals].S = 0;
    teams[*totals].OS = 0;
    *totals++;//at this point, let's totals goes to 1. BUT...
    }

    int find_position(Team teams[], int *totals, char team[]){//Given a string with the name of a team, I want to know what position is it, and if it's in neither, I'll add it to the vector.
    int i,j;
    i = 0;
    j = 0;
    while(i<*totals && j != '\0'){
    if (teams[i].name[j] == team[j]){
    if(team[j]=='\0'){return i;}
    j++;
    }
    else{i++; j=0;}
    }

    new_team(teams, totals, team);
    //At this point, right after exiting the function, totals is 0.
    return *totals-1;
    }

    void update(Team teams[50], int *totals, char team1[21], int s, int os){
    int i;
    i = find_position(teams,totals,team1);
    teams[i].S = teams[i].S + s;
    teams[i].OS = teams[i].OS + os;
    if (s>os){teams[i].W++;}
    if(os>s){teams[i].L++;}
    if(os==s){teams[i].D++;}
    }

    int main() {
    Team teams[50];
    char team1[21], team2[21];
    int games, totals, i, s1, s2;

    scanf("%d", &games);

    ntimes = 0;
    for (i = 0; i < games; i++) {
    scanf("%s %d x %d %s", team1, &s1, &s2, team2);

    update(teams, &totals, team1, s1, s2);
    update(teams, &totals, team2, s2, s1);
    }

    bubblesort()(teams, totals);

    print_table(teams, totals);

    return 0;
    }
    Can you see what is wrong with the pointer issue? Well, if it's the case I might post the rest of the functions, but since the issue is mainly in the interaction from update,find_position and new_team I think this might be enough.
  10. #6
  11. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    I tried but then the function were expecting '**' as parameters and when I changed everything stopped working.
    Huh? I have no idea what you're talking about there. I certainly never suggested declaring any parameter to be changed to a pointer-pointer. Rather, I told you to pass the address of totals when you call a function that expects the address of totals, as I see you now doing in the update() calls. So I don't have any idea what you were trying.

    I'll post the code.

    Except for some minor functions wich I'm pretty sure are not the problem, the code looks like this:
    Do not use quote tags when you post code, especially if you continue to use K&R format. When you hide the open brace at the ends of lines and embedded within a single line between code and a comment, then the only way we can tell that a block of code had started is by seeing the indentation. But if you don't use code tags then that indentation disappears through the magic of HTML and we're left trying to decipher an unreadable mess.

    Use code tags! These are code tags: [code][/code] . Simply type them in, then copy and paste your indented code between them and you'll get something like this (though I slightly modified it by moving overly long comments to their own lines so they don't clutter up the code and moving open braces to their own lines so we can see them):

    Code:
    #include <stdio.h>
    
    typedef struct _team 
    {
        char name[21];
        int W;
        int L;
        int D;
        int S;
        int OS;
    } Team;
    
    void swap(Team *team1, Team *team2)
    {
        Team temp;
        temp = *team1;
        *team1 = *team2;
        *team2 = temp; //I can do this with structures right? Or do I have to swap each of the components?
    }
    
    void bubblesort(Team teams[], int totals)
    {
        int i,j;
        for(i=totals-1; i>0; i--)
        {
            for(j=0; j < i; j++)
            {
                //function used here has no problems, so I won't bother writing it again.
                if(compare(teams[j],teams[j+1])==0) 
                {
                    swap(&teams[j], &teams[j+1]);
                }
            }
        }
    }
    
    //assume you have n teams, then the last one is on n-1 position on teams[], so the next will be on n position.
    void new_team(Team teams[], int *totals, char team[])
    {
        int i=0;
        while(team[i]!='\0')
        {
            teams[*totals].name[i] = team[i];
        }
        teams[*totals].W = 0;
        teams[*totals].L = 0;
        teams[*totals].D = 0;
        teams[*totals].S = 0;
        teams[*totals].OS = 0;
        *totals++;//at this point, let's totals goes to 1. BUT...
    }
    
    //Given a string with the name of a team, I want to know what position is it, and if it's in neither, I'll add it to the vector.
    int find_position(Team teams[], int *totals, char team[])
    {
        int i,j;
        i = 0;
        j = 0;
        while(i<*totals && j != '\0')
        {
            if (teams[i].name[j] == team[j])
            {
                if(team[j]=='\0'){return i;}
                j++;
            }
            else{i++; j=0;}
        }
    
        new_team(teams, totals, team);
        //At this point, right after exiting the function, totals is 0.
        return *totals-1;
    }
    
    void update(Team teams[50], int *totals, char team1[21], int s, int os)
    {
        int i;
        i = find_position(teams,totals,team1);
        teams[i].S = teams[i].S + s;
        teams[i].OS = teams[i].OS + os;
        if (s>os){teams[i].W++;}
        if(os>s){teams[i].L++;}
        if(os==s){teams[i].D++;}
    }
    
    int main() 
    {
        Team teams[50];
        char team1[21], team2[21];
        int games, totals, i, s1, s2;
    
        scanf("%d", &games);
    
        ntimes = 0;
        for (i = 0; i < games; i++) 
        {
            scanf("%s %d x %d %s", team1, &s1, &s2, team2);
    
            update(teams, &totals, team1, s1, s2);
            update(teams, &totals, team2, s2, s1);
        }
    
        bubblesort()(teams, totals);
    
        print_table(teams, totals);
    
        return 0;
    }

    swap(): You want to swap two Team pointers, so declare temp to be a pointer as well, a Team* . temp needs to be the same datatype as what it's being used to swap.

    new_team(): I already talked to you about this: *totals++; . What did I say? I already told you that it's the pointer itself that's getting incremented, not the contents of what it originally pointed at. I also already told you how it needs to be written. Since you decided to ignore what I told you, I don't see any reason to tell you again.


    Can you see what is wrong with the pointer issue? Well, if it's the case I might post the rest of the functions, but since the issue is mainly in the interaction from update,find_position and new_team I think this might be enough.
    What I think I'm seeing is that totals is the variable to holding the number of teams that there are and that the only place where it gets changed is the last line of new_team() -- though you're not actually changing it because the pointer is incremented away to point to either games or i instead, a change that is forgotten immediately as you return from new_team(). So while you're passing the address of totals to functions that don't change totals, they do eventually call new_team() which is supposed to change it (but doesn't because of the bug I told you about but which you didn't fix), so that makes sense now.

    Fix that bug in new_team and the new one I spotted in swap(). Which you should have gotten warnings about so why are you ignoring warnings? Never ignore warnings! And never turn off warnings! Warnings are very much more important than error messages are! Until you can compile without errors nor warnings, you do not have a clean compile. Never ignore warnings!

    Comments on this post

    • salem agrees : Well said
  12. #7
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    27
    Rep Power
    0
    Well, first I'd like to thank you for the help and apologize for using the quote instead of code, didn't even realize it would remove the indentation.

    I guess I was just tired yesterday, the code I posted above was the one I had before starting the thread, and after you told me to use the (*totals)++ I had changed the way the variable was declared in main, then everything became a big mess.

    I just re-wrote the code and now it's giving me the right value outside the function and except for some minor errors I'll still have to fix, the code is working fine.

    It just bothers me that I could have used *totals = *totals + 1 since the beggining instead of ++ and I guess it would work without all this trouble.

    Anyway, thank you again, and sorry for the big deal I made of a small detail.

IMN logo majestic logo threadwatch logo seochat tools logo