Thread: Problem with copying a string into array in a struct

  1. #1
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463

    Problem with copying a string into array in a struct

    Now the problem I have is that when I copy strings into an array in a struct, it does it, but when I try to print the first element of the array in the struct it prints out everything that's in the array. I think you just need to look at the colour highlighted bits.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
    
    //3 AI's and 1 player game
    
    typedef struct player Player;
    
    struct player {
      
      char alias[25];    //player name
      char nCards[26];     //cards the player has
      Player *next;
    };
    
    int TCards;   //total cards
    
    Player *newn(void); //new node (player)
    //int cards (void);
    int dist (void);   //distributing
    
    int main (void) {
    
      dist();
    
      return 0;
    }
    
    int dist (void) {
      
      char *cards[] = {"2c","3c","4c","5c","6c","7c","8c","9c","10c","JC","QC","KC","AC",
                        "2s","3s","4s","5s","6s","7s","8s","9s","10s","JS","QS","KS","AS",
                        "2h","3h","4h","5h","6h","7h","8h","9h","10h","JH","QH","KH","AH",
                        "2d","3d","4d","5d","6d","7d","8d","9d","10d","JD","QD","KD","AD"};
      char *cards2[] = {"2c","3c","4c","5c","6c","7c","8c","9c","10c","JC","QC","KC","AC",
                        "2s","3s","4s","5s","6s","7s","8s","9s","10s","JS","QS","KS","AS",
                        "2h","3h","4h","5h","6h","7h","8h","9h","10h","JH","QH","KH","AH",
                        "2d","3d","4d","5d","6d","7d","8d","9d","10d","JD","QD","KD","AD"};
    
      /*char *p_dist[52]; //distributed cards are also copied into this array, so no recopying
      char *p_dist2[52];*/ //second array to handle doubles to prevent infinite loop from less-card distribution
    
      int i = 0; //indexer of array from distributor
      int j = 0;
      int arr_choice; //value can be 0 or 1, if 0, then take from cards[], if 1, from cards2[]
    
    
      Player *n_player;  //node for new players
      Player *user;      //human
      Player *ai_1;
      Player *ai_2;
      Player *ai_3;
    
      puts("Creating AI's and User...");
    
      n_player = newn();
      user = n_player;
      n_player = newn();
      ai_1 = n_player;
      n_player = newn();
      ai_2 = n_player;
      n_player = newn();
      ai_3 = n_player;
    
      puts("\nEnter your name");
      scanf("&#37;25s", user->alias);
      puts("\nEnter 1st AI's name");
      scanf("%25s", ai_1->alias);
      puts("Enter 2nd AI's name");
      scanf("%25s", ai_2->alias);
      puts("Enter 3rd AI's name");
      scanf("%25s", ai_3->alias);
    
    
      printf("\n\nDistributing cards to %s...\n\n", user->alias);
      srand ( time(NULL) );         //seed
      TCards = 0;  //indexer for controlling cards that go to user
    
    //////////////////*THIS IS THE DISTRIBUTION LOOP FOR THE HUMAN USER*/////////////////
      for (TCards=0; TCards < 25; TCards++){   //104 / 4 = 26 cards per user
        arr_choice = rand()/(int) (((unsigned)RAND_MAX + 1)/ 2);
        if(arr_choice == 0) {
          i = rand()/(int) (((unsigned)RAND_MAX + 1)/ 53);
          while(strcmp(cards[i], "0") == 0) {
            i = rand()/(int) (((unsigned)RAND_MAX + 1)/ 53);
          }
          strcpy(&user->nCards[j], cards[i]);
          cards[i] = "0";
          j++;
        }
        else if(arr_choice == 1) {
          i = rand()/(int) (((unsigned)RAND_MAX + 1)/ 53);
          while(strcmp(cards2[i], "0") == 0) {
            i = rand()/(int) (((unsigned)RAND_MAX + 1)/ 53);
          }
          strcpy(&user->nCards[j], cards2[i]);
          cards[i] = "0";
          j++;
        }
      }
      int b = 0;
      [B]printf("%s\n", &user->nCards);
      return 0;
    }
    
    Player *newn(void) {
      
      Player *player;
      player = (Player*)malloc(sizeof(Player));
      
      return (player);
    }
    So essentially instead of the first element printing say: "2s"

    It will print 2s3dfJK3d...etc etc.

    I think it's because of the way I've used the pointers. How do I fix this?

    Thanks

    EDIT: Don't ask me why [b] comes before printf, it's not like that in the code, the formatting doesn't work too well when I tried editing here.
    Last edited by JFonseka; 04-30-2008 at 05:44 AM.
    =========================================
    Everytime you segfault, you murder some part of the world

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Perhaps you want
    char nCards[26][3];

    And
    printf("&#37;s\n", user->nCards[0] );
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Code:
    >  char nCards[26];
    nCards need to be two dimensional, so you can store more than one card, each card being a string.
    Code:
      char nCards[26][3];

  4. #4
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463
    Why does it need to be [26][3] ? What is the [3] for ?

    The user gets only 26 cards, so isn't [26] enough for storing the cards? Where each card is indicated by a string, so 26 cards, 26 strings.
    =========================================
    Everytime you segfault, you murder some part of the world

  5. #5
    Registered User
    Join Date
    Apr 2008
    Posts
    40
    You need [26] [3] because right now you have an array of 26 chars. What you want is an array of char-arrays, which is what they are suggesting. The 3 is so that the strings are null-terminated I guess.

    Or you could just get a array of char-pointers like:

    char* nCards[26];

  6. #6
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463
    The two dimensional seems to work, but not properly, sometimes I get garbage values. I can't use char *nCards[26]

    That doesn't work.
    =========================================
    Everytime you segfault, you murder some part of the world

  7. #7
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    That doesn't work.
    You mean - you haven't found yet a correct way to make it work...
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  8. #8
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463
    Quote Originally Posted by vart View Post
    You mean - you haven't found yet a correct way to make it work...

    Not really, I tried that several times before with varying things, it didn't work, so I assumed it didn't.
    =========================================
    Everytime you segfault, you murder some part of the world

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by JFonseka View Post
    Not really, I tried that several times before with varying things, it didn't work, so I assumed it didn't.
    You assume wrong - there's certainly a way to make it work, because a 2D array can ALWAYS be replaced with an array of pointers - you obviously have to make the pointers point to some suitable memory, but it certainly can be done.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463
    Well I get segmentation faults that way, do I need to malloc before strcpy ?
    =========================================
    Everytime you segfault, you murder some part of the world

  11. #11
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463
    Did that too now, it works a lot better, except it randomnly segfaults sometimes.
    =========================================
    Everytime you segfault, you murder some part of the world

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    If you post the code, we will be much better equipped to help you.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  13. #13
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
    
    //3 AI's and 1 player game
    
    typedef struct player Player;
    
    struct player {
      
      char alias[25];    //player name
      char *nCards[26];     //cards the player has
      Player *next;
    };
    
    int TCards;   //total cards
    
    Player *newn(void); //new node (player)
    //int cards (void);
    int dist (void);   //distributing
    
    int main (void) {
    
      dist();
    
      return 0;
    }
    
    int dist (void) {
    
      char *cards[] = {"2c","3c","4c","5c","6c","7c","8c","9c","Tc","JC","QC","KC","AC",
                        "2s","3s","4s","5s","6s","7s","8s","9s","Ts","JS","QS","KS","AS",
                        "2h","3h","4h","5h","6h","7h","8h","9h","Th","JH","QH","KH","AH",
                        "2d","3d","4d","5d","6d","7d","8d","9d","Td","JD","QD","KD","AD"};
      char *cards2[] = {"2c","3c","4c","5c","6c","7c","8c","9c","Tc","JC","QC","KC","AC",
                        "2s","3s","4s","5s","6s","7s","8s","9s","Ts","JS","QS","KS","AS",
                        "2h","3h","4h","5h","6h","7h","8h","9h","Th","JH","QH","KH","AH",
                        "2d","3d","4d","5d","6d","7d","8d","9d","Td","JD","QD","KD","AD"};
    
      /*char *p_dist[52]; //distributed cards are also copied into this array, so no recopying
      char *p_dist2[52];*/ //second array to handle doubles to prevent infinite loop from less-card distribution
    
      int i = 0; //indexer of array from distributor
      int j = 0;
      int arr_choice; //value can be 0 or 1, if 0, then take from cards[], if 1, from cards2[]
    
    
      Player *n_player;  //node for new players
      Player *user;      //human
      Player *ai_1;
      Player *ai_2;
      Player *ai_3;
    
      puts("Creating AI's and User...");
      // THINGS FINALLY STOPPED GIVING SEG FAULTS, CHECK SIZE OF ALLOCATION
      n_player = newn();
      user = n_player;
      n_player = newn();
      ai_1 = n_player;
      n_player = newn();
      ai_2 = n_player;
      n_player = newn();
      ai_3 = n_player;
    
      puts("\nEnter your name");
      scanf("&#37;25s", user->alias);
      puts("\nEnter 1st AI's name");
      scanf("%25s", ai_1->alias);
      puts("Enter 2nd AI's name");
      scanf("%25s", ai_2->alias);
      puts("Enter 3rd AI's name");
      scanf("%25s", ai_3->alias);
    
    
      printf("\n\nDistributing cards to %s...\n\n", user->alias);
      srand ( time(NULL) );         //seed
      TCards = 0;  //indexer for controlling cards that go to user
    
    //////////////////*THIS IS THE DISTRIBUTION LOOP FOR THE HUMAN USER*/////////////////
      for (TCards=0; TCards < 25; TCards++){   //104 / 4 = 26 cards per user
        arr_choice = rand()/(int) (((unsigned)RAND_MAX + 1)/ 2);
        if(arr_choice == 0) {
          i = rand()/(int) (((unsigned)RAND_MAX + 1)/ 53);
          while(strcmp(cards[i], "0") == 0) {
            i = rand()/(int) (((unsigned)RAND_MAX + 1)/ 53);
          }
          user->nCards[j] = malloc(strlen(cards[i])*sizeof(char*));
          strcpy(user->nCards[j], cards[i]);
          cards[i] = "0";
          j++;
        }
        else if(arr_choice == 1) {
          i = rand()/(int) (((unsigned)RAND_MAX + 1)/ 53);
          while(strcmp(cards2[i], "0") == 0) {
            i = rand()/(int) (((unsigned)RAND_MAX + 1)/ 53);
          }
          user->nCards[j] = malloc(strlen(cards2[i])*sizeof(char*));
          strcpy(user->nCards[j], cards2[i]);
          cards[i] = "0";
          j++;
        }
      }
      int b;
      for (b=0;b<25;b++){
        printf("%s\n", user->nCards[b]);
      }  
    
    /////////////////////*THIS IS THE DISTRIBUTION LOOP FOR AI 1////////////////////
      printf("\n\nDistributing cards to %s...\n\n", ai_1->alias);
      j = 0;
      for (TCards=0; TCards < 25; TCards++){   //104 / 4 = 26 cards per user
        arr_choice = rand()/(int) (((unsigned)RAND_MAX + 1)/ 2);
        if(arr_choice == 0) {
          i = rand()/(int) (((unsigned)RAND_MAX + 1)/ 53);
          while(strcmp(cards[i], "0") == 0) {
            i = rand()/(int) (((unsigned)RAND_MAX + 1)/ 53);
          }
          ai_1->nCards[j] = malloc(strlen(cards[i])*sizeof(char*));
          strcpy(ai_1->nCards[j], cards[i]);
          cards[i] = "0";
          j++;
        }
        else if(arr_choice == 1) {
          i = rand()/(int) (((unsigned)RAND_MAX + 1)/ 53);
          while(strcmp(cards2[i], "0") == 0) {
            i = rand()/(int) (((unsigned)RAND_MAX + 1)/ 53);
          }
          ai_1->nCards[j] = malloc(strlen(cards2[i])*sizeof(char*));
          strcpy(ai_1->nCards[j], cards2[i]);
          cards[i] = "0";
          j++;
        }
      }
      for (b=0;b<25;b++){
        printf("%s\n", ai_1->nCards[b]);
      }
      return 0;
    }
    
    Player *newn(void) {
      
      Player *player;
      player = (Player*)malloc(sizeof(Player));
      
      return (player);
    }
    =========================================
    Everytime you segfault, you murder some part of the world

  14. #14
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    nCards[j], is a pointer - you should not use strcpy just
    ai_1->nCards[j] = cards2[i];

    no need to malloc as well

    also char *cards2
    should be declared as
    const char *cards2
    as all other const char pointers used
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  15. #15
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    if instead of
    cards[i] = "0";
    you will use cards[i] = NULL;
    your check
    strcmp(cards2[i], "0") == 0
    could be made shorter:
    cards[i] == NULL
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Link List math
    By t014y in forum C Programming
    Replies: 17
    Last Post: 02-20-2009, 06:55 PM
  2. Inheritance Hierarchy for a Package class
    By twickre in forum C++ Programming
    Replies: 7
    Last Post: 12-08-2007, 04:13 PM
  3. Replies: 16
    Last Post: 10-29-2006, 05:04 AM
  4. Copying a string, into a string array.
    By m.mixon in forum C Programming
    Replies: 5
    Last Post: 07-31-2006, 05:19 PM
  5. Struct *** initialization
    By Saravanan in forum C Programming
    Replies: 20
    Last Post: 10-09-2003, 12:04 PM