在C语言中修改函数内的变量

4

我是一名C语言初学者,我有一个程序,在其中我想在函数内设置结构的值,但是我不确定如何将结构传递到函数中并修改其原始值。

我有一个简单的结构体如下所示:

struct player {

    char name[40];
    int acceleration;

};

为了玩一下,我做了这个:

struct player terry;
terry.acceleration = 20;
strcpy(terry.name, "John Terry");

我希望将这项功能移动到一个函数中,以便我可以像这样操作:

createPlayer(terry, 20, "John Terry");

到目前为止,我的函数看起来像这样:
void createPlayer(struct player currentPlayer, char name[], int acceleration) {

     strcpy(currentPlayer.name, name);

     currentPlayer.acceleration = acceleration;

}

但是当我打印这个时:

printf("The speed of %s is %d \n\n", terry.name, terry.acceleration);

我看到这个:
The speed of  is 0

我在这里做错了什么?请建议对我的代码/样式进行任何更改,以符合通常的约定。

非常感谢你!


虽然给出的答案是正确的,但您的帖子表明您在C语言方面存在理解不足,特别是指针,这是您必须了解才能使用该语言。我建议阅读一本好的C语言入门书籍,或者更加专注地搜索有关C语言指针的教程。 - Brian Roach
谢谢Brian,我一直在网上和Youtube上阅读相关内容,但有时候我觉得当我直接尝试时学习效果最好。 - Doug Molineux
好的,我只是想指出正确的方向。对于新手程序员来说,指针可能是最难理解的东西,但是学习它们是必不可少的。 - Brian Roach
我发现指针对我来说很难理解,我主要是 PHP 开发人员,稍微涉猎了一下 Java,但不是很深入。我发现很令人沮丧的是,我必须传递指向对象的指针而不是对象本身。但从我所学的知识来看,我非常喜欢 C 语言,并且我认为学习这些概念会对我有所裨益。 - Doug Molineux
2个回答

3
您需要通过指针来传递结构体:
将函数更改为以下内容:
void createPlayer(struct player *currentPlayer, char name[], int acceleration) {

     strcpy(currentPlayer->name, name);

     currentPlayer->acceleration = acceleration;

}

并且像这样调用:

createPlayer(&terry, 20, "John Terry");

编辑:

在您原始的代码中,当您将结构体传递到函数中时,是通过“按值”进行的。这意味着一个副本被传递给函数。因此,在函数内部对其所做的更改将在本地副本上进行,并且不会应用于原始副本。


谢谢!所以你使用箭头来访问结构属性,这比点符号更受欢迎吗?它们中有一个比另一个更新吗?再次感谢 :) - Doug Molineux
1
它们是不同的。当它是一个普通结构体时,你使用“.”。当它是一个指针时,你使用“->”。 - Mysticial
嗯,看起来我在以strcpy开头的那一行遇到了一个错误:20 C:\Us....r.c request for member `name' in something not a structure or union。 - Doug Molineux
太棒了,感谢您的编辑,您解释得很清楚,这让我理解了很多。 - Doug Molineux
2
x->y 只是 (*x).y 的语法糖。 (有些语言都使用 . - Keith Thompson

1

你可能还想考虑一下,“createPlayer”函数感觉就像是在为应用程序创建一个新的玩家。在代码中,根据需要分配结构体的内存,并在使用完后释放该内存是惯例并非常强大的做法。这样做还可以让你在运行代码时创建任意多个“玩家”,并按照自己的喜好使用它们。

下面是一个示例,展示了如何使用动态内存分配(在程序执行时分配内存)。

让我们创建一个头文件(.h),用来存放我们的定义。

player.h:

/* this player.h header file is used by other parts of our program to access
 * the player functionality definitions and interface 
 */

/* the #ifndef / #define below protects against inadvertent syntax errors
 * that may occur by double inclusion of the same file.
 */

#ifndef _PLAYER_H 
#define _PLAYER_H

struct player {

    char name[40];
    int acceleration;

};

extern struct player * create_player(const char *name, int acceleration);
void delete_player(struct player *p);
const char * get_player_name(struct player *p);
void set_player_name(struct player *p, const char *name);
int get_player_accel(struct player *p);
void set_player_accel(struct player *p, int accel);

/* you can add other functions here and then define their implementation in player.c
   shown below */

#endif /* _PLAYER_H */

让我们创建一个 player.c 文件,其中包含在 player.h 中定义的函数的实现。

player.c:

/* include memory management functions */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "player.h" /* we created this above */


/* Define the structure */

定义用于管理结构分配的函数。
/* create_player function allocates memory for a new player structure 
 *  and returns the pointer to it upon succcess. It returns NULL on failure 
 */
struct player * create_player(const char *name, int acceleration) {
       struct player *new_player = malloc(sizeof(struct player));
       /* malloc allocates memory for the sizeof the structure and returns
          the pointer to it */
       if ( !new_player ) {
             /* typically we don't put error messages in production code
              * it is handled elsewhere but verbosity 
              * is okay for learning, so we add an error message */
             fprintf(stderr, "unable to allocate memory for a new player\n");
             return NULL;
       }
} 

/* delete_player deallocates memory that was allocated in create_player
 * only pass it the pointers that were created by create_player structure
 */

void delete_player(struct player *p) {
     if (p)
        free(p); 
} 

/* let's do some house keeping functions */


const char * get_player_name(struct player *p) {
      if ( p ) 
           return p->name;
      else 
           return NULL;
}

void set_player_name(struct player *p, const char *name) {
     if ( p ) {
           strncpy(p->name, name, sizeof(p->name)); /* only 40 characters */
     }
}

int get_player_accel(struct player *p) {
    return p->acceleration;
} 

void set_player_accel(struct player *p, int accel) {
    if ( p ) 
         p->acceleration = accel;
} 

现在在您的代码的其他地方,您可以像这样使用上述函数:

main.c:

#include <stdio.h>
#include "player.h"

int main() {
      struct player *player = create_player("john", 30);

      if ( player ) { 
               printf("%s's acceleration is %d\n", player->name, player->acceleration);
      }
}

使用您的C编译器编译两个C文件的程序(如果您正在使用C IDE,则将它们添加到项目中)。构建项目...

如果您正在使用命令行,则可以使用以下命令:

cc -o player_test player.c main.c

就可以了

注意事项

我没有使用C编译器就把这些都写出来了,所以可能会有一些语法错误...请从中感受C,而不是照字面意思使用它 :) 以防有愚蠢的错误。


非常感谢!这真的很棒,帮了我大忙。 - Doug Molineux

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接