Register FAQ/Rules Forum Spy Search Today's Posts Mark Forums Read

Welcome to the Mac Forums forums. Please read the FAQ if you have questions. Register to participate.

 
Go Back   Mac Forums > Apple Software > Mac Programming
TouchArcade.com - iPhone Game Reviews and News

Reply
 
Thread Tools Search this Thread Display Modes
Old Nov 4, 2009, 12:57 PM   #1
gotenks05
macrumors member
 
Join Date: Jan 2009
[C programming] reverse string

Alright, I'm having another problem in C. I want to make a program that takes a string inputted by the user and reverses it. I got it to work, but it displays gibberish at the start, which I can't get rid of.

Here is the function prototype:

Code:
void reverse(char string[], int size);
Here is the function definition:

Code:
#include <stdio.h>

void reverse(char string[], int size)
{
	int count = size -1;

	for (count; count >= 0; count--)
	{

		if (string[count] >= 33 && string[count] < 123| string[count] >= 65 && string[count] < 123 | string[count] >= 97 && string[count] < 123)
		{
			printf("%c", string[count]);
		}
	}

	printf("\n");
}
and here is the source:

Code:
#include <stdio.h>
#define Size 700
int main()
{
	char sentence[Size];
	int items = Size;

	printf("Enter a string:  ");

	fgets(sentence, Size, stdin);

	reverse(sentence, items);

	return 0;
}
I defined a variable to 700, because that will accommodate most strings, since I have no idea how long the actual string a user inputs will be exactly. Both putchar and printf give me gibberish.

Last edited by gotenks05 : Nov 4, 2009 at 12:58 PM. Reason: wrong function mentioned
gotenks05 is offline   Reply With Quote
Old Nov 4, 2009, 01:20 PM   #2
autorelease
macrumors regular
 
Join Date: Oct 2008
Location: Achewood, CA
You're not just printing the bytes of the string in reverse order; you're printing the bytes of the entire 700-byte buffer in reverse order.

I see that you've tried to compensate for this by trying to print only characters with certain ASCII values. However, when your program starts, your 700-byte buffer might not be all zeros; it'll probably be filled with random values, some of which will probably be letters. These gibberish values don't get overwritten by fgets(), so they'll be printed in your reverse() function.

So you shouldn't be passing 700 as the size parameter to reverse(). Use the actual length of the string the user entered. This can be computed with the strlen() function.

Also, technically, you're not reversing the string, you're printing the letters in reverse order. The characters in the string haven't moved anywhere. Actually reversing the bytes a string is a good exercise; do it without making a copy of the string for bonus points! ;-)
__________________
*** -[NSAutoreleasePool autorelease]: Cannot autorelease an autorelease pool
autorelease is offline   Reply With Quote
Old Nov 4, 2009, 01:40 PM   #3
gotenks05
Thread Starter
macrumors member
 
Join Date: Jan 2009
Quote:
Originally Posted by autorelease View Post
You're not just printing the bytes of the string in reverse order; you're printing the bytes of the entire 700-byte buffer in reverse order.

I see that you've tried to compensate for this by trying to print only characters with certain ASCII values. However, when your program starts, your 700-byte buffer might not be all zeros; it'll probably be filled with random values, some of which will probably be letters. These gibberish values don't get overwritten by fgets(), so they'll be printed in your reverse() function.

So you shouldn't be passing 700 as the size parameter to reverse(). Use the actual length of the string the user entered. This can be computed with the strlen() function.

Also, technically, you're not reversing the string, you're printing the letters in reverse order. The characters in the string haven't moved anywhere. Actually reversing the bytes a string is a good exercise; do it without making a copy of the string for bonus points! ;-)
Thanks that helped.
gotenks05 is offline   Reply With Quote
Old Nov 4, 2009, 05:44 PM   #4
Kyle?
macrumors 6502a
 
Kyle?'s Avatar
 
