翻译句子中的单词

我目前正在通过KN King的C编程:现代方法 。 我已经超过了第8章(Arrays)的文本,我很想继续学习第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 /* 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

另一种思考方法:

 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. 继续前进,直到你到达“中间”

由于反转字符串的块是一种常见的操作,因此将其作为自己的函数是有意义的。 由于该function需要完成其工作的唯一信息是:

  1. 字符串
  2. 起始指数
  3. 结束指数

您认为该function的参数是什么?

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

 man strcspn 

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

这是我提到的一个例子。 首先,将每个单词反转到位,然后反转整个字符串。 这是一个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 
 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”等等。希望这会有所帮助。

  void reverse(char s[],int start,int stop){ char t; while(start 

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

 char temp[100]; int j=0, k=100, l=0; for(i=size-1; i>=0; i--){ if(sentence[i] == ' ' || i == 0){ if(ki >= 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); 

这是我的答案

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

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

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

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

让循环停止在一个句点,问号或感叹号 – (“终止字符”),它被保存为一个单独的char变量。

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

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

最后打印终止字符。

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

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

    下面的代码推送堆栈上的单词,然后向后读出堆栈,正如Quonux暗示的那样 。

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

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

    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 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开始?