I have developed a reverse-string program. I am wondering if there is a better way to do this, and if my code has any potential problems. I am looking to practice some advanced features of C.
char* reverse_string(char *str)
{
char temp;
size_t len = strlen(str) - 1;
size_t i;
size_t k = len;
for(i = 0; i < len; i++)
{
temp = str[k];
str[k] = str[i];
str[i] = temp;
k--;
/* As 2 characters are changing place for each cycle of the loop
only traverse half the array of characters */
if(k == (len / 2))
{
break;
}
}
}
Just a rearrangement, and safety check. I also removed your non-used return type. I think this is a safe and clean as it gets:
#include <stdio.h>
#include <string.h>
void reverse_string(char *str)
{
/* skip null */
if (str == 0)
{
return;
}
/* skip empty string */
if (*str == 0)
{
return;
}
/* get range */
char *start = str;
char *end = start + strlen(str) - 1; /* -1 for \0 */
char temp;
/* reverse */
while (end > start)
{
/* swap */
temp = *start;
*start = *end;
*end = temp;
/* move */
++start;
--end;
}
}
int main(void)
{
char s1[] = "Reverse me!";
char s2[] = "abc";
char s3[] = "ab";
char s4[] = "a";
char s5[] = "";
reverse_string(0);
reverse_string(s1);
reverse_string(s2);
reverse_string(s3);
reverse_string(s4);
reverse_string(s5);
printf("%s\n", s1);
printf("%s\n", s2);
printf("%s\n", s3);
printf("%s\n", s4);
printf("%s\n", s5);
return 0;
}
Edited so that end will not point to a possibly bad memory location when strlen is 0.
rev {
int len = strlen(str)-1;
for ( int i =0; i< len/2 ; i++ ) {
char t = str[i];
str[i] = str[len-i];
str[len-i] = t;
}
}
My two cents:
/* Reverses n characters of a string and adds a '\0' at the end */
void strnrev (char *txt, size_t len) {
size_t idx;
for (idx = len >> 1; idx > 0; idx--) {
txt[len] = txt[idx - 1];
txt[idx - 1] = txt[len - idx];
txt[len - idx] = txt[len];
}
txt[len] = '\0';
}
/* Reverses a null-terminated string */
void strrev (char *txt) {
size_t len = 0;
while (txt[len++]);
strnrev(txt, --len);
}
Test #1 – strrev()
:
char string[] = "Hello world!";
strrev(string);
printf("%s\n", string); // Displays "!dlrow olleH"
Test #2 – strnrev()
:
char string[] = "Hello world!";
strnrev(string, 5);
printf("%s\n", string); // Displays "olleH"
Here is my shot which will handle all the cases
char *p ="KDLAKDADKADAD"
char p[] = "lammdlamldaldladadada"
also empty string
#include<stdio.h>
#include<string.h>enter code here
#include<stdlib.h>
char *string_reverse(char *p);
int main()
{
char *p = " Deepak@klkaldkaldkakdoroorerr";
char *temp = string_reverse(p);
printf("%s", temp);
}
char * string_reverse( char *p )
{
if(*p == '\0')
{
printf("No charecters are present \n");
return 0;
}
int count = strlen(p)+1;
int mid = strlen(p)/2;
char *q = (char *)malloc(count * sizeof(char));
if( q )
{
strcpy(q,p);
char *begin,*end,temp;
begin = q ;
end = q+strlen(p)-1 ;
int i = 0;
while( i < mid/2 )
{
temp = *end;
*end = *begin;
*begin = temp;
begin++;
end--;
i++;
}
return q;
}
else
{
printf("Memory Not allocated ");
}
free(q);
}
You can actually do something like this:
#include <string.h>
void reverse(char *);
int main(void){
char name[7] = "walter";
reverse(name);
printf("%s", name);
}
void reverse(char *s) {
size_t len = strlen(s);
char *a = s;
char *b = &s[(int)len - 1];
char tmp;
for (; a < b; ++a, --b) {
tmp = *a;
*a = *b;
*b = tmp;
}
}
Does nobody use pointers anymore?
void inplace_rev( char * s ) {
char t, *e = s + strlen(s);
while ( --e > s ) { t = *s;*s++=*e;*e=t; }
}
EDIT: Sorry, just noticed the above XOR example...
bool reverse_string(char* str) {
if(str == NULL){
return false;
}
if(strlen(str) < 2){
return false;
}
char* first = str;
char* last = str + strlen(str) - 1; // Minus 1 accounts for Index offset
char temp;
do{
temp = *first;
*first = *last;
*last = temp;
}
while (++first < --last); // Update Pointer Addresses and check for equality
return true;
}
This solution is based on GManNickG's post with a few modifications. The initial logical statement may be dangerous if !str is not evaluated before the strlen operation (For a NULL ptr). This wasn't the case with my compiler. I thought I would add this code because its a nice example of a do-while loop.
void reverse(char *s)
{
char *end,temp;
end = s;
while(*end != '\0'){
end++;
}
end--; //end points to last letter now
for(;s<end;s++,end--){
temp = *end;
*end = *s;
*s = temp;
}
}
#include <stdio.h>
int main()
{
char string[100];
int i;
printf("Enter a string:\n");
gets(string);
printf("\n");
for(i=strlen(string)-1;i>-1;i--)
printf("%c",string[i]);
}
Try this:
reverse_string(NULL);
reverse_string("");
This complete program shows how I would do it. Keep in mind I was writing C when most of you whippersnappers were a glint in your mothers eyes so it's old-school, do-the-job, long-var-names-are-for-wimps. Fix that if you wish, I'm more interested in the correctness of the code.
It handles NULLs, empty strings and all string sizes. I haven't tested it with strings of maximum size (max(size_t)) but it should work, and if you're handling strings that big, you're insane anyway :-)
#include <stdio.h>
#include <string.h>
char *revStr (char *str) {
char tmp, *src, *dst;
size_t len;
if (str != NULL)
{
len = strlen (str);
if (len > 1) {
src = str;
dst = src + len - 1;
while (src < dst) {
tmp = *src;
*src++ = *dst;
*dst-- = tmp;
}
}
}
return str;
}
char *str[] = {"", "a", "ab", "abc", "abcd", "abcde"};
int main(int argc, char *argv[]) {
int i;
char s[10000];
for (i=0; i < sizeof(str)/sizeof(str[0]); i++) {
strcpy (s, str[i]);
printf ("'%s' -> '%s'\n", str[i], revStr(s));
}
return 0;
}
The output of that is:
'' -> ''
'a' -> 'a'
'ab' -> 'ba'
'abc' -> 'cba'
'abcd' -> 'dcba'
'abcde' -> 'edcba'
Here is my shot. I avoid swapping just by using the standard strcpy
pattern:
char *string_reverse(char *dst, const char *src)
{
if (src == NULL) return NULL;
const char *src_start = src;
char *dst_end = dst + strlen(src);
*dst_end = '\0';
while ((*--dst_end = *src_start++)) { ; }
return dst;
}
Since you say you want to get fancy, perhaps you'll want to exchange your characters using an XOR swap.
Rather than breaking half-way through, you should simply shorten your loop.
size_t length = strlen(str);
size_t i;
for (i = 0; i < (length / 2); i++)
{
char temp = str[length - i - 1];
str[length - i - 1] = str[i];
str[i] = temp;
}
I don't see a return statement, and you are changing the input string, which may be a problem for the programmer. You may want the input string to be immutable.
Also, this may be picky, but len/2 should be calculated only one time, IMO.
Other than that, it will work, as long as you take care of the problem cases mentioned by rossfabricant.
Made a tiny program that accomplishes that:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char str[8192] = "string"; // string
size_t len = strlen(str)-1; // get string length and reduce 1
while(len+1 > 0) // Loop for every character on string
{
printf("%c",str[len--]); // Print string reversed and reducing len by one
}
return 0; // Quit program
}
Explanation:
We take the length of the string, and then we start looping by the last position until we arrive to index 0 quit program.
That's a good question ant2009. You can use a standalone function to reverse the string. The code is...
#include <stdio.h>
#define MAX_CHARACTERS 99
int main( void );
int strlen( char __str );
int main() {
char *str[ MAX_CHARACTERS ];
char *new_string[ MAX_CHARACTERS ];
int i, j;
printf( "enter string: " );
gets( *str );
for( i = 0; j = ( strlen( *str ) - 1 ); i < strlen( *str ), j > -1; i++, j-- ) {
*str[ i ] = *new_string[ j ];
}
printf( "Reverse string is: %s", *new_string" );
return ( 0 );
}
int strlen( char __str[] ) {
int count;
for( int i = 0; __str[ i ] != '\0'; i++ ) {
++count;
}
return ( count );
}
You could change your for loop declaration to make the code shorter:
char* reverse_string(char *str)
{
char temp;
size_t len = strlen(str) - 1;
size_t stop = len/2;
size_t i,k;
for(i = 0, k = len; i < stop; i++, k--)
{
temp = str[k];
str[k] = str[i];
str[i] = temp;
}
return str;
}
The code looks unnecessarily complicated. Here is my version:
void strrev(char* str) {
size_t len = strlen(str);
char buf[len];
for (size_t i = 0; i < len; i++) {
buf[i] = str[len - 1 - i];
};
for (size_t i = 0; i < len; i++) {
str[i] = buf[i];
}
}
easy and simple code xD
void strrev (char s[]) {
int i;
int dim = strlen (s);
char l;
for (i = 0; i < dim / 2; i++) {
l = s[i];
s[i] = s[dim-i-1];
s[dim-i-1] = l;
}
}
You can put your (len/2)
test in the for loop:
for(i = 0,k=len-1 ; i < (len/2); i++,k--)
{
temp = str[k];
str[k] = str[i];
str[i] = temp;
}
#include <stdio.h>
#include <string.h>
int main()
{
char *data = "hello world";
int length=strlen(data);
char bytes[length];
int n=0;
while(n<=length)
{
bytes[n] = data[length-n-1];
n++;
}
printf("%s\n", bytes);
return 0;
}
You can try this pointer arithmetic:
void revString(char *s)
{
char *e = s; while(*e){ e++; } e--;
while(e > s){ *s ^= *e; *e ^= *s; *s++ ^= *e--; }
}
/* Author: Siken Dongol */
#include <stdio.h>
int strLength(char *input) {
int i = 0;
while(input[i++]!='\0');
return --i;
}
int main()
{
char input[] = "Siken Man Singh Dongol";
int len = strLength(input);
char output[len];
int index = 0;
while(len >= 0) {
output[index++] = input[--len];
}
printf("%s\n",input);
printf("%s\n",output);
return 0;
}
Source: Stackoverflow.com