Reversing words in a sentence
我目前正在学习K.N.King的C编程:一种现代的方法。我已经通过了第八章(数组)的课文,我很想继续到第九章,但是我还没有在每一章结束时解决所谓的"编程项目"。不幸的是,第14…让我讨厌。
Write a program that reverses the words in a sentence.
号
1 2 | 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.
号
我一直在考虑将一个单词定义为空格之间的字符序列。因此,当到达一个空格时,后退一步,打印每个字符,直到找到另一个空格。我的程序的第一个版本只打印了第一个字。它的当前版本只打印其他单词。我在这个问题上坚持了两天,所以任何帮助都是非常感谢的。这是我的代码,还有一个输出示例。希望我已经正确地记录了我的代码。事先谢谢!
代码1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | /* 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: "); for(c = getchar(); (c != '.') && (c != '!') && (c != '?') && (c != ' '); 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 ", tc); return 0; /* Return 0 upon successful program execution */ } |
号输出:
http://drp.ly/1nyt5j
将每个字压入堆栈并从索引0读取堆栈到n-1
另一种思考方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 | man strcspn |
号
下面是一个例子,可以实现我提到的功能。首先,在适当的位置反转每个单词,然后反转整个字符串。这里有一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
下面是一个带有一个小示例程序的用例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
。
用法示例:
1 2 | $ ./example"the quick red fox jumps over the lazy brown dog" dog brown lazy the over jumps fox red quick the |
将输入作为字符数组,然后反转整个数组。在此之后,逐字逆序,在"",?"处将句子拆分为单词。"0"等。希望这有帮助。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 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]!=' '&&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; } |
。
到目前为止,答案提供了替代算法,可分为两类:
我将解释为什么原始问题中的代码不能按预期工作,而不是建议另一种算法(可能属于上述两个类别之一)。
首先,注意问题中的代码实际上是类1的变体。它首先颠倒整个句子,然后颠倒每个单词:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
除了一些初学者的错误外,这实际上是一个颠倒句子的最佳方法。它不需要额外的内存,也不浪费时间。
提问者指出,该算法按预期工作,只是它没有打印原句子的第一个单词(应该是最后一个单词)。原因是数组遍历在两个方向的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /* ... */ char sentence[100] = { ' ' }, c, tc; /* ... */ int i = 0, j = 1, size = 0; /* Get the sentence */ printf("Enter a sentence: "); for(c = getchar(); (c != '.') && (c != '!') && (c != '?') && (c != ' '); c = getchar(), i++) { sentence[i] = c; /* Store the current character in the array */ size++; /* Increase the sentence's size */ } |
号
因此,当
通过简单地以用户身份运行程序,您可以在不更改代码的情况下对此进行测试。如果输入空格作为第一个字符,程序的响应将正确:
1 2 3 | Enter a sentence: you can cage a swallow can't you? you can't swallow a cage can you? |
有两种方法可以强制在代码中包含第一个单词。第一种方法就是始终在
1 2 3 4 5 | /** * 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; |
。
另一种稍微不那么优雅的方法是在外部循环终止后简单地重复内部循环:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | /** * 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++; } |
通过将内部循环分解为一个新函数,可以减少重复性。下面是整个算法,将内部循环分解为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #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: "); for(c = getchar(); (c != '.') && (c != '!') && (c != '?') && (c != ' '); 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 ", tc); return 0; /* Return 0 upon successful program execution */ } |
。
最后一句话,还有一件事你可以做得更好。现在,外部循环从
下面的代码将单词推到堆栈上,然后像Quonux暗示的那样向后读取堆栈。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
。
在一个字符串中反转单词(单词由一个或多个空格分隔)-这个问题可以用不同的方式处理,到目前为止,我看到的解决方案很少使用额外的内存。其思想是获得最佳的解决方案,比如不使用具有时间复杂性的额外内存(就地)解决方案O(n)。
那么让我们举个例子,假设字符串是"hello world",并期望O/P是"world hello"
- 首先,我们将在适当的位置反转整个句子,比如"dlrow olleh"(我们使用了xor操作进行交换)。请看swap()方法)
- 现在,我们增加索引,当我们遇到'(空格)。
- 一旦我们遇到任何空间,我们就知道我们有话要说。让我们调用这个词的倒转功能和那个词的倒转功能。所以在那一点上如果是这样的话,"世界奥利"
- 现在我们走得更远,当我们的指数达到句子。
- 一旦到达末尾,抓取最后一个索引-1并反转最后一个索引一句话,就好像"世界你好"
这里需要注意的一点是,当我们调用reverse函数来反转单词时,我们需要在相应的句子中提供该特定单词的起始索引和结束索引。
示例代码如下所述。我还没有用边缘案例进行测试——但它将提供方法的基本概念。
江户十一〔一〕号
这是我的答案
/*编写一个程序来颠倒句子中的单词:
输入一句话:你能把燕子关在笼子里,是吗?
反句:你不能吞下笼子,是吗?
提示:使用循环逐个读取字符,并将它们存储在一维char数组中。
将循环停止在句点、问号或感叹号处--(终止字符),另存为单独的char变量。
然后使用第二个循环在数组中向后搜索最后一个单词的开头。
打印最后一个单词,然后向后搜索下一个到最后一个单词。重复,直到最后到达数组的开头。
最后打印终止字符。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | */ #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()) != ' ' ) { 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(" "); // 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(" "); printf(" "); return 0; |
我没试过。希望对你有帮助。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
。