Join Date: Nov 2002
Location: MI
Also, your conditional is not doing what you think it is. It's simply accepting all characters between 33 (inclusive) and 123. I'd recommend checking for yourself to see why it's not doing what you think it is. However, following autorelease's advice, you won't even need this test to print valid data.
__________________
We start, then, with nothing, pure zero. But this is not the nothing of negation. For not means other than, and other is merely a synonym of the ordinal numeral second. As such it implies a first; while the present pure zero is prior to every first. The nothing of negation is the nothing of death, which comes second to, or after, everything. But this pure zero is the nothing of not having been born. There is no individual thing, no compulsion, outward nor inward, no law. It is the germinal nothing, in which the whole universe is involved or foreshadowed. As such, it is absolutely undefined and unlimited possibility -- boundless possibility. There is no compulsion and no law. It is boundless freedom.
-Charles S. Peirce www.nothing.com
Kyle? is offline   Reply With Quote
Old Nov 4, 2009, 06:21 PM   #5
lloyddean
macrumors regular
 
Join Date: May 2009
Location: Seattle
Since he's implied a solution but not posted it I'll throw this one down for future readers.

Assuming C99 and 'char string[]' is NOT a pointer to a string constant -

Code:
void reverse(char string[])
{
    char*   left    = &string[0]-1;
    char*   right   = &string[strlen(string)];
    char    temp;
    while ( ++left < --right )
    {
        temp = *left;
        *left = *right;
        *right = temp;
    }
}

Last edited by lloyddean : Nov 5, 2009 at 12:33 PM. Reason: Rewrote the function to work correctly.
lloyddean is offline   Reply With Quote
Old Nov 4, 2009, 08:34 PM   #6
gnasher729
macrumors 68040
 
gnasher729's Avatar
 
Join Date: Nov 2005
Quote:
Originally Posted by lloyddean View Post
Since he's implied a solution but not posted it I'll throw this one down for future readers.

Assuming C99 and 'char string[]' is NOT a pointer to a string constant -

Code:
void reverse(char string[])
{
    char c;
    for ( int  i = 0; i < ((strlen(string)-1) / 2); i++ )
    {
        c = string[i];
        string[i] = string[(strlen(string)-1) - i];
        string[(strlen(string)-1) - i] = c;
    }
}
Question: What happens when you pass in a string with a million characters?
Question: What happens when you pass in a string with 2, 4, 6 or 8 characters?
gnasher729 is offline   Reply With Quote
Old Nov 4, 2009, 09:04 PM   #7
JangoFett124
macrumors member
 
Join Date: Jul 2002
Quote:
Originally Posted by lloyddean View Post
Since he's implied a solution but not posted it I'll throw this one down for future readers.

Assuming C99 and 'char string[]' is NOT a pointer to a string constant -

Code:
void reverse(char string[])
{
    char c;
    for ( int  i = 0; i < ((strlen(string)-1) / 2); i++ )
    {
        c = string[i];
        string[i] = string[(strlen(string)-1) - i];
        string[(strlen(string)-1) - i] = c;
    }
}
Haven't tested it, but this seems more like it:

