簡體   English   中英

C - 如何通過引用將結構指針數組傳遞給 function

[英]C - How to pass struct pointer array to a function by reference

我有這個結構:

typedef struct {
    char name[31];
    int played;
    int won;
    int lost;
    int tie;
    int points;
} Player;

這個 function 用文件中的數據填充結構數組:

int load(Player *players[], int max_players, int *player_count)
{
    static const char filename[] = "players.txt";
    FILE *file = fopen(filename, "r");

    if (file != NULL)
    {
        char line[128]; 

        players = malloc(max_players * sizeof *players);

        while (1) /* read until end of file */
        {

            players[*player_count] = malloc(sizeof(Player));

            if (*player_count < max_players && fgets(players[*player_count]->name, sizeof players[*player_count]->name, file) != NULL)
            {
                fscanf(file, "%d", &players[*player_count]->played);    // read played
                fscanf(file, "%d", &players[*player_count]->won);       // read won 
                fscanf(file, "%d", &players[*player_count]->lost);      // read lost 
                fscanf(file, "%d", &players[*player_count]->tie);       // read tie 
                fscanf(file, "%d", &players[*player_count]->points);    // read points 
                fgets(line, sizeof line, file);                         // read new line

                // increase player count
                *player_count += 1;
            }
            else
            {
                break;
            }
        }

        fclose(file);
    }
    else
    {
        return 0;
    }
    return 1;
}

現在我在通過傳遞玩家作為參考來調用它時遇到問題,這樣玩家的更新數據就會反映在調用端。

下面是我的調用代碼,我認為它有問題:

Player *players[MAX_PLAYERS] = { NULL };
int playerCount = 0;
load(players, MAX_PLAYERS, &playerCount);

當我調試代碼時,玩家數組填入 function 但當它返回時,玩家的值仍然是 null。

任何幫助,將不勝感激。

您正在覆蓋本地變量players

從不需要的功能中刪除以下行。

   players = malloc(max_players * sizeof *players);|

由於您已經在main擁有了指針數組。


您不需要Player類型的指針數組,而只需要Player類型的數組

Player *players;
load(&players, MAX_PLAYERS, &playerCount);

並具有load功能。

int load(Player **players, int max_players, int *player_count)
{
    static const char filename[] = "players.txt";
    FILE *file = fopen(filename, "r");

    if (file != NULL)
    {
        char line[128]; 

        (*players) = malloc(max_players * sizeof **players);

        while (1) /* read until end of file */
        {


            if (*player_count < max_players && fgets((*players)[*player_count].name, sizeof (*players)[*player_count].name, file) != NULL)
            {
                fscanf(file, "%d", &(*players)[*player_count].played);    // read played
                fscanf(file, "%d", &(*players)[*player_count].won);       // read won 
                fscanf(file, "%d", &(*players)[*player_count].lost);      // read lost 
                fscanf(file, "%d", &(*players)[*player_count].tie);       // read tie 
                fscanf(file, "%d", &(*players)[*player_count].points);    // read points 
                fgets(line, sizeof line, file);                         // read new line

                // increase player count
                *player_count += 1;
            }
            else
            {
                break;
            }
        }

        fclose(file);
    }
    else
    {
        return 0;
    }
    return 1;
}

C不支持通過引用傳遞變量。

我只是保持簡單。 您的函數應如下所示:

int load(Player *players, int max_players, int *player_count)
{
    static const char filename[] = "players.txt";
    FILE *file = fopen(filename, "r");

    if (file != NULL)
    {
        char line[128]; 

        while (!feof(file ) && !ferror(file )) /* read until end of file */
        {
            fscanf(file, "%d", &players[*player_count].played);    // read played
            fscanf(file, "%d", &players[*player_count].won);       // read won 
            fscanf(file, "%d", &players[*player_count].lost);      // read lost 
            fscanf(file, "%d", &players[*player_count].tie);       // read tie 
            fscanf(file, "%d", &players[*player_count].points);    // read points 
            fgets(line, sizeof line, file);                         // read new line

            // increase player count
            *player_count += 1;
        }

        fclose(file);

        return 1;
    }

    return 0;
}

主要:

int main ()
{
    Player players[MAX_PLAYERS] = { NULL };
    int playerCount = 0;
    load(players, MAX_PLAYERS, &playerCount);
    printf("");
}

以下建議的代碼:

  1. 尚未編譯,因為OP沒有發布最小,完整,可驗證的示例
  2. 正確傳遞參數
  3. 正確檢查錯誤
  4. 執行所需的功能
  5. 顯示了如何在main()初始化指針
  6. 顯示如何更新main()的指針
  7. 遵循不可恢復錯誤導致代碼將所有錯誤信息輸出到stderr的計划,然后退出
  8. 遵循成功的“典型”返回值“ 0”
  9. 確保在main()中將所有分配的內存指針傳遞給free()以避免內存泄漏

