Thread: swaping characters

  1. #1
    Registered User
    Join Date
    Oct 2007
    Posts
    62

    swaping characters

    Hi
    I wrote this to swap characters in a string. as long as the string is even in legnth, it works fine. But when it is odd it prints the last character on a new line and a ascii character. I know it is because the last character does not have anything to swap with. My goal is to just print the last character at the end if it is odd. I know I need modulus but van;t figure out where.

    Code:
    #include "string.h"
    #define MaxStringLen 200
    
    int main(int argc, char* argv)
    {
    	char userString[MaxStringLen + 1];
    	char *copyString;
    	int size;
    	int i;
    
    	printf( "Please enter some text: ");
    	fgets(userString, sizeof(userString), stdin);
    	
    	size = strlen(userString);
    
    	copyString = malloc(size + 1 * sizeof(char));	
    	
    	for (i = 0; i < size + 1; i += 2)
    	{
    		copyString[i] = userString[i + 1];
    		copyString[i + 1] = userString[i];
    	}
    
    	printf( "Here is the string you entered and its byte-swapped counterpart:\n");
    	printf( "  %s", userString);
    	printf( "  %s\n", copyString);
    
    	free(copyString);
    	copyString = NULL;
    
    	return 0;
    }

  2. #2
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Something like,

    Code:
    /* if it's odd */
    if(size &#37; 2 != 0)
        lastChar = userString[size - 1];
    Or whatever

  3. #3
    Registered User
    Join Date
    Oct 2007
    Posts
    62
    Quote Originally Posted by zacs7 View Post
    Something like,

    Code:
    /* if it's odd */
    if(size % 2 != 0)
        lastChar = userString[size - 1];
    Or whatever
    hmmm I get it. But I really want to stop the loop at the right time don't I? I get Heap overruns if I don't.

  4. #4
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    I would check if it's odd before the loop maybe? And act accordingly (ie trim the last chars off 'size' so it is even).

    You should also be checking if the malloc() failed or succeeded.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > for (i = 0; i < size + 1; i += 2)
    Since there is also a +1 inside the loop, the +1 here as well combine for a total of size+2 - aka overrun.

    You might want to check the precedence of + and * in your malloc calculation.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    abyss - deep C
    Join Date
    Oct 2007
    Posts
    46
    You could use the code below:

    Code:
    for (i = 0; i < size/2; i++)
    {
      copyString[2*i] = userString[2*i+1];
      copyString[2*i+1] = userString[2*i];
    }
    copyString[2*i] = '\0';
    The for loop takes care of the last single character.
    Also, we shouldn't forget to end the copyString with the '\0' character.

    Code:
    copyString[2*i] = '\0';
    cheers
    maverix

  7. #7
    Registered User
    Join Date
    Oct 2007
    Posts
    62
    Quote Originally Posted by Salem View Post
    You might want to check the precedence of + and * in your malloc calculation.
    Thanks Salem. I did not see the precedence issue, I fixed it. I still get the odd character issue. I 'll keep at it!!

  8. #8
    Registered User
    Join Date
    Oct 2007
    Posts
    62
    Quote Originally Posted by maverix View Post
    You could use the code below:

    Code:
    for (i = 0; i < size/2; i++)
    {
      copyString[2*i] = userString[2*i+1];
      copyString[2*i+1] = userString[2*i];
    }
    copyString[2*i] = '\0';
    The for loop takes care of the last single character.
    Also, we shouldn't forget to end the copyString with the '\0' character.

    Code:
    copyString[2*i] = '\0';
    cheers
    maverix
    Thanks. This works but it still prints the last char on a newline

    input:
    01234
    output:
    1032
    4

  9. #9
    Registered User
    Join Date
    Oct 2007
    Posts
    62
    Here's what I have with changes (Thanks to all thus far)

    Code:
    #include "string.h"
    #define MaxStringLen 200
    
    int main(int argc, char* argv)
    {
    	char userString[MaxStringLen + 1];
    	char *copyString;
    	int size;
    	int i;
    
    	printf( "Please enter some text: ");
    	fgets(userString, sizeof(userString), stdin);
    	
    	size = strlen(userString);
    
    	copyString = malloc((size + 1) * sizeof(char));
    
    	for (i = 0; i < size; i += 2)// removed + 1 here per Salem
    	{
    		copyString[i] = userString[i + 1];		
    		copyString[i + 1] = userString[i];
    	}
    	//for (i = 0; i < size/2; i++)
    	//{
    	//	copyString[2*i] = userString[2*i+1];
    	//	copyString[2*i+1] = userString[2*i];
    	//}
    	if (size % 2 != 1)
    	{
    	copyString[i] = userString[i];
    	//copyString[i] = '\0';
    	}
    
    	printf( "Here is the string you entered and its byte-swapped counterpart:\n");
    	printf( "  %s", userString);
    	printf( "  %s\n", copyString);
    
    	free(copyString);
    	copyString = NULL;
    
    	return 0;
    }
    It produces desired results when an even number of char are input, and comes real close when an odd number of char are input.

    input:
    01234
    output:
    1032
    4

    I know (hope) it is something simple or I am not seeing. I'll keep pluggin'
    Thanks all.

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    fgets() reads all text up to and including the newline that is given to it. So if you enter "01234", it gets "01234\n" as the string. You need to remove the newline on the end. To be perfectly safe, you should do something like this:
    Code:
       int len;
       ....
       len  = strlen(input);
       if (input[len-1] == '\n') input[len-1] = 0;
       ...
    This avoids removing the last entry if the string is too long to fit in the buffer given.
    --
    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.

  11. #11
    abyss - deep C
    Join Date
    Oct 2007
    Posts
    46
    Quote Originally Posted by tikelele View Post
    Thanks. This works but it still prints the last char on a newline

    input:
    01234
    output:
    1032
    4

    Hi,

    As pointed out by matsp, your input has a '\n' at the end of the input, hence the behavior.
    Using the code excerpts given by matsp should do the trick.

    cheers
    maverix

  12. #12
    Registered User
    Join Date
    Oct 2007
    Posts
    62
    thanks folks. that's an aspect of fgets that I did not even think of. I suppose I should look fgets over to get more comfortable with it!!

  13. #13
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Remember to update the length of the string if you remove the newline character, I would suggest calculating it's size after you've removed it. Ie,

    Code:
    size_t len = 0;
    char * nl = NULL;
    
    if((nl = strchr(input, '\n')) != NULL)
        *nl = '\0';
    
    len = strlen(input);

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A development process
    By Noir in forum C Programming
    Replies: 37
    Last Post: 07-10-2011, 10:39 PM
  2. HELP!!!!emergency Problem~expert please help
    By unknowppl in forum C++ Programming
    Replies: 9
    Last Post: 08-21-2008, 06:41 PM
  3. Replies: 10
    Last Post: 07-10-2008, 03:45 PM
  4. How do you check how many characters a user has entered?
    By engstudent363 in forum C Programming
    Replies: 5
    Last Post: 04-08-2008, 06:05 AM
  5. help with text input
    By Alphawaves in forum C Programming
    Replies: 8
    Last Post: 04-08-2007, 04:54 PM