#1
  1. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    26
    Rep Power
    0

    C: Weird characters on output


    As I might have explained before, I am trying to write C while learning, so I decided to take a subroutine I've built a long time ago in Perl, and translate it to C (though, making it more than just a function, so I can test via the CLI).

    Here is my code so far:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    
    void rollDice(char *pool);
    void joinRolls(int *toJoin, char *joinedRolls, int numOfRolls);
    
    int main() {
      char test[50];
      char quit[3] = "q\n";
      char blank[2] = "\n";
      
      int iQuit = 0;
      while (!iQuit) {
        printf("Enter a dice pool (or q for quit):  ");
        fgets(test,50,stdin);
        if (strcmp(test,quit) == 0) {
          iQuit = 1;
        }
        else if (strcmp(test,blank) == 0) {
          continue;
        }      
        else {
          rollDice(test);
        }
      }
        
      return 0;
    }
    
    void rollDice(char *pool) {
      char *dieNumber, *dieSides;
      char pool_copy[50];
      strcpy(pool_copy,pool);
      dieNumber = strtok(pool_copy,"d");
      dieSides = strtok(NULL,"d");
      
      int dieNumberAsInt = atoi(dieNumber);
      int dieSidesAsInt  = atoi(dieSides);
      
      int rolls[dieNumberAsInt];
      int i;
      for (i = 1; i <= dieNumberAsInt; i++) {
        srand(time(NULL)+rand());
        int roll = (rand() % dieSidesAsInt) + 1;
        rolls[i-1] = roll;
      }
    
      int j;
      for (j = 0; j < dieNumberAsInt; j++) {
        printf("roll %d is %d\n", j+1, rolls[j]);
      }
      char joinedRolls[1000];
      joinRolls(rolls,joinedRolls,dieNumberAsInt);
      printf("joinedRolls is %s\n",joinedRolls);
      
      //sprintf(pool, "dieNumber is %s\ndieSides is %s\n", dieNumber, dieSides);
    }
    
    void joinRolls (int *toJoin, char *joinedRolls, int numOfRolls) {
      int i;
      for (i=0; i < numOfRolls; i++) {
        if (strlen(joinedRolls) == 0) {
          char thisRoll[5];
          sprintf(thisRoll, "%d", toJoin[i]);
          strcat(joinedRolls,thisRoll);
        }
        else {
          char thisRoll[5];
          sprintf(thisRoll, "%d", toJoin[i]);
          strcat(joinedRolls,",");
          strcat(joinedRolls,thisRoll);
        }
      }
    }
    Things seem to be going okay, but then I noticed if I submitted dice pools three times, part of the cumulative joinedRolls gets odd characters in it, as the output below illustrates:

    Code:
    [anthony@ogre src]$ ./crpbs
    Enter a dice pool (or q for quit):  5d10
    roll 1 is 10
    roll 2 is 3
    roll 3 is 3
    roll 4 is 9
    roll 5 is 3
    joinedRolls is 10,3,3,9,3
    Enter a dice pool (or q for quit):  5d10
    roll 1 is 3
    roll 2 is 1
    roll 3 is 1
    roll 4 is 8
    roll 5 is 3
    joinedRolls is 10,3,3,9,3,3,1,1,8,3
    Enter a dice pool (or q for quit):  5d10
    roll 1 is 1
    roll 2 is 3
    roll 3 is 10
    roll 4 is 5
    roll 5 is 1
    joinedRolls is 10,3,3,9,3,3,1,1B BZ@,1,3,10,5,1
    Enter a dice pool (or q for quit):  
    [anthony@ogre src]$
    I can't figure out what's wrong, but I'd take a guess it has to do something with me screwing up pointers somewhere, because I know they can point to garbage if not used properly.

    Pointers are the one thing I still really don't have a grasp on when it comes to C. I'm reading the K&R book, but its all a bit esoteric. Any pointers (no pun intended) to good online tutorials would be appreciated.
    Last edited by notsoevil; June 20th, 2003 at 03:28 PM.
  2. #2
  3. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    26
    Rep Power
    0
    I've gone over this and over this and I can't figure out where those characters are coming from.

    Can anyone else see anything? Does the same thing happen if you compile it (if anyone has, that is)?
  4. #3
  5. /(bb|[^b]{2})/

    Join Date
    Nov 2001
    Location
    Somewhere in the great unknown
    Posts
    5,163
    Rep Power
    792
    I compiled your application and did not get the same error, but I will say that this is a mixture of C and C++. Your program would not compile with gcc, it had to be done with g++ instead. Mainly because of declaring variables later on in the body of the function instead of at the top of it.
  6. #4
  7. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    26
    Rep Power
    0
    I didn't know I mixed C and C++ there, and Anjuta is hiding most of the compiling from me so I didn't notice whether it was using gcc or g++. I'll try to correct it.

    I am curious though: did you run the same test data and the same number of times?
  8. #5
  9. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    26
    Rep Power
    0
    Also, I just tested and was able to compile this with just gcc just fine:

    Code:
    gcc -o crpbs main.c
    Also, I just noted that after compiling with that command (instead of letting Anjuta do the build), the garbage characters do not print out until the 5th dice pool, instead of the third like above. Can you try to run yours again and go out as far as 5 dice pools?
  10. #6
  11. /(bb|[^b]{2})/

    Join Date
    Nov 2001
    Location
    Somewhere in the great unknown
    Posts
    5,163
    Rep Power
    792
    Code:
    Enter a dice pool (or q for quit):  5d10
    roll 1 is 7
    roll 2 is 6
    roll 3 is 8
    roll 4 is 7
    roll 5 is 9
    joinedRolls is x,7,6,8,7,9
    Enter a dice pool (or q for quit):  5d10
    roll 1 is 8
    roll 2 is 7
    roll 3 is 9
    roll 4 is 3
    roll 5 is 9
    joinedRolls is x,7,6,8,7,9,8,7,9,3,9
    Enter a dice pool (or q for quit):  5d10
    roll 1 is 3
    roll 2 is 9
    roll 3 is 1
    roll 4 is 1
    roll 5 is 10
    joinedRolls is x,7,6,8,7,9,8,7,9,3,9,3,9,1,1,10
    Enter a dice pool (or q for quit):  5d10
    roll 1 is 9
    roll 2 is 10
    roll 3 is 6
    roll 4 is 10
    roll 5 is 2
    joinedRolls is x,7,6,8,7,9,8,7,9,3,9,3,9,1,1,10,9,10,6,10,2
    Enter a dice pool (or q for quit):  5d10
    roll 1 is 4
    roll 2 is 2
    roll 3 is 7
    roll 4 is 7
    roll 5 is 1
    joinedRolls is x,7,6,8,7,9,8,7,9,3,9,3,9,1,1,10,9,10,6,10,2,4,2,7,7,1
    Enter a dice pool (or q for quit):  5d10
    roll 1 is 4
    roll 2 is 8
    roll 3 is 7
    roll 4 is 1
    roll 5 is 6
    joinedRolls is x,7,6,8,7,9,8,7,9,3,9,3,9,1,1,10,9,10,6,10,2,4,2,7,7,1,4,8,7,1,6
    I got a x for the first one every time

    I don't know why yours compiled with gcc and mine would not.
  12. #7
  13. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    26
    Rep Power
    0
    With the help of someone on another site, I was pointed to my joinedRolls pointer and the limit of its scope. Although I intended that pointer to persist, it continually went out of scope at the end of the RollDice method, since that is where I was mistakenly declaring it.

    So, I've made joinedRolls static (1 solution of several he pointed out) and everything is working fine.

    Thanks for your help too, Onslaught. I'm sure I'll be around here a lot more.

    And if you're curious, here is the debugged method:

    Code:
    void rollDice(char *pool) {
      char *dieNumber, *dieSides;
      char pool_copy[50];
      strcpy(pool_copy,pool);
      dieNumber = strtok(pool_copy,"d");
      dieSides = strtok(NULL,"d");
      
      int dieNumberAsInt = atoi(dieNumber);
      int dieSidesAsInt  = atoi(dieSides);
      
      int rolls[dieNumberAsInt];
      int i;
      for (i = 1; i <= dieNumberAsInt; i++) {
        srand(time(NULL)+rand());
        int roll = (rand() % dieSidesAsInt) + 1;
        rolls[i-1] = roll;
      }
    
      int j;
      for (j = 0; j < dieNumberAsInt; j++) {
        printf("roll %d is %d\n", j+1, rolls[j]);
      }
      static char joinedRolls[1000];
      joinRolls(rolls,joinedRolls,dieNumberAsInt);
      printf("joinedRolls is %s\n",joinedRolls);
      
    }
  14. #8
  15. /(bb|[^b]{2})/

    Join Date
    Nov 2001
    Location
    Somewhere in the great unknown
    Posts
    5,163
    Rep Power
    792
    I had started working on a sample workup of this script done that would be able to hold a more dynamic amount, if/when I get it done I will post it here for you.
  16. #9
  17. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    26
    Rep Power
    0
    That would be much appreciated and helpful, thanks. I'd like to compare the two and learn how you approach the task.

    This was just the first leg of the program, and now I am going to be adding in suggested checks (syntax, maximum die, maximum sides, etc) and additional die options.

    Its not really a useful program and is really just a hack to turn a Perl subroutine into a C program with a CLI. But its turning out to be a practical application to what I am learning about, which is definitely the best way to approach a new language, I feel.

IMN logo majestic logo threadwatch logo seochat tools logo