Thread: Truncating user input

  1. #1
    Registered User
    Join Date
    Feb 2009
    Posts
    19

    Truncating user input

    What's the best way to truncate user input to a certain number of characters ( ie.6 characters)? tried using the following code but it doesn't seem to work properly for certain inputs.

    If I input only a newline the output is:
    �@
    If I input ctrl +D the output is:
    �@
    If I input one character, for example 'a' the output is:
    a@
    If I input two characters, for example 'ab' the output is:
    ab@

    For three or more characters the output appears to be correct and if I enter more characters than MAX, the output appears to be properly truncated.

    Can someone point out what I'm doing wrong?


    Code:
    #include <stdio.h>
    #define MAX 6
    
    int main(void)
    {
    int c;
    	char array [MAX];
    	int count = 0;
    
    	while((c = getchar()) != EOF && count < MAX &&  c != '\n')
    	{
    		array[count++] = c;
    	}
    	
    	printf("\n%s", array);
    	printf("\n");
    	return 0;
    }
    Last edited by CS_Student8337; 03-17-2009 at 02:52 AM.

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Quote Originally Posted by CS_Student8337 View Post
    What's the best way to truncate user input to a certain number of characters ( ie.6 characters)? tried using the following code but it doesn't seem to work properly for certain inputs.

    If I input only a newline the output is:
    �@

    Your array has just random "stuff" in it. Your newline is not being added to the array.

    If I input ctrl +D the output is:
    �@
    Your while condition doesn't exclude adding a ctrl + D to the array, so it's being added.

    If I input one character, for example 'a' the output is:
    a@
    You added one char, but you did not add the end of string char to the char array, and
    you're printing the array out, as a string.

    A bunch of char's in a char array != a string. A string must have an end of string marker char - or the string will be interpreted as God knows what, for it's end.


    If I input two characters, for example 'ab' the output is:
    ab@

    Sure, same reason as above.
    For three or more characters the output appears to be correct and if I enter more characters than MAX, the output appears to be properly truncated.

    Can someone point out what I'm doing wrong?


    Code:
    #include <stdio.h>
    #define MAX 6
    
    int main(void)
    {
    int c;
    	char array [MAX] = { '\0' };
    	int count = 0;
    
    	while((c = getchar()) != EOF && count < MAX &&  c != '\n')
    	{
    		array[count++] = c;
    	}
    	
    	printf("\n%s", array);
    	printf("\n");
    	return 0;
    }
    Setting the char array like this may make it clearer to you.

  3. #3
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    In C, a string is a sequence of characters terminated by a byte with the value zero. If your string doesn't have a zero (aka null) byte, it's not really a string. This also means that if you want to store 6 characters, you need an array that's at least seven bytes long, so you have space for the null character.

    What you want to do is, after the loop, set array[count] to 0. Don't forget about that null byte, meaning you have to make MAX 7 if you want to store 6 characters. For this fix to work, your array should be declared:
    Code:
    char array[MAX + 1];
    As it stands your loop writes MAX bytes to your array. Since you need one extra for the null byte, adding one to the array size is the easiest solution.

  4. #4
    Registered User
    Join Date
    Feb 2009
    Posts
    19
    Thanks for the help. That was a silly error on my part. I have another question though and since it's somewhat related, I hope it's ok to ask it in this thread instead of creating another one.

    I'm trying to create a little program that takes two lines of user input and determines if they are the same. Here's what I have:
    Code:
    #include <stdio.h>
    #include <string.h>
    #define MAX 6
    
    int main(void)
    {
    	int i, j, k, output;
    	char arrayA [MAX], arrayB[MAX];
    	
    	output = 1;
    	
    	printf("Enter line 1: ");
    	fgets(arrayA, MAX, stdin);
    	
    	printf("\nEnter line 2: ");
    	fgets(arrayB, MAX, stdin);
    	
    //Compares arrayA to arrayB and determines if they're the same
    //===========================================================
    	if((i = strlen(arrayA)) != (j = strlen(arrayB)))
    		output = 0;
    	else
    	{
    		for(k = 0; k < i; k++)
    		{
    			if(arrayA[k] != arrayB[k])
    				output =  0;
    		}
    	}	
    //===========================================================
    	switch (output)
    	{
    		case 0: printf("\nDifferent.\n");
    			break;
    		case 1: printf("\nSame.\n");
    			break;
    	}
    
    	return 0;
    }
    Everything works fine until the user inputs more than 5 characters at the first command prompt. My guess is that since I set my MAX to 6, the first 5 characters and a '\0' are going into the first array and any excess characters that were input are going into the second array before the user is even prompted to enter any text for the second array. Is my guess correct and how do I go about fixing this? I'd like for the program to allow the user to enter as much text as they want at each prompt but for only the characters up to MAX to placed in the array and excess characters to be ignored..
    Last edited by CS_Student8337; 03-17-2009 at 11:09 PM.

  5. #5
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    Your guess is correct. The easiest way is to simply make your arrays "large enough", probably a couple thousand characters. Then you can just set array[5] to 0 to truncate the string. The rest is still in the array, but it hardly matters, since string functions won't read beyond the zero.

    You still have the same problem though: say a user enters thousands of characters. For some programs that's OK, but it's still an annoying issue. The way around this would be to read characters yourself, using getchar(), until you see EOF or a newline. For the first 5 (or whatever) characters, store them in the array. Just ignore the rest.

    You can also achieve this with some scanf() trickery, but it's not extremely pretty.

  6. #6
    Registered User
    Join Date
    Feb 2009
    Posts
    19
    Thank you for the response Cas. Taking the input into a huge temporary array was originally what I was going to do but it's expressly forbidden in one of the bullets of the assignment. But I have another idea and was wondering if it would work.

    Code:
    if(arrayA[strlen(arrayA)] == '\n')
                            arrayA[strlen(arrayA)] = '\0';
                  if(arrayA[MAX+1] != '\n' || arrayA[MAX+1 != '\0')
                            while((c = fgetc(stdin)) != EOF || c != '\n');
    //Assume c is declared as an int..

    Basically, what I want this piece of code to do is check if the last character of the array is newline or NULL. If it's not, then it should be safe to assume that there was excess input which will be gathered one character at a time by fgetc until it reaches EOF or newline. That should clean up all of those excess characters I believe.

    Please scrutinize the code. I just wrote and believe that it works except that hitting ENTER for a newline doesn't end fgets. It only ends when I use Ctrl+D.

  7. #7
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Quote Originally Posted by CS_Student8337 View Post
    Thank you for the response Cas. Taking the input into a huge temporary array was originally what I was going to do but it's expressly forbidden in one of the bullets of the assignment. But I have another idea and was wondering if it would work.

    Code:
    if(arrayA[strlen(arrayA)] == '\n')
                            arrayA[strlen(arrayA)] = '\0';
                  if(arrayA[MAX+1] != '\n' || arrayA[MAX+1 != '\0')
                            while((c = fgetc(stdin)) != EOF || c != '\n');
    //Assume c is declared as an int..

    Basically, what I want this piece of code to do is check if the last character of the array is newline or NULL. If it's not, then it should be safe to assume that there was excess input which will be gathered one character at a time by fgetc until it reaches EOF or newline. That should clean up all of those excess characters I believe.

    Please scrutinize the code. I just wrote and believe that it works except that hitting ENTER for a newline doesn't end fgets. It only ends when I use Ctrl+D.
    No. You're driving me nuts here.

    Info on fgets:
    Code:
     Syntax:
       char *fgets(char *s, int n, FILE *stream);
    
     Prototype in:
     stdio.h
    
     Remarks:
    fgets reads characters from stream into the
    string s.
    
    The function stops reading when it reads
    either n - 1 characters or a newline
    character, whichever comes first.
    
    fgets retains the newline character at the end
    of s. A null byte is appended to s to mark the
    end of the string.
    
     Return Value:
    On success, fgets returns the string pointed
    to by s.
    
    It returns null on end-of-file or error.
    
    
    
    
     Example:
     #include <string.h>
     #include <stdio.h>
    
     int main(void)
     {
        FILE *stream;
        char string[] = "This is a test";
        char msg[20];
    
        /* open a file for update */
        stream = fopen("DUMMY.FIL", "w+");
    
        /* write a string into the file */
        fwrite(string, strlen(string), 1, stream);
    
        /* seek to the start of the file */
        fseek(stream, 0, SEEK_SET);
    
        /* read a string from the file */
        fgets(msg, strlen(string)+1, stream);
    
        /* display the string */
        printf("%s", msg);
    
        fclose(stream);
        return 0;
     }
    Let's not assume anything by checking one array element. That doesn't even sound right, does it?

    I'll read thru this thread and see what's up if you promise not to Rube Goldberg it to death.

    OK, you've got your sizes wrong for fgets(). You want it to be two char *LESS* than the size of the array the user is putting char's into.

    So, fgets() needs space in the char array for the char's you want entered, + one space for a newline, + one space for an end of string char marker.

    So adjust your number of char's you want fgets() to put into the array, accordingly. (Two char's less than the size of the array)

    Then see how if that doesn't work properly for you.
    Last edited by Adak; 03-17-2009 at 11:15 PM.

  8. #8
    Registered User
    Join Date
    Feb 2009
    Posts
    19
    No, messing with the sizes of fegts didn't help.
    Code:
    #include <stdio.h>
    #include <string.h>
    #define MAX 6
    
    int main(void)
    {
    	int c, i, j, k, output;
    	char arrayA [MAX+1], arrayB[MAX+1];
    	char *pointerToArrayA = arrayA;
    	char *pointerToArrayB = arrayB;
    	
    	output = 1;
    	
    	printf("Enter line 1: ");
    	fgets(arrayA, MAX+1, stdin);
    	
    	if(arrayA[strlen(arrayA)-1] == '\n')
    	    arrayA[strlen(arrayA)-1] = '\0';
           //++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    	if(arrayA[strlen(arrayA)-1] != '\n' || arrayA[strlen(arrayA)-1] != '\0')    	  
    		while((c = fgetc(stdin)) != EOF)
    		{	
    	    		if(c == '\n')
    				break;
    		}
    	//+++++++++++++++++++++++++++++++++++++++++
    	printf("\nEnter line 2: ");
    	fgets(arrayB, MAX+1, stdin);
    	
    	if(arrayB[strlen(arrayB)-1] == '\n')
    		arrayB[strlen(arrayB)-1] = '\0';
    	
    //Compares arrayA to arrayB and determines if they're the same
    //===========================================================
    	if((i = strlen(pointerToArrayA)) != (j = strlen(pointerToArrayB)))
    		output = 0;
    	else
    	{
    		for(k = 0; k < i; k++)
    		{
    			if(pointerToArrayA[k] != pointerToArrayB[k])
    				output =  0;
    		}
    	}	
    //===========================================================
    	switch (output)
    	{
    		case 0: printf("\nDifferent.\n");
    			break;
    		case 1: printf("\nSame.\n");
    			break;
    	}
    
    
    
    	return 0;
    }
    This code does exactly what I want it to, except when I enter less characters than MAX at the first prompt I have to hit ENTER twice instead of once to go to the prompt for the second input. The problem seems to be somewhere in between the sets of + signs.. Maybe someone can help me figure it out?

  9. #9
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    if you have found \n in the buffer - it means nothing left by the fgets in the stream - you should not call your fgetc loop here
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  10. #10
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    OK, no problems now.

    Code:
    #include <stdio.h>
    #include <string.h>
    #define MAX 6
    
    int main(void)
    {
       int c, i, j, k, output;
       char arrayA [MAX+2], arrayB[MAX+2]; //was +1
       char *ptr;
    
       output = 1;
    	
       printf("Enter line 1: ");
       fgets(arrayA, MAX, stdin);  //was +1
    	
       ptr = strchr(arrayA, '\n');
       if(!ptr) 
          while((c = getchar()) != '\n');
       
    
       printf("\nEnter line 2: ");
       fgets(arrayB, MAX, stdin);  //was +1
    	
       i = strlen(arrayA);
       for(k = 0; k < i; k++)
       {
          if(arrayA[k] != arrayB[k])
    	output =  0;
       }
    		
       switch (output)
       {
          case 0: printf("\nDifferent.\n");
             break;
          case 1: printf("\nSame.\n");
             break;
       };
    
       printf("\n\n\t\t\t   press enter when ready\n");
       ptr = strchr(arrayB, '\n');
       if(!ptr) 
          while((c = getchar()) != '\n');
    
       i = getchar(); 
       return 0;
    }
    Last edited by Adak; 03-18-2009 at 05:09 AM.

  11. #11
    Registered User
    Join Date
    Feb 2009
    Posts
    19
    Thanks to everyone who posted. I think I have it working properly now

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. About aes
    By gumit in forum C Programming
    Replies: 13
    Last Post: 10-24-2006, 03:42 PM
  2. SSH Hacker Activity!! AAHHH!!
    By Kleid-0 in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 03-06-2005, 03:53 PM
  3. Nested Structures - User Input
    By shazg2000 in forum C Programming
    Replies: 2
    Last Post: 01-09-2005, 10:53 AM
  4. ~ User Input script help~
    By indy in forum C Programming
    Replies: 4
    Last Post: 12-02-2003, 06:01 AM
  5. Getting user input for filename loop
    By jpchand in forum C++ Programming
    Replies: 1
    Last Post: 09-16-2003, 06:37 AM