1

I'm constrained to not use anything from <string.h>.

I want to reverse each word in the passed string.

This is what I have so far:

#include <stdio.h>

char * reversepPrint( char *name )
{
    char *normal = name, *reverse = name;

    while ( *reverse ) ++reverse;

    if ( normal < reverse )
    {
        for ( ; normal < --reverse; ++normal  )
        {
            char c = *normal;
            *normal = *reverse;
            *reverse  = c;
        }
    }

    return name;
}

int main( void ) 
{
    char s[] = "Simon liebt Pizza!";

    printf("%s", reversepPrint(s));

    return 0;
}

My code is reversing the whole string, but I want individual words to be reversed - so the result for this example would be "nomiS tbeil !azziP".

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
  • When reversing, keep characters in another array until you find a blank space. Then, reverse again that string in the second array to get the word in order – PhoenixBlue Dec 04 '19 at 15:19
  • Hint: [link](https://stackoverflow.com/questions/9210528/split-string-with-delimiters-in-c) – LPs Dec 04 '19 at 15:29
  • 1
    Lots of answers. Just for fun, here's mine: https://ideone.com/aE5MHU. – 001 Dec 04 '19 at 16:01

6 Answers6

3

We need to decompose into two problems. We already have most of the solution to one problem (reversing a string); we just need to make it work with a substring. We do this mainly by removing the code that finds the end of the string:

/* reverse substring [left, right) in-place */
void reverseSubstring(char *left, char *right)
{
    while (left < --right) {
        char c = *right;
        *right = *left;
        *left++ = c;
    }
}

The other half of the problem is finding the boundaries between words. We can use isspace() to position start and end pointers in the right places, and call our reverseSubstring with them:

#include <ctype.h>
char *reversepPrint(char *const name)
{
    char *start = name;
    char *end;

    while (*start) {
        while (*start && isspace(*start)) {
            ++start;
        }
        end = start;
        while (*end && !isspace(*end)) {
            ++end;
        }
        reverseSubstring(start, end);
        start = end;
    }

    return name;
}

If you're also prohibited from using <ctype.h>, it isn't hard to write a simple isspace() of your own for this function.


Full program

/* reverse substring [left, right) in-place */
void reverse_substring(char *left, char *right)
{
    while (left < --right) {
        char c = *right;
        *right = *left;
        *left++ = c;
    }
}
    
#include <ctype.h>
/* reverse individual words in string */
/* word boundaries determined by isspace() */
char *reverse_words(char *const name)
{
    for (char *start = name, *end;  *start;  start = end) {
        while (*start && isspace(*start)) { ++start; }
        end = start;
        while (*end && !isspace(*end)) { ++end; }
        reverse_substring(start, end);
    }

    return name;
}

#include <stdio.h>
int main(void)
{
    char s[] = "Simon liebt Pizza!";
    printf("%s", reverse_words(s));
}
Community
  • 1
  • 1
Toby Speight
  • 27,591
  • 48
  • 66
  • 103
  • How can i put all together in one function i tested it but i cannot put reverSubstring function into the reversePrint(); function –  Dec 04 '19 at 16:42
  • Why do you want it all in one function? That's less reusable, and harder to understand! You *can* do it, but remember that here, `reverse_substring()` gets *copies* of its arguments (and modifies those copies), so you'd need to manually make copies if you inline it into `reverse_words()`. I.e. `char *left = start, *right = end;` – Toby Speight Dec 04 '19 at 16:46
0

Your function reversepPrint reverse a string.

Since you want to reverse by word, you have to parse your string in order to apply your function reversepPrint on each word. For doing so, you can use the space character as a delimiter.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Chopin
  • 188
  • 1
  • 10
0

What I would do is the following:

  1. Create a function that reverse only n char of a string
  2. Use that to reverse words of the original array.
  3. Words can be easily identified because are blocks of non-null and non-space chars.

Something like the following should work (note that I did not test the code) and produces the following output: nomiS tbeil !azziP

//this is basically your original function
char * reverse_n( char *name, const int  len )
{
    char *normal = name, *reverse = name+len;

    if ( normal < reverse )
    {
        for ( ; normal < --reverse; ++normal  )
        {
            char c = *normal;
            *normal = *reverse;
            *reverse  = c;
        }
    }

    return name;
}

char * my_reverse( char *nname)
{
    char* name=nname;
    while(*name)
    {
        char* next = name;
        int l = 0;
        //find the next word and its length
        while(*next && *next!=' '){
            next++;
            l++;
        }
        //reverse it
        reverse_n(name, l);
        name=next;
        //skip the space
        if(*name)
            name++;
    }
    return nname;
}
Davide Spataro
  • 7,319
  • 1
  • 24
  • 36
0

Here's my little effort to the logic without using the string.h

#include <stdio.h>

char * reversepPrint( char *name )
{

    char *normal = name, *reverse = name;

    while ( *reverse ) ++reverse;

    if ( normal < reverse )
    {
        for ( ; normal < --reverse; ++normal  )
        {
            char c = *normal;
            *normal = *reverse;
            *reverse  = c;
        }
    }

    return name;
}

int main( void ) 
{
    char s[] = "Simon liebt Pizza!";
    int i;
    int num_of_spaces = 0;

    int length = 0;

    char *temp = &s;

    while(*temp!='\0'){
        temp++;
    }
    length = temp - s;


    for (i = 0; i<length; i++)
    {

        if (s[i]==' ')
        {
            num_of_spaces++;
        }
    }

    char x[num_of_spaces+1][100];
    i = 0;
    int index = 0,index1 = 0, k = 0;
    for(i = 0; i < length; i++)
    {
        if(s[i]!=' ')
        {
            x[k][index] = s[index1];
            index++;

        }else{

            x[k][index] = '\0';
            index = 0;
            k++;

        }
        index1++;
    }

    i = 0;
    for(i = 0; i<=num_of_spaces; i++)
    {
        printf("%s\n",reversepPrint(x[i]));
    }



    return 0;
}

This is what the code does

  • Given any string it will find its length without using strlen
  • Then, the code will find the total numbers of strings (Spaces between them)
  • After that, I am creating a 2d-array with the dimension [strings][100] (each string with length 100)
  • Copying the content separately to each string
  • then looping over the 2d array and calling the method.
Amir Ali
  • 11
  • 7
  • What happens when you use it on a string that has a really long word? There appears to be a hard limit of 100 chars per word, with no checking for overflow. – Toby Speight Dec 04 '19 at 16:08
  • Well, we can modify that a bit which would cater that. In most cases, during learning phase keeping a fixed length would be sufficient enough. – Amir Ali Dec 04 '19 at 16:38
0

Here is a version using some nested loops:

#include <ctype.h>

char * reversepPrint( char *name )
{
    char *s = name;

    while (*s)
    {
        char *t = s;

        /* Find end of non-space character sequence. */
        while (*t && *t == (unsigned char)*t && !isspace(*t))
        {
            t++;
        }
        if (t - s > 1)
        {
            /* Got a non-space character sequence of length > 1. */
            char *e = t;

            /* Reverse the non-space character sequence. */
            do
            {
                char tmp = *s;

                *s++ = *--e;
                *e = tmp;
            } while (s < e);

            /* Start past non-space characters for next iteration. */
            s = t;
        }
        else
        {
            /* Skip space or singleton non-space. */
            s++;
        }
    }

    return name;
}

The variable s is used to advance through the name string in each iteration of the outer while loop. The variable t is initialized to s in each iteration of the outer loop and is then advanced past any non-space characters by the inner while (*t && ...) loop. After advancing t past the any non-space characters, the length of the sequence of non-space characters is t - s. (If *s is a space character then this length will be 0.) If this length is greater than 1, it uses the inner do { ... } while loop to reverse the sequence of non-space characters, and then assigns s = t ready for the next iteration of the outer loop. Otherwise, *s is either a space character or a singleton non-space character, so s is advanced by one character for the next iteration of the outer loop.

Ian Abbott
  • 15,083
  • 19
  • 33
  • How can i chage the upper and lower case so the first letter of a word is always uppercase and the all the others lowercase. I cannot reach the goal i tried many ideas. –  Dec 05 '19 at 09:37
  • how can i find the first Charakter in the Word So that the result is Nomis Tbeil Azzip! –  Dec 05 '19 at 10:18
  • @SimonMayrhofer That can be done in a separate function. It probably needs a different rule to determine the start and end of a "word" (for example, using any non-alphabetic character as a word separator). – Ian Abbott Dec 05 '19 at 10:49
-2

try this logic instead,reverse the individual words of string one by one, for example if the string is "i like programming" after reversing the individual words the string should be "i ekil gnimmargorp".

i hope this code snippet helps

void reverse(char* begin, char* end) 
{ 
    char temp; 
    while (begin < end) { 
        temp = *begin; 
        *begin++ = *end; 
        *end-- = temp; 
    } 
} 

// Function to reverse words 
void reverseWords(char* s) 
{ 
    char* begin = s; 

    char* temp = s;  
    while (*temp) { 
        temp++; 
        if (*temp == '\0') { 
            reverse(begin, temp - 1); 
        } 
        else if (*temp == ' ') { 
            reverse(begin, temp - 1); 
            begin = temp + 1; 
        } 
    } 
} 
nani
  • 1
  • 1