Thread: Another returning of C String issue. Don't kill me please!

  1. #1
    Registered User
    Join Date
    Nov 2005
    Posts
    41

    Another returning of C String issue. Don't kill me please!

    Hi Guys,

    Sorry. I know this topic has been discussed millions of times. But I'm totally loss at the way C handles strings.

    I do know in C, strings are arrays of chars. The last char must be a '\0' to indicate end of string. And erm...i guess that's all i know.

    I've done a search but it's getting more confusing. Can anyone give me some sound advise, please?

    I've a function "DecimaltoBinary" which takes in a integer parameter. You pass in a decimal, it will convert and return a value. It is supposed to return a string type which contains the binary representation of the decimal.

    But in main(), how am I supposed to implement that?

    I know it has something to do with pointers, but I'm like swimming in a vast ocean without any float Can pointers or malloc() solev the problem?

    Code:
    #include <stdio.h>
    char DecimaltoBinary(int i);
    int main(int argc, char *argv[])
    {
     char s;
     int intDecimals=27;
     s= DecimaltoBinary(intDecimals);
     return 0;
    }
    
    char DecimaltoBinary(int i)
    {
     int NumOfChars=0,intTemp=1;
     char ChrArray[128];
     char TempArray[128];
     while(i!=1)
     {
      ChrArray[NumOfChars]=i%2;
      NumOfChars++;  
      i/=2; 
     }
     ChrArray[NumOfChars++]=1;
     TempArray[0]=1;
     while(intTemp<NumOfChars)
      TempArray[intTemp++]=ChrArray[NumOfChars-(intTemp+1)];
     return TempArray;
    }

  2. #2
    Registered User
    Join Date
    Aug 2005
    Posts
    1,267
    first, the function needs to return a pointer to a character array. That means using the '*' "operator?".
    Code:
    char * DecimaltoBinary(int i)
    {
    
    }
    The function cannot just return a pointer to TempArray because TempArray was declared as an auto variable which gets tossed into the bit bucket just as soon as the function returns to its caller. So there's a couple ways to overcome that problem.
    1. make the variable static so that it does not go out of scope.
    Code:
    char * DecimaltoBinary(int i)
    {
       static char TempArray[128];
    
    
      ...
      return TempArray;
    
    }
    Another way, probably better, is for the calling function to pass in a pointer to the caracter array.

    Code:
    char *DecimaltoBinary(static char* TempArray, int i)
    {
    
    
      ...
      return TempArray;
    
    }

  3. #3
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    I'm pretty sure you can't return an array from a function with a standard return line.

    /\
    ||
    I like these answers.
    ||
    \/
    Last edited by SlyMaelstrom; 11-17-2005 at 10:55 AM.
    Sent from my iPad®

  4. #4
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    You have a few options. The tricky part is variable scope. If you declare an array in a function it only exists until the function returns. So this is the wrong way:
    Code:
    char *func(void)
    {
      char str[] = "I'm a string";
    
      return str;  // WRONG! str is only local to this function and will be invalid in calling function
    }
    
    int main(void)
    {
      printf("%s\n", func());
      return 0;
    }
    There's a few ways around this though. You can:
    - Declare str as static (e.g. static char str[] = "I'm a string";) This makes str last as long as the program lives instead of until the function returns.
    - Pass a buffer to the function. If the called function stores the string into a buffer you pass to it then you're guaranteed that the buffer will last at least until the calling (not the called) function returns.
    - Use dynamic memory allocation. You can do something like char *func(void) { char *str = malloc(20); strcpy(str, "I'm a string"); return str; }. You just have to make sure the calling function free()s the malloc()d memory when it's done with it.
    If you understand what you're doing, you're not learning anything.

  5. #5
    Registered User
    Join Date
    Nov 2005
    Posts
    41
    Oh ok..Thanks..

    I have modified ...erm..based on what i've understand so far..

    Code:
    #include <stdio.h>
    char *DecimaltoBinary(int i);
    int main(int argc, char *argv[])
    {
     int intDecimals=11;
     char *s;
     s=DecimaltoBinary(intDecimals);
     printf("%s",s);
     return 0;
    }
    char *DecimaltoBinary(int i)
    {
     int NumOfChars=0,intTemp=1;
     char ChrArray[128];
     static char TempArray[128];
     while(i!=1)
     {
      ChrArray[NumOfChars]=i%2;
      NumOfChars++;  
      i/=2; 
     }
     ChrArray[NumOfChars++]=1;  
     TempArray[0]=1;
     while(intTemp<NumOfChars)
      TempArray[intTemp++]=ChrArray[NumOfChars-(intTemp+1)];
     TempArray[intTemp++] = '\0'; 
     
     return TempArray;
    }
    but printing out "s" gives me garbage results instead of the desired results.

    Is my logic wrong (i tried to loop out the results in the function, it displayed correctly) ? Or i've screwed up concepts of returning
    strings in C?

    Pls advise. Thanks

  6. #6
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    What is the program supposed to do?
    Code:
     TempArray[0]=1;
    That doesn't put the character '1' at the beginning of TempArray. It puts ASCII value 1 instead which is not a printable character. Are you sure you don't mean to do TempArray[0]='1'; instead?
    If you understand what you're doing, you're not learning anything.

  7. #7
    Registered User
    Join Date
    Nov 2005
    Posts
    41
    Quote Originally Posted by itsme86
    What is the program supposed to do?
    Code:
     TempArray[0]=1;
    That doesn't put the character '1' at the beginning of TempArray. It puts ASCII value 1 instead which is not a printable character. Are you sure you don't mean to do TempArray[0]='1'; instead?
    Oh.. I wanted to indicate it as integer.... Erm...That means all my other lines are wrong too?

    ChrArray[NumOfChars]=i%2;

    since i%2 returns an int too....

    Then I need to cast i%2 too?

  8. #8
    Registered User
    Join Date
    Nov 2005
    Posts
    41
    I feel like killing myself.

    I've finally finished the piece of crap.
    I feeling so crappy right now. How I wish C is my very first language.

    I intially wanted to return a STRING (or in C context, an array of chars?); Then I realised: Why not return an array of int instead?

    After some fooling around, I realised that returning both ways are more or less dealing with returning of arrays. Seems that C style of returning arrays are different from others ( C is just too complex for my simplistic mind )

    The code below have some workaround of some prblems that I've not yet solved:

    1. How do you get the length of array? As in, how many items are inside an array?
    I've declared an array of size 128. But let's say I've filled up 10 elements out of the 128;
    How do we know that 10 elements are used up? sizeof() is not the correct way as sizeof returns the size of the object instead. In this case, a 4 byte int???

    2. Why do I need to use the EOF? It's because I do not know how many elements in the array will be used up. I've declared size of array to be 128. But it may only use up the first 4 or 8. Hence I've used EOF to mark the last element. Im surprised I've used it. I believe this is not the correct way to use EOF. I wanted to use '\0'. But it seems that '\0' is equivalent to 0 too?? (I thought \0 is a binary representation of null or something?)

    Let's say a binary representation of 27 is 11011. If I used '\0' to mark the last element of array, the result will only print out

    "Binary of 27 is 11"


    Sorry for my rantings. Im really ........ed with myself.

    Er....can anyone give advise on how to improve the code?

    Code:
    #include <stdio.h>
    int *DecimaltoBinary(int i);
    int main(int argc, char *argv[])
    {
     int intDecimals=1972;
     int xx=0;
     int *s;
     printf("Binary of %i is: ",intDecimals);
     s=DecimaltoBinary(intDecimals);
     for(;s[xx]!=EOF;xx++)printf("%i",s[xx]);
     return 0;
    }
    int *DecimaltoBinary(int i)
    {
     int NumOfChars=0,intTemp=1;
     int ChrArray[128];
     static int TempArray[128];
     while(i!=1)
     {
      ChrArray[NumOfChars++]=i%2; 
      i/=2; 
     }
     ChrArray[NumOfChars++]=1;  
     TempArray[0]=1;
     while(intTemp<NumOfChars)
      TempArray[intTemp++]=ChrArray[NumOfChars-(intTemp+1)];
     TempArray[intTemp]=EOF; 
     return TempArray;
    }
    Last edited by stevong; 11-18-2005 at 07:27 AM.

  9. #9
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    1. How do you get the length of array? As in, how many items are inside an array?
    I've declared an array of size 128. But let's say I've filled up 10 elements out of the 128;
    How do we know that 10 elements are used up? sizeof() is not the correct way as sizeof returns the size of the object instead. In this case, a 4 byte int???

    2. Why do I need to use the EOF? It's because I do not know how many elements in the array will be used up. I've declared size of array to be 128. But it may only use up the first 4 or 8. Hence I've used EOF to mark the last element. Im surprised I've used it. I believe this is not the correct way to use EOF. I wanted to use '\0'. But it seems that '\0' is equivalent to 0 too?? (I thought \0 is a binary representation of null or something?)
    1. You can keep track of what the last element you filled was and use that as your size, or you could initialize the array with non-valid integer (negetive perhaps?) then you could do a search through the array until you get to that non-valid integer, or you could perhaps consider using a more complex data structure.

    2. If you can keep track of your last array element, this should be no problem.
    Sent from my iPad®

  10. #10
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Instead of actually using the integers 0 and 1 in the array, try using the ASCII characters '0' and '1'. You can do this by adding '0' to the value you're setting in the array (e.g. ChrArray[NumOfChars++]=(i%2)+'0'; )
    If you understand what you're doing, you're not learning anything.

  11. #11
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    As an aside, I find bit-shifting a cleaner method for converting integers to binary this way:
    Code:
    itsme@itsme:~/C$ cat inttobin.c
    #include <stdio.h>
    
    char *inttobin(int num)
    {
      // Make sure binrep can hold all the binary digits plus 1 for the '\0'
      static char binrep[sizeof(int) * 8 + 1];
      int bit;
      int index;
    
      // Loop through num from MSB to LSB
      for(index = 0, bit = sizeof(int) * 8 - 1;bit >= 0;--bit)
        binrep[index++] = ((num >> bit) & 1) + '0';
    
      // Be sure to terminate the string
      binrep[index] = '\0';
    
      // Skip all the leading '0's
      for(index = 0;binrep[index] == '0';++index)
        ;
    
      // Make sure we have at least one digit to show
      if(!binrep[index])
        index--;
    
      return binrep + index;
    }
    
    int main(void)
    {
      printf("%s\n", inttobin(1234567));
    
      return 0;
    }
    Code:
    itsme@itsme:~/C$ ./inttobin
    100101101011010000111
    Last edited by itsme86; 11-18-2005 at 10:47 AM.
    If you understand what you're doing, you're not learning anything.

  12. #12
    Registered User
    Join Date
    Nov 2005
    Posts
    41
    Quote Originally Posted by itsme86
    Instead of actually using the integers 0 and 1 in the array, try using the ASCII characters '0' and '1'. You can do this by adding '0' to the value you're setting in the array (e.g. ChrArray[NumOfChars++]=(i%2)+'0'; )
    so
    Code:
    ChrArray[NumOfChars++]=(i%2)+'0'
    effectively cast an int to char datatye?
    how about
    Code:
    int x=2;
    (char)x;
    because if you print out x, x outputs junk

    Thanks

  13. #13
    Registered User
    Join Date
    Nov 2005
    Posts
    41
    Quote Originally Posted by itsme86
    As an aside, I find bit-shifting a cleaner method for converting integers to binary this way:
    Code:
    itsme@itsme:~/C$ cat inttobin.c
    #include <stdio.h>
    
    char *inttobin(int num)
    {
      // Make sure binrep can hold all the binary digits plus 1 for the '\0'
      static char binrep[sizeof(int) * 8 + 1];
      int bit;
      int index;
    
      // Loop through num from MSB to LSB
      for(index = 0, bit = sizeof(int) * 8 - 1;bit >= 0;--bit)
        binrep[index++] = ((num >> bit) & 1) + '0';
    
      // Be sure to terminate the string
      binrep[index] = '\0';
    
      // Skip all the leading '0's
      for(index = 0;binrep[index] == '0';++index)
        ;
    
      // Make sure we have at least one digit to show
      if(!binrep[index])
        index--;
    
      return binrep + index;
    }
    
    int main(void)
    {
      printf("%s\n", inttobin(1234567));
    
      return 0;
    }
    Code:
    itsme@itsme:~/C$ ./inttobin
    100101101011010000111

    Wow. Bit Shifting is something I need to read up more on.
    Hmm..why use
    Code:
    sizeof(int) * 8
    ??

    Why cant you directly put 32? Isnt int a standard 4 bytes?

    Pls advise.Thanks

  14. #14
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Why cant you directly put 32? Isnt int a standard 4 bytes?
    The C standard doesn't say that an int is any specific size. In fact, the standard doesn't say that many of the datatypes are any specific size. Instead it defines most of the datatype sizes in relation to other datatype sizes. Like an int must be at least as big as a short, but may be bigger. And a long must be at least as big as an int, but may be bigger.

    Code:
    int x=2;
    (char)x;
    Of course it prints junk. You're telling it to print ASCII value 2 which is a nonprintable character. Try printing x + '0' instead. You can use the same trick with the alphabet. Try printing 4 + 'a' and you'll get d.

    The char datatype is nothing more than a 1-byte integer. When you do something like char ch = 'f' you're actually just storing the ASCII value of 'f' in ch. You can even print it out as a number if you want. Try printf("%d\n", 'f');.

    To complicate things, not all computers use the ASCII character set. Those little math tricks depend on the underlying character set being laid out in a way in which they work.
    Last edited by itsme86; 11-19-2005 at 02:05 PM.
    If you understand what you're doing, you're not learning anything.

  15. #15
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534
    Quote Originally Posted by stevong
    Wow. Bit Shifting is something I need to read up more on.
    Hmm..why use
    Code:
    sizeof(int) * 8
    ??

    Why cant you directly put 32? Isnt int a standard 4 bytes?

    Pls advise.Thanks
    You may want to consider using the macro CHAR_BIT in <limits.h> instead of the magic number 8:

    Code:
    #include <limits.h>
    
    sizeof(int) * CHAR_BIT....

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C++ ini file reader problems
    By guitarist809 in forum C++ Programming
    Replies: 7
    Last Post: 09-04-2008, 06:02 AM
  2. Replies: 4
    Last Post: 03-03-2006, 02:11 AM
  3. Calculator + LinkedList
    By maro009 in forum C++ Programming
    Replies: 20
    Last Post: 05-17-2005, 12:56 PM
  4. string issue
    By gregulator in forum C++ Programming
    Replies: 4
    Last Post: 03-21-2005, 07:49 PM
  5. Linked List Help
    By CJ7Mudrover in forum C Programming
    Replies: 9
    Last Post: 03-10-2004, 10:33 PM