Thread: K&R Exercise 1-16: Modifying a getline() function

  1. #1
    Registered User edw211's Avatar
    Join Date
    Jun 2011
    Location
    Wilkes-Barre, PA
    Posts
    22

    K&R Exercise 1-16: Modifying a getline() function

    This exercise asks me to rewrite a getline() function. Originally, it stored up to 1000 chars of the line in an array and returned the length of the line. However, the function would not return the length correctly for arbitrarily long input lines, returning a max of 1000, ignoring anything after the 998th character.

    My task was to rewrite getline() to correctly return the length, but still only store the 1000 first characters in the array I pass to it.

    Here is the original getline() unmodified:

    Code:
    /* getline: read a line into s, return length */
    int getline(char s[], int lim)
    {
    	int c, i;
    
    	for (i=0; i < lim - 1 && (c=getchar()) != EOF && c != '\n'; ++i)
    		s[i] = c;
    	if (c == '\n')
    	{
    		s[i] = c;
    		++i;
    	}
    	s[i] = '\0';
    	return i;
    }
    Here are my modifications. I've tested it with a lower max of 10, but want to make sure I haven't left any holes that anyone more experienced could easily spot.

    Code:
    /* getline: read a line (1000 char max) into s, return true length */
    int getline(char s[], int lim)
    {
    	//length: true length of string regardless of array size limit
    	//pos: current position in the array limited to 1000 chars
    	//c: char holder 
    	int length = 0, pos = 0, c = 0;
    	
    	for (length=0; (c=getchar()) != EOF && c != '\n'; ++length)
    	{
    		//only assign to the array if we are under the limit of 998
    			//need room for '\n' and '\0'
    		if(length < lim - 1)
    			s[pos++] = c;
    	}
    	
    	if (c == '\n')
    	{
    		s[pos] = c;
    		++pos;
    	}
    
    	s[pos] = '\0';
    	
    	return length;
    }
    Thanks in advance for any constructive criticism anyone can provide.

    EDIT: I should note that the maximum of 1000 I mentioned is a symbolic constant I pass to getline() in my main().
    Last edited by edw211; 06-15-2011 at 03:20 AM.
    Evan Williams
    Lehigh University Senior
    Computer Science and Engineering

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Suppose '\n' isn't encountered in the first lim -1 characters. Doesn't your function still put the '\n' in with the data that is returned? That would be wrong.

  3. #3
    Registered User edw211's Avatar
    Join Date
    Jun 2011
    Location
    Wilkes-Barre, PA
    Posts
    22
    Ah, right you are. Thanks.
    Evan Williams
    Lehigh University Senior
    Computer Science and Engineering

  4. #4
    Registered User edw211's Avatar
    Join Date
    Jun 2011
    Location
    Wilkes-Barre, PA
    Posts
    22
    Would adding a "length == pos" condition like this fix the problem? It should ensure that I've not surpassed the limit. Seems to fix the problem when I test it:

    Code:
    /* getline (MODIFIED): read a line (1000 char max) into s, return length */
    int getline(char s[], int lim)
    {
    	//length: true length of string regardless of limit
    	//pos: current position in the array limited to 1000 chars
    	//c: char holder 
    	int length = 0, pos = 0, c = 0;
    	
    	for (length = 0; (c=getchar()) != EOF && c != '\n'; ++length)
    	{
    		//only assign to the array if we are under the limit of 998
    			//need room for '\n' and '\0'
    		if(length < lim - 1)
    			s[pos++] = c;
    	}
    	
    	if (c == '\n' && length == pos)
    	{
    		s[pos] = c;
    		++pos;
    	}
    
    	s[pos] = '\0';
    	
    	return length;
    }
    Evan Williams
    Lehigh University Senior
    Computer Science and Engineering

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    No, I just tested it to make sure and now you have a new problem.

    Code:
    -		hello	0x0012fd60 "012345678
    "	char [512]
    		[0]	48 '0'	char
    		[1]	49 '1'	char
    		[2]	50 '2'	char
    		[3]	51 '3'	char
    		[4]	52 '4'	char
    		[5]	53 '5'	char
    		[6]	54 '6'	char
    		[7]	55 '7'	char
    		[8]	56 '8'	char
    		[9]	10 '
    '	char
    		[10]	0	char
    The limit here was 10, so that means your function adds the '\n' if it is the last thing entered at the limit. As you can see from the debugger output, the '\n' takes up space [9] which is where the terminating '\0' should be. Instead your function has to access the 10th space to do this, which could be out of bounds.

    It's better to add pos < lim - 1, looking like this:
    Code:
     if (c == '\n' && pos < lim - 1)
    This way pos isn't bumped up unless it needs to be and '\0' will always be correctly put.

  6. #6
    Registered User edw211's Avatar
    Join Date
    Jun 2011
    Location
    Wilkes-Barre, PA
    Posts
    22
    I just ran my debugger and see that now. Thanks a lot! =)
    Evan Williams
    Lehigh University Senior
    Computer Science and Engineering

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Modifying variable from external function
    By haifisch in forum C Programming
    Replies: 2
    Last Post: 05-11-2010, 06:02 AM
  2. modifying bubblesort function
    By tenhavenator in forum C Programming
    Replies: 3
    Last Post: 11-14-2009, 12:54 AM
  3. modifying a return address of a function
    By jay1313 in forum C Programming
    Replies: 3
    Last Post: 09-18-2008, 09:09 AM
  4. Stuck on function exercise
    By yougene in forum C Programming
    Replies: 2
    Last Post: 07-24-2007, 01:10 AM
  5. Function exercise
    By Bit in forum C Programming
    Replies: 6
    Last Post: 09-27-2004, 07:37 PM