Как выполнить изменение предложения слово за словом в C? - PullRequest
1 голос
/ 09 марта 2012
#include <stdio.h>

int main(void)
{
  int i,j;
  int wordstart = -1;
  int wordend = -1;
  char words[]= "this is a test";
  char temp;

  // Reverse each word
  for (i = 0; i < strlen(words); ++i)
  {
    wordstart = -1;
    wordend = -1;
    if(words[i] != ' ') 
      wordstart = i;
    for (j = wordstart; j < strlen(words); ++j)
    {
      if(words[j] == ' ')
      {
        wordend = j - 1;
        break;
      }
    }
    if(wordend == -1)
      wordend = strlen(words);
    for (j = wordstart ; j <= (wordend - wordstart) / 2; ++j)
    {
      temp = words[j];
      words[j] = words[wordend - (j - wordstart)];
      words[wordend - (j - wordstart)] = temp;
    }
    i = wordend;
    printf("reversed string is %s:", words);
  }
}

Я пытался таким образом, но я получаю этот вывод:
siht is a test
мой ожидаемый результат:
test a is this

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

Ответы [ 12 ]

0 голосов
/ 09 марта 2012

Я бы использовал функцию записи, аналогичную strrchr , для нахождения последнего вхождения ' ', если его найденное слово для печати следует, перепишите это ' ' с помощью '\0' и повторяйте его в цикле, пока нет больше слов найдено. В конце я снова напечатал бы содержимое этой строки, потому что, скорее всего, нет ' ' перед первым словом.

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

Вот код:

char* findLastWord(char* str, int* len)
{
    int i;
    for (i = *len - 1; i >= 0; --i)
    {
        if (str[i] == ' ')
        {
            str[i] = '\0';
            if (i < *len - 1)
            {
                *len = i - 1;
                return &str[i + 1];
            }
        }
    }
    return NULL;
}

int main (int argc, char *argv[])
{
    char str[] = " one two three  four five six ";
    int len = strlen(str);

    char* lastWord = findLastWord(str, &len);
    while (lastWord != NULL)
    {
        printf("%s\n", lastWord);
        lastWord = findLastWord(str, &len);
    }
    if (len > 1)
        printf("%s\n", str);
    return 0;
}

выход:

six
five
four
three
two
one

Надеюсь, это поможет;)

0 голосов
/ 09 марта 2012

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

При сканировании может потребоваться пропустить символы пробела.

ОБНОВЛЕНИЕ

Это быстрая реализация:

#include <stdio.h>
#include <ctype.h>
#include <string.h>

#define MAX_BUF 256

void show_string (char *str, int i, int n)
{
  while (i <= n)
  {
    printf ("%c", str[i]);
    i++;
  }
}

int main (void)
{
  char str[MAX_BUF];
  int end_anchor, start_ptr;
  int state;

  printf ("\nEnter a string: ");
  scanf (" %[^\n]", str);

  start_ptr = strlen (str) - 1;

  end_anchor = start_ptr;
  state = 0;
  while (start_ptr >= -1)
  {
    switch (state)
    {
      case 0:
             if ((!isspace (str[start_ptr]) && (start_ptr >= 0)))
             {
               start_ptr--;
             }
             else
             {
               state = 1;
             }
             break;

      case 1:
             show_string (str, start_ptr + 1, end_anchor);
             state = 2;
             start_ptr--;
             printf (" ");
             break;

      case 2:
             if (!isspace (str[start_ptr]))
             {
               state = 0;
               end_anchor = start_ptr;
             }
             else
             {
               start_ptr--;
             }
             break;
    }
  }


  printf ("\n");
  return 0;
}

end_anchor указывает на каждое конечное слово, а start_ptr находит начало слова, конец которого содержится в end_anchor.Когда мы находим слово начало (по пробелам или start_ptr = -1), мы печатаем все символы от start_ptr + 1 до end_anchor.+ 1 обусловлен реализацией: start_ptr указывает на символ пробела, а процедура печати будет печатать все символы от i до n.После того, как мы обнаружили одно пустое пространство, мы печатаем его и пропускаем соседние пробелы (в case 2) и сохраняем только одно, которое печатается вручную.Как только не пропущено пробел, у нас есть другое слово end, для которого мы устанавливаем end_anchor для этого индекса в case 2 и устанавливаем state = 0, чтобы мы могли искать слово start снова.

...