admin管理员组

文章数量:1401233

I'm passing a dynamic array of structures to a function with the intent to write them into a binary file but after it's in the array the first values are the same (Arr+0) but the values after are garbage values when printing them out.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
int compGamesByTitle(const void * a, const void * b);
int compGamesByPrice(const void * a, const void * b);
typedef struct {
    double price;
    char title[25];
    unsigned int popularity:3;
} game;
void writeBinary(game** Arr);
int compGamesByTitle(const void * a, const void * b)
{
    game* p2first = *(game **)a;
    game* p2second = *(game **)b; 
    return strcmp(p2first->title,p2second->title);
}

int compGamesByPrice(const void * a, const void * b)
{  
    game* p2first = *(game **)a;
    game* p2second = *(game **)b;
    return (p2first->price - p2second->price);
}
int main()
{
    // create Array
    int SIZE_OF_ARR = sizeof(game*)*6;
    game** Arr = malloc(SIZE_OF_ARR);
    double price[] = {22.79,0.01,14.99,0,7.79,64.96};
    char* title[] = {"Opus Magnum","Minecraft", "Trainz","Code Combat", "Lemmings Revolution", "Warcraft"};
    unsigned popularity[] = {1,4,2,3,3,1};
    for (int i = 0; i < 6; i++)
    {
        Arr[i] = malloc(sizeof(game));
        Arr[i]->price = price[i];
        strcpy(Arr[i]->title,title[i]);
        Arr[i]->popularity = popularity[i];
    }
    qsort(Arr,6,sizeof(game*),compGamesByTitle);
    //print
    printf("%s | %-20s | %s","Price", "Title", "Popularity\n");
    printf("----------\n");
    for (int i = 0; i < 6; i++)
    {
        printf("%5.2lf | %-20s | %2d\n",Arr[i]->price,Arr[i]->title,Arr[i]->popularity);
    }
    printf("----------\n");
    qsort(Arr,6,sizeof(game*),compGamesByPrice);
    //print 
    for (int i = 0; i < 6; i++)
    {
        printf("%5.2lf | %-20s | %2d\n",Arr[i]->price,Arr[i]->title,Arr[i]->popularity);
    }
    writeBinary(Arr);
    for (int i = 0; i < 6; i++)
    {
        free(Arr[i]);
    }
    free(Arr);
    return 0;
}
void writeBinary(game** Arr)
{
    FILE* p2out = fopen("out.bin","wb");
    for (int i = 0; i < 6;i++)
    {
        printf("%s \n",(*Arr+i)->title);
    }
    fclose(p2out);    
}

I'm Still very new to C and am lost as the why the values are not same.

I'm passing a dynamic array of structures to a function with the intent to write them into a binary file but after it's in the array the first values are the same (Arr+0) but the values after are garbage values when printing them out.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
int compGamesByTitle(const void * a, const void * b);
int compGamesByPrice(const void * a, const void * b);
typedef struct {
    double price;
    char title[25];
    unsigned int popularity:3;
} game;
void writeBinary(game** Arr);
int compGamesByTitle(const void * a, const void * b)
{
    game* p2first = *(game **)a;
    game* p2second = *(game **)b; 
    return strcmp(p2first->title,p2second->title);
}

int compGamesByPrice(const void * a, const void * b)
{  
    game* p2first = *(game **)a;
    game* p2second = *(game **)b;
    return (p2first->price - p2second->price);
}
int main()
{
    // create Array
    int SIZE_OF_ARR = sizeof(game*)*6;
    game** Arr = malloc(SIZE_OF_ARR);
    double price[] = {22.79,0.01,14.99,0,7.79,64.96};
    char* title[] = {"Opus Magnum","Minecraft", "Trainz","Code Combat", "Lemmings Revolution", "Warcraft"};
    unsigned popularity[] = {1,4,2,3,3,1};
    for (int i = 0; i < 6; i++)
    {
        Arr[i] = malloc(sizeof(game));
        Arr[i]->price = price[i];
        strcpy(Arr[i]->title,title[i]);
        Arr[i]->popularity = popularity[i];
    }
    qsort(Arr,6,sizeof(game*),compGamesByTitle);
    //print
    printf("%s | %-20s | %s","Price", "Title", "Popularity\n");
    printf("----------\n");
    for (int i = 0; i < 6; i++)
    {
        printf("%5.2lf | %-20s | %2d\n",Arr[i]->price,Arr[i]->title,Arr[i]->popularity);
    }
    printf("----------\n");
    qsort(Arr,6,sizeof(game*),compGamesByPrice);
    //print 
    for (int i = 0; i < 6; i++)
    {
        printf("%5.2lf | %-20s | %2d\n",Arr[i]->price,Arr[i]->title,Arr[i]->popularity);
    }
    writeBinary(Arr);
    for (int i = 0; i < 6; i++)
    {
        free(Arr[i]);
    }
    free(Arr);
    return 0;
}
void writeBinary(game** Arr)
{
    FILE* p2out = fopen("out.bin","wb");
    for (int i = 0; i < 6;i++)
    {
        printf("%s \n",(*Arr+i)->title);
    }
    fclose(p2out);    
}

I'm Still very new to C and am lost as the why the values are not same.

Share Improve this question edited Mar 24 at 2:32 Raeden Nesbitt asked Mar 24 at 2:26 Raeden NesbittRaeden Nesbitt 213 bronze badges 2
  • Can you reduce this to a minimal reproducible example? The code in this question is much, much more than is needed to demonstrate the problem. – Toby Speight Commented Mar 24 at 9:20
  • Not the main bug here but game* p2first = *(game **)a; etc is wrong, should be const game* p2first = *(const game **)a; – Lundin Commented Mar 24 at 12:04
Add a comment  | 

2 Answers 2

Reset to default 7

The issue is in writeBinary:

printf("%s \n",(*Arr+i)->title);

The pointer notation you used here isn't exactly the same as the array notation you used elsewhere. In other places you used Arr[i] which is equivalent to *(Arr+i). That's not what you have here. For it to be the same you'd need (*(Arr+i))->title). Also, you're writing to stdout instead of the file object you opened.

So the above should be:

fprintf(p2out,"%s \n",(*(Arr+i))->title);

Or more simply:

fprintf(p2out,"%s \n",Arr[i]->title);

On a side note, you don't actually have an array of structures but an array of pointers to structures. You can get rid of a level of indirection by creating an actual array of structs:

int SIZE_OF_ARR = sizeof(game)*6;
game *Arr = malloc(SIZE_OF_ARR);
...
for (int i = 0; i < 6; i++)
{
    Arr[i].price = price[i];
    strcpy(Arr[i].title,title[i]);
    Arr[i].popularity = popularity[i];
}   
...
int compGamesByTitle(const void * a, const void * b)
{
    const game *p2first = a;
    const game *p2second = b; 
    return strcmp(p2first->title,p2second->title);
}

Note that the above is not the complete set of necessary changes, but enough to give you an idea.

The problem is how you de-reference the pointers to print the game titles in void writeBinary(game** Arr) . The line printf("%s \n",(*Arr+i)->title); is first computing *Arr , which is the same as Arr[0] . The first iteration amounts to Arr[0]+0 , which doesn't corrupt the pointer to the first element. However, Arr[0]+1 and onward does corrupt the pointer. A correct and simpler way to iterate over the titles would be Arr[i]->title (as you somehow DID do when freeing the games) or if you want to keep the arithmetic approach, then (*(Arr+i))->title works too.

Also, just in case it's an overlook, you aren't actually writing anything to the file yet.

本文标签: C Values of a Array of Structs changing after being passed to a functionStack Overflow