Thread: Dynamic string input

  1. #1
    Registered User
    Join Date
    Jul 2010
    Posts
    3

    Dynamic string input

    So I'm trying to create a dynamically allocated user input string. I thought I had everything figured out but theres seems to be a problem when my program reaches 16 char's. Any string smaller than 16 chars seems to work completely fine, and will print out on the screen. Once the string length goes beyond that printf displays garbage. I sat there for about 2 hours trying to figure out why but I can't seem to get it.

    I even use printf(%s) RIGHT before the function exits and the string prints out completely fine.

    Also, am I even going about this the right way?

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <math.h>
    #include "lab4.h"
    
    int main()
    {
    	char *dynamic_string;
    	
    	dynamic_string = (char *)malloc(sizeof(char));
    	if(dynamic_string == NULL)
    	{
    		printf("Error");
    		return 1;
    	}
    
    	user_input(dynamic_string);
    
    	printf("%s\n", dynamic_string);
    	return 0;
    }
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <math.h>
    
    void user_input(char *input_array)
    {
    	int i;
    	int j;
    	int flag = 0;
    	int string_size = 0;
    	int num_allocated = 1;
    	char * temp;	
    
    	for(i=0; flag!=1; i++)
    	{
    		scanf("%c", &input_array[i]);
    		string_size++;
    
    		if(string_size == num_allocated)
    		{
    			temp = (char *)malloc(num_allocated*2);
    			if(temp == NULL)
    			{
    				printf("Error");
    				flag = 1;
    			}
    	
    			for(j=0; j<=string_size; j++)
    			{
    				temp[j] = input_array[j];
    			}
    
    			free(input_array);
    			input_array = (char *)malloc(num_allocated*2);	
    			if(input_array == NULL)
    			{
    				printf("Error");
    				flag = 1;
    			}
    
    			for(j=0; j<=string_size; j++)
    			{
    				input_array[j] = temp[j];
    			}
    			
    			free(temp);
    			temp = NULL;
    			num_allocated *= 2;
    		}
    
    		if(input_array[i] == '\n')
    		{
    			input_array[i] = '\0';
    			printf("TEST = %s\n", input_array);
    			flag = 1;
    		}
    	}
    }

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    I'm surprised you get anything out of it. You can't update a pointer inside a function, so that it points elsewhere, unless you pass a pointer to that pointer.
    Code:
    void bar( char ** ); /*prototype */
    ...
    char *foo;
    bar( &foo ); /* call */
    Or, alternately, you can return a new pointer:
    Code:
    char *bar ( char * );
    ...
    char *foo;
    foo = bar( foo );

    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Jul 2010
    Posts
    3
    Ah I thought it would be something along those lines, I originally did all the allocating inside of main and only had the user_input function hold the scanf() code to input the string, but then decided to change it because I didn't know if that was the proper way to code. I'm redoing one of my old labs to use dynamic memory, so I don't know where I should be doing the allocating, inside the functions or inside of main?

    Part A

    In this file, create a new C function which can read in whole lines of input from the user of up to 126 characters in length, and store them in a character string passed-in as a function argument. Lines will be separated (only) by newline characters. Note that empty lines are valid entries as well. All other characters should be read and added into the string.

    Create another new C file, as before, and in it write a new function that will use the previous function to read in up to 128 lines from the user until they enter the special line of a "." by itself, or until they enter a 128th line. These should be read into a 128x128 two-dimensional array passed in as a function argument.
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Also, I'm an amateur when it comes to programming, so why can't you modify where a an argument passed pointer points to inside of a function?

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by CaptainQcumber
    Also, I'm an amateur when it comes to programming, so why can't you modify where a an argument passed pointer points to inside of a function?
    You can modify what the pointer points to, but you'll only be modifying your local copy of the pointer that was passed, unless you pass a pointer to the pointer that you want to modify.
    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

  5. #5
    Registered User claudiu's Avatar
    Join Date
    Feb 2010
    Location
    London, United Kingdom
    Posts
    2,094
    Also sizeof(char) means 1.
    1. Get rid of gets(). Never ever ever use it again. Replace it with fgets() and use that instead.
    2. Get rid of void main and replace it with int main(void) and return 0 at the end of the function.
    3. Get rid of conio.h and other antiquated DOS crap headers.
    4. Don't cast the return value of malloc, even if you always always always make sure that stdlib.h is included.

  6. #6
    Registered User
    Join Date
    Jul 2010
    Posts
    3
    So heres my failed attempt at trying to fix this horrid code using char **'s.

    Code:
    int main()
    {
    	char *dynamic_string;
    	char **string_ptr;
    	int i=0;
    	
    	dynamic_string = (char *)malloc(sizeof(char));
    	if(dynamic_string == NULL)
    	{
    		printf("Error");
    		return 1;
    	}
    
    	string_ptr = &dynamic_string;
    	user_input(string_ptr);
    	printf("%s\n", dynamic_string);
    
    	return 0;
    }
    Code:
    void user_input(char **input_array)
    {
    	int i;
    	int j;
    	int flag = 0;
    	int string_size = 0;
    	int num_allocated = 1;
    	char * temp;	
    
    	for(i=0; flag!=1; i++)
    	{
    		scanf("%c", *(&input_array[i]));
    		string_size++;
    
    		if(*input_array[i] == '\n')
    		{
    			*input_array[i] = '\0';
    			flag = 1;
    		}
    		else
    		{
    			if(string_size == num_allocated)
    			{
    				temp = (char *)malloc(num_allocated);
    				for(j=0; j<string_size; j++)
    				{
    					temp[j] = *input_array[j];
    				}
    
    				free(*input_array);
    				*input_array = (char *)malloc(num_allocated*2);
    			
    				for(j=0; j<string_size; j++)
    				{
    					*input_array[j] = temp[j]; 
    				}
    				free(temp);
    				temp = NULL;
    				num_allocated *= 2;
    			}
    		}
    	}
    }
    This is my assumption of how its supposed to work. String_ptr points to dynamic_string, which is the memory I would like to allocate. I pass string_ptr(which points to the address of dynamic_string) to user_input where I can manipulate and dynamically allocate dynamic_string.

    So inside user_input.
    *input_array is technically the address of dynamic_string?
    and *input_array[index] allows me to input a char into dynamic_string?

    I think I have a fatal misunderstanding of pointers, or maybe its just amateur hour.

  7. #7
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    It would be helpful if you reviewed pointers, sure. Mainly though, we have:

    char **outAddress; /* to communicate with the world outside your function */
    char *theString; /* modify this */
    void *more; /* use this to store what realloc returns when you need to grow theString */

    I think if you used the comments like guidelines your code will be simpler. For example would only really use outAddress in the beginning and end of the function body.

    you're doing silly stuff like scanf("%c", *(&input_array[i]));
    which is easier to express than that.

    Basically all you have to do is try to read a part of the line and try to store it in theString. If the line is too big, you've already read a part of it. So, make sure theString is big enough to append the part, do the appending, and keep reading, until you've read the whole line.
    Last edited by whiteflags; 07-23-2010 at 10:12 PM.

  8. #8
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    temp[j] = *input_array[j];
    it's equivalent to *(intput_array[j])... What you need is (*input_array)[j].
    And I don't know why you use scanf() to just read one character? Why not getchar() ?

    Here is a sample implementation.
    Last edited by Bayint Naung; 07-23-2010 at 10:25 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Program using classes - keeps crashing
    By webren in forum C++ Programming
    Replies: 4
    Last Post: 09-16-2005, 03:58 PM
  2. Something is wrong with this menu...
    By DarkViper in forum Windows Programming
    Replies: 2
    Last Post: 12-14-2002, 11:06 PM
  3. ........ed off at functions
    By Klinerr1 in forum C++ Programming
    Replies: 8
    Last Post: 07-29-2002, 09:37 PM