4

I am a beginner at C, I have a program where I'm trying to set values of a structure inside a function, but I'm unsure of how to pass the structure to the function and have it modify it's original values.

I have a simple structure that looks like this:

struct player {

    char name[40];
    int acceleration;

};

And just to play around I do this:

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

I want to move this functionality to a function so I can do something like this:

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

So far my function looks like this:

void createPlayer(struct player currentPlayer, char name[], int acceleration) {

     strcpy(currentPlayer.name, name);

     currentPlayer.acceleration = acceleration;

}

But when I print this:

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

I see this:

The speed of  is 0

What am I doing wrong here? Please suggest any changes to my code / style that goes against the usual convention.

Thank you so much!

4
  • While the answers being given are correct, your post indicates a lack of understanding when it comes to C, specifically pointers which you must understand to use the language. I would suggest a good Intro To C book, or to be more focused googling a tutorial on pointers in C. Commented Oct 29, 2011 at 20:41
  • Thanks Brian, I've been reading what I can find online and in Youtube, but sometimes I think I learn best when I just jump in and try it. Commented Oct 29, 2011 at 20:43
  • Fair enough - just wanted to point you in the right direction. Pointers are the hardest thing to grok for a new programmer, but they're essential to learn. Commented Oct 29, 2011 at 20:44
  • I have found that Pointers are difficult to grasp for me, I've been a PHP guy mostly, dabbled in Java a little bit, but not very much. I've found it frustrating that I have to pass something that points to an object instead of passing the object itself. But from what I have studied, I'm really enjoying C and I think I'll benefit from learning these concepts Commented Oct 29, 2011 at 20:47

2 Answers 2

3

You'll need to pass the struct by pointer:

Change the function to this:

void createPlayer(struct player *currentPlayer, char name[], int acceleration) {

     strcpy(currentPlayer->name, name);

     currentPlayer->acceleration = acceleration;

}

And call it like this:

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

EDIT:

In your original code, when you pass the struct into the function. It is done "by value". This means that a copy is made into the function. So what changes you make to it inside the function will be on the local copy and will not be applied to the original copy.

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you! So you use an arrow to access the structures attribute, is this preferred over dot notation? Is one newer than the other? Thanks again :)
They are different. You use ., when it's a normal struct. You use -> when it's a pointer.
Hmm so I seem to get an error with the line that starts with strcpy: 20 C:\Us....r.c request for member `name' in something not a structure or union
Awesome, thanks for the edit, this makes a lot of sense the way you explained it
x->y is simply syntactic sugar for (*x).y. (Some languages use . for both.)
1

You may also want to consider that "createPlayer" function feels as if it's creating a new player for use by the application. It is customary and very powerful to allocate memory for the structure only when you require to use it in the code, and discard the memory when you are done. Also, doing so will allow you to create as many "players" as you want when you are running the code and use them as you like.

Below is a post to show how it may be done using dynamic memory allocation (allocating memory when the program is executed). let's create a header file (.h) that will house our definitions

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 */

let's create a player.c that will contain the implementation of the functions defined in 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 */

Define the functions to manage the structure allocation

/* 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;
} 

Now elsewhere in your code you can use the above function like this:

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);
      }
}

compile the program with both c files using your c compiler (add them to your project if you are using a C IDE). build the project... .

In case you are using command line then:

cc -o player_test player.c main.c

should do the trick

NOTE

Now i wrote this all out without without using a c compiler so i may have some syntax errors ... please get the feeling of C from it, rather than using it literally :) in case there are silly mistakes.

1 Comment

Thank you very much! This is really great, a huge help

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.