Code:
void reverse(char string[])
{
    for (int low = 0, high = strlen(string)-1; low < high; ++low, --high)
    {
        const char temp = string[low];
        string[low] = string[high];
        string[high] = temp;
    }
}
(I do feel a bit dirty doing the homework from someone that doesn't even seem all that appreciative looking at their post history. Hopefully tests have more weight than these assignments.)
JangoFett124 is online now   Reply With Quote
Old Nov 4, 2009, 10:17 PM   #8
lloyddean
macrumors regular
 
Join Date: May 2009
Location: Seattle
Whoops you're right gnasher729.
lloyddean is offline   Reply With Quote
Old Nov 5, 2009, 11:47 AM   #9
Kyle?
macrumors 6502a
 
Kyle?'s Avatar
 
Join Date: Nov 2002
Location: MI
lloyddean, it doesn't matter for efficiency, and it shouldn't introduce any bugs, but you don't have to execute your loop when low and high are equal.
__________________
We start, then, with nothing, pure zero. But this is not the nothing of negation. For not means other than, and other is merely a synonym of the ordinal numeral second. As such it implies a first; while the present pure zero is prior to every first. The nothing of negation is the nothing of death, which comes second to, or after, everything. But this pure zero is the nothing of not having been born. There is no individual thing, no compulsion, outward nor inward, no law. It is the germinal nothing, in which the whole universe is involved or foreshadowed. As such, it is absolutely undefined and unlimited possibility -- boundless possibility. There is no compulsion and no law. It is boundless freedom.
-Charles S. Peirce www.nothing.com
Kyle? is offline   Reply With Quote
Old Nov 5, 2009, 11:54 AM   #10
lee1210
macrumors 68000
 
lee1210's Avatar
 
Join Date: Jan 2005
Location: Austin, TX
Quote:
Originally Posted by Kyle? View Post
lloyddean, it doesn't matter for efficiency, and it shouldn't introduce any bugs, but you don't have to execute your loop when low and high are equal.
It would affect it if you changed your swap to the XOR trick instead of using a temp variable for swapping. If you use that trick on the same memory address, you end up zero'ing it.

-Lee
lee1210 is online now   Reply With Quote
Old Nov 5, 2009, 02:43 PM   #11
autorelease
macrumors regular
 
Join Date: Oct 2008
Location: Achewood, CA
Quote:
Originally Posted by lee1210 View Post
It would affect it if you changed your swap to the XOR trick instead of using a temp variable for swapping. If you use that trick on the same memory address, you end up zero'ing it.

-Lee
The XOR trick is clever but you shouldn't use it unless you're an 8-bit assembler jockey. On modern hardware, the standard swap can be pipelined better, and the compiler might even recognize the swap and turn it into an exchange instruction.

Here's my solution to the in-place swap I suggested. JangoFett and lloyddean pretty much had it right, I just prefer for loops
Code:
void reverse(char *str)
{
  char *front, *back;
  for (front = str, back = str+strlen(str)-1; front < back; front++, back--)
  {
    char tmp = *front;
    *front = *back;
    *back = tmp;
  }
}
This function can also be modified to test whether or not a string is a palindrome. Any takers?
__________________
*** -[NSAutoreleasePool autorelease]: Cannot autorelease an autorelease pool
autorelease is offline   Reply With Quote
Old Nov 5, 2009, 03:20 PM   #12
lee1210
macrumors 68000
 
lee1210's Avatar
 
Join Date: Jan 2005
Location: Austin, TX
Quote:
Originally Posted by autorelease View Post
The XOR trick is clever but you shouldn't use it unless you're an 8-bit assembler jockey. On modern hardware, the standard swap can be pipelined better, and the compiler might even recognize the swap and turn it into an exchange instruction.

Here's my solution to the in-place swap I suggested. JangoFett and lloyddean pretty much had it right, I just prefer for loops
Code:
void reverse(char *str)
{
  char *front, *back;
  for (front = str, back = str+strlen(str)-1; front < back; front++, back--)
  {
    char tmp = *front;
    *front = *back;
    *back = tmp;
  }
}
This function can also be modified to test whether or not a string is a palindrome. Any takers?
Code:
void reverse(char *str)
{
  char *front, *back;
  int isPalindrome = 1;
  for (front = str, back = str+strlen(str)-1; front < back; front++, back--)
  {   
    if(*front != *back) {
      char tmp = *front;
      isPalindrome = 0;
      *front = *back;
      *back = tmp;
    }
  }
  if(isPalindrome == 1) printf("Found a palindrome! Huzzah!\n");
}
Also, i mentioned the XOR trick because it was one of the first things that really pulled me into CS. When my HS CS teacher showed it to us, it blew my mind. It is totally useless for modern programming, i just think it's interesting. Another a-ha moment was when a prof or TA in college said that you should ensure you check that the addresses aren't equal when passed into an XOR swap subroutine, or you'll lose your value.

-Lee
lee1210 is online now   Reply With Quote
Old Nov 5, 2009, 10:25 PM   #13
lloyddean
macrumors regular
 
Join Date: May 2009
Location: Seattle
Quote:
The XOR trick is clever but you shouldn't use it unless you're an 8-bit assembler jockey. On modern hardware, the standard swap can be pipelined better, and the compiler might even recognize the swap and turn it into an exchange instruction.
Yes it was quite useful back in the mid 70's for game programming on the very small memory systems of the day. And still useful in the very small embedded throw away processors.

But, I think it's best left as a curiosity on todays desktop systems and game consoles.
lloyddean is offline   Reply With Quote

Reply

Mac Forums > Apple Software > Mac Programming

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -5. The time now is 08:03 AM.

Mac News | Mac Rumors | iPhone Game Reviews | iPhone Apps

Powered by vBulletin® Version 3.6.10
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Copyright 2002-2010, MacRumors.com, LLC