tags:

views:

246

answers:

4

I'm currently going through K.N. King's C Programming: A Modern Approach. I've made it past the text for the 8th chapter (Arrays), and I'm eager to move on to chapter 9, but I've yet to solve the so-called "programming projects" at the end of each chapter. Unfortunately, the 14th... bugs me.

Write a program that reverses the words in a sentence.

Enter a sentence: you can cage a swallow can't you?
Reversal of sentence: you can't swallow a cage can you?

Hint: Use a loop to read the characters one by one and store them in a one-dimensional char array. Have the loop stop at a period, question mark, or exclamation point (the "terminating character "), which is saved in a separate char variable. Then use a second loop to search backward through the array for the beginning of the last word. Print the last word, then search backward for the next-to-last word. Repeat until the beginning of the array is reached. Finally, print the terminating character.

I've been thinking of defining a word as a sequence of characters between blank spaces. So when a space is reached, go backward, printing each character, until another space is found. My first version of the program only printed the first word. The current version of it only prints the other words. I've been stuck on this for two days, so any help is truly appreciated. Here is my code, as well as an output sample. Hopefully I've properly documented my code. Thanks in advance!

Code

/* Include the standard I/O library */
#include<stdio.h>

/* Define main */
int main(void) {

    /**
     * Declare an array of characters storing the sentence, as well as
     * a character representing the current character under cursor and
     * the terminating character
     */
    char sentence[100] = { ' ' }, c, tc;

    /**
     * Declare a loop counter already initialized at 0, an incremental
     * variable, as well as the size of the read sentence
     */
    int i = 0, j = 1, size = 0;

    /* Get the sentence */
    printf("Enter a sentence: \n");
    for(c = getchar(); (c != '.') && (c != '!') && 
        (c != '?') && (c != '\n'); c = getchar(), i++) {

        sentence[i] = c; /* Store the current character in the array */
        size++; /* Increase the sentence's size */
    }

    tc = c; /* Get the terminating character */

    /**
     * Go backward through the array, printing each sequence of characters
     * between spaces
     */
    for(i = 99; i >= 0; i--) {

        if(sentence[i] == ' ') {

            while(sentence[i + j] != ' ') {

                printf("%c", sentence[i + j]);
                j++;
            }

            j = 1; /* Reset the incremental variable */
            printf(" "); /* Print a tailing space */
        }
    }

    /**
     * Delete the tailing blank space and print the terminating character,
     * as well as a new line 
     */
    printf("\b%c\n", tc);

    return 0; /* Return 0 upon successful program execution */
}

Output:

http://drp.ly/1nYt5J

+2  A: 

push each word on a stack and read the stack from index 0 to N-1

Quonux
this is hard to do in C if this is his first time messing with strings in C. we're not in C++ or perl land here, toto. :-)
eruciform
I've edited my post removing the "strings" tag. I think many misunderstandings have come across. Apart from this not being a "homework" really, it's also not related to strings. So far, I'm *supposed* to know only Loops, Conditionals, console I/O, basic data types, and, now, arrays. No strings or functions. So I think I have to come up with an ad-hoc solution. Stacks are... two chapters away.
XLR3204S
+2  A: 

Another methodology to think about:

you can cage a swallow can't you?
uoy t'nac wollaws a egac nac uoy?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
you t'nac wollaws a egac nac uoy?
^^^
you can't wollaws a egac nac uoy?
    ^^^^^
you can't swallow a egac nac uoy?
          ^^^^^^^
you can't swallow a egac nac uoy?
                  ^
you can't swallow a cage nac uoy?
                    ^^^^
you can't swallow a cage can uoy?
                         ^^^
you can't swallow a cage can you?
                             ^^^

For each thing you want to reverse (be it a whole sentence or a word):

  1. Find the beginning and end
  2. Swap the beginning and end characters
  3. Move "inwards" once
  4. keep going until you reach "the middle"

Since reversing a chunk of a string is a common operation, it makes sense to make it its own function. And since the only information the function need to do its job is:

  1. the string
  2. the beginning index
  3. the ending index

What do you think the parameters for the function would be?

The other common thing that needs to be done over and over is "finding" something, be it a space or a punctuation mark. You may need to write this yourself, or if you can use library functions, or want a hint, look up:

man strcspn
eruciform
Thing is... I'm not new to programming, I've done extensive work in PHP (and the related web technologies). But two weeks ago I wanted to pick C, this time for good (yes, I do have past attempts, but school was taking way too much time, so I had to give up). So I bought this book and I'm trying to follow it thoroughly. There have been many places where I could have used things like... functions, but I didn't want to, because, as I said, that's the subject of the next chapter, and I'm not trying to rush things. I'm gonna try making the most out of your suggestions. Thanks!
XLR3204S
no problem, glad to help! this is a bit of a large first project messing with strings in c. each of the sub-problems i mentioned (which should go into a separate function each) would be a good place to start. write a program to find either a `'.'` or a `'?'` in a string, and figure out the index. write a program to reverse all the of the characters in a string, all the way to the end (not the `'\0'` though!). and write a program that finds and prints out the individual words in a sentence. if you can do those three things separately, you can add them together to solve this larger problem. :-)
eruciform
I was thinking of writing the first function you suggest, as it would be way easier to look for the end of the input string by using a function with a variable number of arguments. But I'm not supposed to know how to write a function, so, as I said, I'll have to come up with an ad-hoc solution. As for the second function, do I need two arrays, or am I missing something? Finally, is my idea of defining words as sequences of characters delimited by spaces a good one?
XLR3204S
you don't need a variable number of arguments. check out `strcspn`. the first arg is the string to search, the second is a string containing several characters, any of which will trigger the find. `strtok` and several others work this way as well. stay away from variable-arg functions in c unless you really, really need to. for the second function, you can do it in-place. think of juggling. you can swap two balls if you keep one in the air. just make room for that one ball, do the swap, and move on to the next swap. and yes, space-separated is easiest, if not 100% correct - start there.
eruciform
A: 

Here's an example that does what I mentioned. First, reverse each word in place, then reverse the entire string. Here is a reverse() function that reverses a string in place with a given delimiting character. You could extend to use multiple delimiters if you like.

char *reverse(char *str, char delim)
{
  char *end = strchr(str, delim);
  char *ret;
  char tmp;

  if (end == NULL)
    end = strchr(str, '\0');

  ret = end + 1;
  end--;

  while (end > str)
  {
    tmp = *str;
    *str = *end;
    *end = tmp;

    end--;
    str++;
  }

  return ret;
}

Here is a use case with a little example program:

int main(int argc, char **argv)
{
  char *end = strchr(argv[1], '\0');
  char *str = argv[1];

  while (str < end)
    str = reverse(str, ' ');

  reverse(argv[1], '\0');
  printf("%s\n", argv[1]);

  return 0;
}

Usage example:

$ ./example "the quick red fox jumps over the lazy brown dog"
dog brown lazy the over jumps fox red quick the
Carl Norum
`-1` for giving a full-blown solution to someone who needs a nudge into the right direction. How is XLR3204S to learn to think when you give a ready-made solution to paste?!
sbi
@sbi, he says he's not new to programming - only new to C. The point is to help him with a well written example in the language he's trying to learn. Algorithms is not the problem here, learning a specific language syntax is. When *I'm* learning something, I usually want to see a good example - a lot more than I want some vague hints about correct syntax.
Carl Norum
Who is pasting anything? I'm free to skip this problem and the next N chapters if I want to. I'm trying to make the most out of his response/program, by looking up the parts I need. I think the *homework* tag is luring people into thinking I'm doing this for a class or something.
XLR3204S
@XLR3204S, take off the homework tag then.
Carl Norum
The tags were edited and this one was added by eruciform. I thought it was basic procedure, I see other self-taughts have the *homework* tag. Can I remove it without being sanctioned for it?
XLR3204S
my fault, it really looked like a homework problem. my apologies.
eruciform
@Carl: There's an exercise @XLR3204S wants to do, but gets stuck and asks for help. You post a pasteable solution. I'm sorry if this offends you, but, having taught programming for years, that's a pattern I passionately dislike and which I down-vote. (If there was `homework` tag, I didn't see it, BTW.)
sbi
A: 

I havent tried it. hope would be helpful to u.

char temp[100];
int j=0, k=100, l=0;
for(i=size-1; i>=0; i--){
  if(sentence[i] == ' ' || i == 0){
    if(k-i >= 2){// at least one character

      if(i==0) j = 0;
      else j = i+1;

      for( l=0; j < k; j++, l++){
         temp[l] = sentence[j];
      }
      temp[l] = '\0';
      printf("%s ",temp);
    }
    k = i;
  }
}
printf("\b%c",tc);
Sadat
why the minus vote, i dont get it! :(
Sadat
Maybe because it combines parts of your code with parts of my code, but I did not downvote your answer, someone else did. I'll try upvoting to counter it...
XLR3204S
thanks. i have followed your pattern, so that you could get it easily. I have told already, i have typed it here, not tested- but logic should work well.
Sadat
Sadat: I down-voted your answer for the same reason I down-voted Carl's. I'm sorry if you didn't understand this, I thought it was obvious.
sbi