現在,建議的代碼修改如下:

regarding:

    typedef struct 
    {
        char name[31];
        int played;
        int won;
        int lost;
        int tie;
        int points;
    } Player;

this anonymous struct will be very difficult to display 
the individual fields via a debugger,
because debuggers use the 'tag' name of the struct 
to reference the individual fields


in main function: Notice only declaring a pointer initialized to NULL,
then passing the address of the pointer to the function: `load()`

    Player *players =  NULL;
    int playerCount = 0;
    load(&players, &playerCount);  

notice the double '**' on the 'players' parameter
This enables the sub function to modify the pointer field in the caller

    int load(Player **players, int *player_count)
    {
        static const char filename[] = "players.txt";

        // it is poor programming practice to name a variable the
        // same as a struct, so changed `file` to `fp`
        FILE *fp = fopen(filename, "r");
        if( !fp )
        {
            perror( "fopen to read players.txt failed" );
            exit( EXIT_FAILURE );
        }

        // implied else, fopen successful

        // increased the size of the input buffer `line[]` for safety
        char line[1024]; 

        // note: used `calloc()` so when cleaning up from error
        //       no need to check if a specific entry in the 'player'
        //       array is used.  `free()` handles a NULL parameter just fine
        *players = calloc( MAX_PLAYERS, sizeof(Player*) );
        if( !*players )
        {
            perror( "calloc for array of pointers to players failed" );
            exit( EXIT_FAILURE );
        }

        // implied else, malloc successful

        /* read until end of file  or array full*/
        while (*player_count < MAX_PLAYERS && fgets(line, sizeof line, fp)) 
        {
            (*players)[*player_count] = malloc(sizeof(Player));
            if( !(*players)[ *player_count ] )
            {
                perror( "malloc for individual player failed" );
                for( int i=0; i<MAX_PLAYERS; i++ )
                {
                    free( (*players)[i] );
                }
                free( *players ); 
                exit( EXIT_FAILURE );
            }

            // implied else, malloc successful

            if( sscanf( line, "%d %d %d %d %d", 
                players[*player_count]->played,    // read played
                players[*player_count]->won,       // read won 
                players[*player_count]->lost,      // read lost 
                players[*player_count]->tie,       // read tie 
                players[*player_count]->points) != 5 )   // read points 
            {
                fprintf( stderr, "extraction of player fields failed\n" );
                exit( EXIT_FAILURE );
            }


            // increase player count
            (*player_count) += 1;
        }

        fclose(file);

        return 0;
    }

我應該像這樣寫你的功能

int func(int ***players){
    *players=new int* [MAXSIZE];
    //use this if use c
    // *players=(int**)malloc(sizeof(int*)*MAXSIZE);
    for(int i=0;i<MAXSIZE;i++){
        *(*players+i)=new int[2];
        // *(*players+i)=(int*)malloc(sizeof(int)*2); 
        //2 is test can choose every number if your computer allow
    }
}

並且您主要的應該喜歡這個主要的:

int main(){

    int **players=nullptr;
    func(&players);
    //use follow if you must delete 
    for(int i=0;i<MAXSIZE;i++){
        delete players[i];
    }
    delete players;
    return 0;
}
typedef struct {    int played;} Player;


void load(Player* &players, int max_players, int &player_count)
{
    players = (Player*)malloc(max_players * sizeof(Player));

    for (int i = 0; i < max_players; i++)
    {
        players[i].played = i;
        player_count++;
    }
}

int main()
{
    const int MAX_PLAYERS=3;
    Player* players=  NULL ;
    int playerCount = NULL;
    load(players, MAX_PLAYERS, playerCount);

    //...
    free(players);
}
  • 結構:
typedef struct Foo {
  int x;
} Foo;

function:

void f(Foo **foo) {
  foo[0]->x = 2021;                // already allocate in main
  foo[1]    = malloc(sizeof(Foo)); // not locate yet
  foo[1]->x = 2022;
}
  • 主要的:
int main() {
  Foo **foo = malloc(100 * sizeof(Foo *)); // foo[10]

  foo[0]    = malloc(sizeof(Foo));         // must allocate before using
  foo[0]->x = 2020;                        // assing 2021 to foo[0].x must use arrow for pointer

  f(foo);
  foo[1]->x = 2024;                        // already allocate in function f();

  printf("main: value of x: %d\n", foo[0]->x);
  printf("main: value of x: %d\n", foo[1]->x);
}
  • Output:
$ gcc test.c && ./a.out
value of x: 2021
value of x: 2024

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM