Реверсивные слова в предложении - PullRequest
6 голосов
/ 18 июля 2010

Я сейчас изучаю программирование KN King's C: современный подход .Я закончил текст 8-й главы (массивы), и мне не терпится перейти к 9-й главе, но мне еще предстоит решить так называемые «программные проекты» в конце каждой главы.К сожалению, 14-е ... вызывает у меня .

Напишите программу, которая переворачивает слова в предложении.

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

Подсказка : Используйте цикл для чтения символов по одному и сохранения их в одномерном массиве char .Остановите цикл в точке, вопросительном знаке или восклицательном знаке («завершающий символ»), который сохраняется в отдельной переменной char .Затем используйте второй цикл для поиска в конце массива начала последнего слова.Напечатайте последнее слово, затем ищите в обратном порядке слова, следующие за последним.Повторяйте, пока не будет достигнуто начало массива.Наконец, напечатайте завершающий символ.

Я думал об определении слова как последовательности символов между пробелами.Поэтому, когда пробел достигнут, идите назад, печатая каждый символ, пока не будет найден другой пробел.Моя первая версия программы напечатала только первое слово.Текущая версия печатает только другие слова.Я застрял на этом в течение двух дней, поэтому любая помощь действительно ценится.Вот мой код, а также пример вывода.Надеюсь, я правильно задокументировал свой код.Заранее спасибо!

Код

/* 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 */
}

Выход:

http://drp.ly/1nYt5J

Ответы [ 10 ]

5 голосов
/ 18 июля 2010

вставьте каждое слово в стек и прочитайте стек из индекса 0 в N-1

3 голосов
/ 18 июля 2010

Еще одна методика для размышления:

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?
                             ^^^

Для каждой вещи, которую вы хотите изменить (будь то целое предложение или слово):

  1. Найти начало и конец
  2. Поменять местами начальный и конечный символы
  3. Переместиться "внутрь" один раз
  4. продолжайте идти, пока не достигнете "середины"

Поскольку обращение фрагмента строки является обычной операцией, имеет смысл сделать ее своей собственной функцией. И поскольку единственная информация, которую должна выполнять функция, это:

  1. Строка
  2. начальный индекс
  3. конечный индекс

Как вы думаете, какими будут параметры функции?

Другая распространенная вещь, которую нужно делать снова и снова, это «найти» что-то, будь то пробел или знак пунктуации. Возможно, вам придется написать это самостоятельно, или если вы можете использовать библиотечные функции или захотите подсказку, посмотрите:

man strcspn
2 голосов
/ 18 июля 2010

Вот пример, который делает то, что я упомянул. Сначала поменяйте местами каждое слово, а затем переверните всю строку. Вот функция reverse(), которая переворачивает строку с заданным символом-разделителем. Вы можете использовать несколько разделителей, если хотите.

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;
}

Вот пример использования с небольшим примером программы:

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;
}

Пример использования:

$ ./example "the quick red fox jumps over the lazy brown dog"
dog brown lazy the over jumps fox red quick the
1 голос
/ 08 августа 2015

Принимая входные данные в качестве символьного массива, а затем обращая весь массив.После этого поменяйте слово за словом, где разбиение предложения на слова происходит в "", "?", "\ 0" и т. Д. Надеюсь, это поможет.

 void reverse(char s[],int start,int stop){
 char t;
 while(start<stop){
    t = s[start];
    s[start]=s[stop];
    s[stop]=t;
    start++;
    stop--;
}
}

int main() {

char str[100];
gets(str);

int pos=0,begin=0,end;
reverse(str,begin,strlen(str)-1); //since the last character is null

while(pos<=strlen(str)){
    if((str[pos]==' ')||(str[pos]=='\0')||(str[pos]=='?')||(str[pos]=='!')){
        end = pos - 1; 
       reverse(str,begin,end);  
        begin = pos+1; //for the next word
    }

    pos++;

}   

cout<<str;
return 0;
}
1 голос
/ 12 марта 2013
int main()
{

    char sent[50],last,s;
    int i,j,length,k,temp,b;
    clrscr();
    i=0;
    printf("Enter a sentence: ");
    sent[i]=getchar();
    while(sent[i]!='\n'&&sent[i]!='.'&&sent[i]!='?'&&sent[i]!='!')
    {
        sent[++i]=getchar();
    }
    last=sent[i];//storing last char
    b=i; //length of string
    printf("Reverse of sentence: ");
    for(;;)
    {
        k=b-1;// begin from last position
        temp=k;
        while(sent[k]!=' ' && k!=-1)
        k--;
        s=k;//storing space here
        b=s;
        for(j=b+1;j<=temp;j++)
        putchar(sent[j]);
        if(s!=-1)
        putchar(sent[s]);
        if(b==-1)
        break;
    }
    putchar(last);
    getch();
    return 0;
}
0 голосов
/ 05 августа 2016

Ответы до сих пор предоставили альтернативные алгоритмы, которые можно отсортировать по двум классам:

  1. полностью изменить предложение и полностью изменить все слова в нем. Некоторые версии сначала меняют слова, в то время как другие сначала меняют предложение; порядок применения этих разворотов не имеет значения. Чистый эффект состоит в том, что слова появляются в обратном порядке, но символы в каждом слове находятся в их обычном порядке.
  2. Поместите слова в стек, затем снова извлеките их из стека, чтобы последнее слово стало первым.

Вместо того, чтобы предлагать еще один альтернативный алгоритм (который, вероятно, подпадает под одну из двух вышеупомянутых категорий), я объясню, почему код в исходном вопросе не работает должным образом.

Во-первых, обратите внимание, что код в вопросе на самом деле является вариантом класса 1. Сначала он полностью переворачивает предложение, а затем переворачивает каждое слово:

/* Outer loop goes backwards through the array, effectively reversing the sentence */
for(i = 99; i >= 0; i--) {

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

        /* Inner loop goes forward, reversing the word again */
        while(sentence[i + j] != ' ') {

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

        j = 1;
        printf(" ");
    }
}

Помимо некоторых ошибок новичка, это на самом деле оптимальный способ перевернуть слова предложения. Он не использует никакой дополнительной памяти и не тратит время.

Аскер отметил, что алгоритм работает так, как задумано, за исключением того, что он не печатает первое слово исходного предложения (которое должно стать последним словом). Причина этого в том, что обход массива останавливается на ' ' в обоих направлениях. Когда внешний цикл достигает начала предложения, он не находит пробела, потому что первый символ пользовательского ввода перезаписывает пробел в sentence[0]:

/* ... */
char sentence[100] = { ' ' }, c, tc;

/* ... */
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 */
}

Следовательно, когда i становится 0 во внешнем цикле, пробела нет, и внутренний цикл, который должен печатать слово, начинающееся с sentence[0], никогда не вводится. i затем уменьшается до -1 и внешний цикл завершается.

Вы можете проверить это без изменения кода, просто запустив программу от имени пользователя. Если вы введете пробел в качестве первого символа, ответ программы будет правильным:

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

Существует два способа принудительного включения первого слова в ваш код. Первый - просто всегда ставить пробел в начале массива sentence. Вы можете сделать это, начав копировать пользовательский ввод с i = 1 вместо i = 0:

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

Другой, немного менее элегантный способ - просто повторить внутренний цикл после завершения внешнего цикла:

/**
 * 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 */
    }
}

/* print the last word */
while(sentence[i + j] != ' ') {

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

Вы можете сделать это менее повторяющимся, выделив внутренний цикл для новой функции. Вот весь алгоритм с внутренним циклом, выделенным для функции print_word, пропуская комментарии и пустые строки:

#include<stdio.h>

void print_word(char[] sentence, int i) {
    int j = 1;
    while(sentence[i + j] != ' ') {
        printf("%c", sentence[i + j]);
        j++;
    }
}

int main(void) {
    char sentence[100] = { ' ' }, c, tc;
    int i = 0, j = 1, size = 0;
    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 */
    for(i = 99; i >= 0; i--) {
        if(sentence[i] == ' ') {
            print_word(sentence, i);
            printf(" "); /* Print a tailing space */
        }
    }
    print_word(sentence, i);
    printf("\b%c\n", tc);
    return 0; /* Return 0 upon successful program execution */
}

В качестве последнего замечания, есть еще одна вещь, которую вы могли бы сделать лучше. Прямо сейчас внешний цикл начинается с i = 99, последнего возможного символа в массиве sentence. Однако, читая пользовательский ввод, вы обновили i, чтобы указывать на следующую позицию ввода, поэтому непосредственно перед началом внешнего цикла i уже указывает на первый символ после предложения. Почему бы не использовать это и просто начать с i - 1?

0 голосов
/ 04 августа 2016

Следующий код помещает слова в стек, а затем считывает стек в обратном направлении, как Quonux намекнул на .

#include <stdlib.h>

int main()
{
char s[20][20];
int i=0,length=-1;
for(i=0;;i++)
{
    scanf("%s",s[i]);
    length++;
    if(getchar()=='\n')
        break;
}
for(i=length;i>=0;i--)
    printf("%s ",s[i]);
return 0;
}
0 голосов
/ 03 апреля 2014

Обратные слова в строке (слова разделяются одним или несколькими пробелами) - эту проблему можно решить различными способами, лишь немногие решения, которые я видел до сих пор, используют дополнительную память. Идея состоит в том, чтобы получить оптимальное решение, например, без использования дополнительной памяти (на месте) с временной сложностью O (N).

Итак, давайте возьмем пример, допустим, что строка «Hello World» - и ожидаемая O / P «World Hello»

  • Сначала мы просто полностью перевернем предложение IN PLACE , например, "dlroW olleH" (мы использовали операцию XOR для замены. Пожалуйста, посмотрите на метод Swap ())
  • Теперь мы увеличиваем индекс и останавливаемся, когда встречаемся. «(Пробел).
  • Как только мы сталкиваемся с любым пространством, мы знаем, что у нас есть слово. Давайте ссылаться обратная функция в этом слове и обратное слово. Так в этом на случай, если это будет похоже на "World olleH"
  • Теперь мы идем дальше и останавливаемся, когда наш индекс достигает длины предложение.
  • Как только мы достигнем конца, возьмем последний индекс -1 и повернем последний словом, так оно и будет похоже на "World Hello"

Здесь важно отметить один важный момент: когда мы вызываем функцию реверса для обращения слова назад, мы должны указать начальный и конечный индексы этого конкретного слова в соответствующем предложении.

Пример кода будет выглядеть так, как указано ниже. Я не проверял крайние случаи - но это даст основную идею подхода.

</p> <pre><code> using System; namespace SampleString { class ReverseWordsInSetence { // Reverse words in a string (words are separated by one or more spaces). private static String GetReverseWordsInSetence(string sentence) { char[] stringArray = sentence.ToCharArray(); int len = sentence.Length; int startIndex = 0; Swap(ref stringArray, ref startIndex , len-1); startIndex = 0; for (int currentIndex = 0; currentIndex < len; currentIndex++) { if (stringArray[currentIndex].Equals(' ')) { Swap(ref stringArray, ref startIndex, currentIndex-1); } else if (currentIndex == len - 1) { Swap(ref stringArray, ref startIndex, currentIndex); } } return new string(stringArray); } private static void Swap(ref char[] a, ref int i, int j) { int tempIndex = j; while (i < j) { if (a[j].Equals('.')) { j--; } else { a[i] ^= a[j]; a[j] ^= a[i]; a[i++] ^= a[j--]; } } i = tempIndex + 2; } static void Main(string[] args) { Console.WriteLine(GetReverseWordsInSetence("Hello World.")); Console.ReadLine(); } } }

0 голосов
/ 24 декабря 2013

Вот мой ответ

/ * написать программу, которая переворачивает слова в предложении:

Введите предложение: вы можете посадить ласточку в клетку, не так ли?

Отмена предложения: вы не можете проглотить клетку, не так ли?

Подсказка: используйте цикл, чтобы читать символы по одному и сохранять их в одномерном массиве символов.

Остановите цикл в точке, вопросительном знаке или восклицательном знаке - («завершающий символ»), который сохраняется как отдельная переменная символа.

Затем используйте второй цикл для поиска в обратном направлении черезмассив для начала последнего слова.

Распечатайте последнее слово, затем ищите в обратном направлении, следуя за последним словом.Повторяйте до тех пор, пока не будет окончательно достигнуто начало массива.

Наконец напечатайте завершающий символ.

*/
#include<stdio.h>

int main()
{
int ch;
char sentence[200]; //hard set a limit of 200 character sentence
char word[10] = {'\0','\0','\0','\0','\0','\0','\0','\0','\0'}; //hard set limit of 10 character words
int i = 0; //character position in input
int w = 9; //character position in word
char terminator = '\0';
printf("Enter a sentence:");
   while  ( (ch=getchar()) != '\n' )
       {
       if ( ch == '.' || ch == '?' || ch == '!')
          terminator = ch;
       else
         {
         sentence[i] = ch;
         i++;
         }
//       printf("%d",i);
       }
       sentence[i] = '\0';//set last character to null


    int x;
    for ( x=i ; x >= 0 ; x-- )
        {
           if ( sentence[x] == ' ' )
           {
            printf(" ");//print the space followed by what is in the word buffer/array
//          printf("word length %d ",w);
            printf("%c",word[0]); //probably should have a for loop here
            printf("%c",word[1]);
            printf("%c",word[2]);
            printf("%c",word[3]);
            printf("%c",word[4]);
            printf("%c",word[5]);
            printf("%c",word[6]);
            printf("%c",word[7]);
            printf("%c",word[8]);
            printf("%c",word[9]);
            w = 9 ;
            word[0] = '\0'; //fill the word buffer/array with null
            word[1] = '\0';
            word[2] = '\0';
            word[3] = '\0';
            word[4] = '\0';
            word[5] = '\0';
            word[6] = '\0';
            word[7] = '\0';
            word[8] = '\0';
            word[9] = '\0';
//          printf("\n");
//          printf("sentence position %d ",x);
           }
           else //assign the letters from sentence[] to letters in word[]
           {
            word[w] = sentence[x];
            w--;
//          printf("word length %d ",w);
//          printf("%c",sentence[x]);
           }
         }
//print the first word because im using space to delimit the words unless i have a space at the
//beginning of the sentence the code above will skip the first word inputed
    printf(" ");//print the space followed by what is in the word buffer/array
    printf("%c",word[0]);
    printf("%c",word[1]);
    printf("%c",word[2]);
    printf("%c",word[3]);
    printf("%c",word[4]);
    printf("%c",word[5]);
    printf("%c",word[6]);
    printf("%c",word[7]);
    printf("%c",word[8]);
    printf("%c",word[9]);



if ( terminator != '\0' ) //prints a . ? or ! if it is including in the inputed sentence
    printf("%c",terminator);

    printf("\n");
    printf("\n");
return 0;
0 голосов
/ 18 июля 2010

Я не пробовал. надеюсь, будет полезно для вас.

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...