Thread: Converting an int array to a character array nicely printed

  1. #1
    Registered User
    Join Date
    Nov 2008
    Posts
    4

    Converting an int array to a character array nicely printed

    Hello everyone,

    I am trying to build a function that takes a struct that contains an array of integers, which I know the length (size) of, and convert it to a nicely formatted character array (string) output in C.

    I am trying to do a nicely printed output in my function like this:
    []
    [3]
    [3, 4]
    [3, 4, 6]

    My code is:
    Code:
    typedef struct {
    	/* A pointer to a dynamically allocated array to hold the elements. */
    	int *element;
    	/* The length of the array. */
    	int length;
    	/* The capacity as a list. */
    	int capacity;
    } IntArray;
    
    char *toString(IntArray *ar) {
        /*
         * Returns a string to be printed, from an IntArray.
         */
        char *str;
    
        // Check for empty array
        if (ar->length == 0) {
              str = (char *) malloc(3 * sizeof(char));
              if (str == NULL) {
                    printf("*** Memory request failed. ***\n");
                    exit(EXIT_FAILURE);
              }
    
              str[0] = '[';
              str[1] = ']';
              str[2] = '\0';
        }
    
        // Otherwise:
        else {
        	int i = 0, j = 0;
        	int size = ar->length * 3 + 3;
    	str = (char *) malloc(size * sizeof(char));
    
    	str[j] = '[';
    	while (i != ar->length) {
    		str[++j] = '0' + ar->element[i++];
    		str[++j] = ',';
    		str[++j] = ' ';
    	}
    	str[--j] = ']';
    	str[++j] = '\0';
        }
    
        return str;
    }
    I have a problem though because sometimes the int array has number bigger than 0-9. I tried using itoa() but it does not seem to solve my problem because it adds a null terminated character at the end. I also have problem finding how much memory I can to allocate as I don't know how big the integers will be.

    It works great for an int array of 0's, but when I have different numbers this function does not work anymore.

    I will really appreciate your help as I have been stuck on this function for quite a bit.
    Thank you very much.

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Jary316 View Post
    I tried using itoa() but it does not seem to solve my problem because it adds a null terminated character at the end.
    Removing the null terminator at the end of a string is easy to do.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Nov 2008
    Posts
    4
    Thank you very much.

    Oh right, should I use itoa() and then strlen(str) to start at the null terminated charactetr?
    I think I got this working now:
    Code:
        else {
        	int i = 0, j = 0;
        	int size = ar->length * 3 + 3;
    		str = (char *) malloc(size * sizeof(char));
    
    		str[j] = '[';
    		while (i != ar->length) {
    			itoa(ar->element[i++], &str[++j], 10);
    			j = strlen(str);
    			str[j] = ',';
    			str[++j] = ' ';
    		}
    		str[--j] = ']';
    		str[++j] = '\0';
        }
    But I still have the problem of not knowing the right size for malloc(). I know the size of the integer array (how many elements) but each integer could be 1 element long or more. It could be 1, 3 or 6 for example. I do not know what size to allocate to malloc().

    Anyway I can find it so I don't use too many memory please? I could use realloc too, set a small initial malloc() but I do not know how to find out when the array is full (while itoa() is called or before it gets called). Thank you.
    Last edited by Jary316; 11-12-2008 at 09:53 AM.

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    No int can have more then 10 digits plus maybe a negative sign. So that's your bound; that's what you should probably malloc.

  5. #5
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Code:
    str = (char *) malloc(size * sizeof(char));
    You shouldn't cast malloc in C, plus I believe the size of a character is guaranteed to be 1 so that whole thing should just boil down to:
    Code:
    str = malloc(size);
    ... likewise for the other malloc.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  6. #6
    Registered User
    Join Date
    Nov 2008
    Posts
    4
    tabstop: That is correct but there is some extra space left though.

    I was thinking about something like that:
    Code:
        	// How many elements are in the array
        	int size = 3;
        	// Defines a string: size is 3 because we have 2 brackets and a null terminated character
    	str = (char *) malloc(size * sizeof(char));
    
    	str[j] = '[';
    	while (i != ar->length) {
    
    		// Define how many characters are in the next integer
    		int temp = ar->element[i];
    		if (temp < 0)
    			temp -= temp;
    		int count = 0;
    		while ((temp = temp / 10) > 0)
    			++count;
    
    		// The new size is the old size and the new element
    		size += count;
    		// Reallocate the array to be able to hold the next element
    		str = (char *) realloc(str, size * sizeof(char));
    
    		itoa(ar->element[i++], &str[++j], 10);
    		j = strlen(str);
    		str[j] = ',';
    		str[++j] = ' ';
    	}
    Basically I define that the array is 3 characters long: [] and the null character.
    Then I assign the next element to temp, check the number of characters by dividing it by 10 until it reaches 0, then calls realloc for the old value + the new value to hold the new element.

    Unfortunately, something is going wrong and it crashes.

    hk_mp5kpdw: You are right for the part that sizeof(char) is one but it's not a big deal. It is better, in my opinion, to typecast malloc because it returns a void pointer. Some compilers do not do the automatic conversion. But that is not a big problem

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Jary316
    It is better, in my opinion, to typecast malloc because it returns a void pointer. Some compilers do not do the automatic conversion.
    All standard conforming C compilers perform that conversion.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by laserlight View Post
    All standard conforming C compilers perform that conversion.
    And hopefully, VERY few people are still using compilers that are significantly over 15 years old. The ANSI standard came out in 1989, but compilers supported the "upcoming" ANSI standard before then - I worked with ANSI-like compilers in 1986-7, IIRC. Older compilers than that would be UNLIKELY to still be in use.

    --
    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.

  9. #9
    Registered User
    Join Date
    Nov 2008
    Posts
    4
    I think I did successfully solve it:
    Code:
        else {
        	int i = 0, j = 0;
    
        	// How many elements are in the array
        	int size = 3;
        	// Defines a string: size is 3 because we have 2 brackets and a null terminated character
    		str = malloc(size);
    
    		str[j] = '[';
    		while (i != ar->length) {
    
    			// Define how many characters are in the next integer
    			int temp = ar->element[i];
    			int count = 1;
    
    			if (temp != 0) {
    				if (temp < 0)
    					temp = -temp;
    
    				while ((temp = temp / 10) > 0)
    					++count;
    			}
    
    			// The new size is the old size and the new element, and the comma and space
    			size = size + (count * 3);
    			// Reallocate the array to be able to hold the next element
    			str = realloc(str, size);
    
    			itoa(ar->element[i++], &str[++j], 10);
    			j = strlen(str);
    			str[j] = ',';
    			str[++j] = ' ';
    		}
    		str[--j] = ']';
    		str[++j] = '\0';
        }
    This seems to be working.

    Thanks for all your help guys!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how to combine these working parts??
    By transgalactic2 in forum C Programming
    Replies: 0
    Last Post: 02-01-2009, 08:19 AM
  2. Debug Error Really Quick Question
    By GCNDoug in forum C Programming
    Replies: 1
    Last Post: 04-23-2007, 12:05 PM
  3. Please Help - Problem with Compilers
    By toonlover in forum C++ Programming
    Replies: 5
    Last Post: 07-23-2005, 10:03 AM
  4. UNICODE and GET_STATE
    By Registered in forum C++ Programming
    Replies: 1
    Last Post: 07-15-2002, 03:23 PM
  5. A Simple (?) Problem
    By Unregistered in forum C++ Programming
    Replies: 8
    Last Post: 10-12-2001, 04:28 AM