翻译句子中的单词

时间:2010-07-18 17:50:36

标签: c arrays

我目前正在通过K.N. King的 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 个答案:

答案 0 :(得分:5)

将每个字推入堆栈并从索引0读取堆栈到N-1

答案 1 :(得分:3)

另一种思考方法:

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. 一直走到“中间”
  5. 由于反转字符串的块是一种常见操作,因此将其作为自己的函数是有意义的。由于该功能需要完成其工作的唯一信息是:

    1. 字符串
    2. 开头索引
    3. 结束指数
    4. 您认为该功能的参数是什么?

      需要反复做的另一件常见事情是“找到”某些东西,无论是空格还是标点符号。您可能需要自己编写,或者如果您可以使用库函数,或想要提示,请查找:

      man strcspn
      

答案 2 :(得分:2)

以下是我提到的一个例子。首先,将每个单词反转到位,然后反转整个字符串。这是一个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

答案 3 :(得分:1)

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

答案 4 :(得分:1)

将输入作为字符数组,然后反转整个数组。 在此之后,逐字翻转,将句子分成单词出现在“”,“?”,“\ 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;
}

答案 5 :(得分:0)

我还没试过。希望对你有所帮助。

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

答案 6 :(得分:0)

这是我的回答

/ *编写一个程序来反转句子中的单词:

输入一句话:你可以笼下燕子吗?

逆转:你不能吞下一个笼子吗?

提示:使用循环逐个读取字符并将它们存储在一维char数组中。

让循环停止在句号,问号或感叹号上 - (“终止字符”),保存为单独的char变量。

然后使用第二个循环在数组中向后搜索最后一个单词的开头。

打印最后一个单词,然后向后搜索下一个单词。 重复,直到最终到达数组的开头。

最后打印终止字符。

*/
#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;

答案 7 :(得分:0)

字符串中的反向字(单词由一个或多个空格分隔) - 这个问题可以通过各种方式处理,到目前为止我看到的解决方案中很少使用额外的内存。我们的想法是获得最佳解决方案,例如不使用时间复杂度为O(N)的额外内存(就地)解决方案。

所以让我们举个例子,让我们说字符串是“Hello World” - 并期待O / P“World Hello”

  • 首先我们将反转整个句子 IN PLACE ,例如“dlroW olleH”(我们使用XOR操作进行交换。请查看Swap()方法)
  • 现在我们增加指数并在遇到时停止' “(空格)。
  • 一旦我们遇到任何空间,我们就知道我们得到了一个字。我们来调用 该单词的反向函数和反转该单词。那就是那个 案例就像是“World olleH”
  • 现在我们进一步停下来,当我们的指数达到时长 句子。
  • 一旦我们到达终点,抓住最后一个索引-1并反转最后一个 这个词,所以就像“世界你好”

这里要注意的一点是,当我们调用反向函数来反转单词时,我们将需要在相应的句子中提供该特定单词的起始索引和结束索引。

示例代码如下所示。我没有测试边缘情况 - 但它将提供方法的基本概念。

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

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

答案 8 :(得分:0)

以下代码推送堆栈上的单词,然后向后读出堆栈,如Quonux hinted at

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

答案 9 :(得分:0)

到目前为止,答案已经提供了替代算法,可以分为两类:

  1. 反转整个句子反转其中的所有字词。有些版本首先反转单词,而其他版本首先反转句子;这些逆转的顺序无关紧要。实际效果是单词以相反的顺序出现,但每个单词中的字符都按正常顺序排列。
  2. 将单词放在堆栈上,然后再将它们从堆栈中取出,以便最后一个单词成为第一个单词。
  3. 我会解释为什么原始问题中的代码不能按预期工作,而不是建议另一种替代算法(可能属于上述两种类别之一)。

    首先,观察问题中的代码实际上是第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开始?