C语言 倒置句子中的单词
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3276582/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Reversing words in a sentence
提问by XLR3204S
I'm currently going through K.N. King's C Programming: A Modern Approach. I've made it past the text for the 8th chapter (Arrays), and I'm eager to move on to chapter 9, but I've yet to solve the so-called "programming projects" at the end of each chapter. Unfortunately, the 14th... bugs me.
我目前正在阅读 KN King's C Programming: A Modern Approach。我已经完成了第 8 章(数组)的课文,我很想进入第 9 章,但我还没有解决每章末尾所谓的“编程项目”。不幸的是,第 14 次......让我感到厌烦。
Write a program that reverses the words in a sentence.
编写一个程序来反转句子中的单词。
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 chararray. Have the loop stop at a period, question mark, or exclamation point (the "terminating character "), which is saved in a separate charvariable. 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.
提示:使用循环一个一个地读取字符并将它们存储在一个一维字符数组中。让循环在句点、问号或感叹号(“终止字符”)处停止,它们保存在单独的char变量中。然后使用第二个循环在数组中向后搜索最后一个单词的开头。打印最后一个单词,然后向后搜索倒数第二个单词。重复直到到达数组的开头。最后,打印终止字符。
I've been thinking of defining a word as a sequence of characters between blank spaces. So when a space is reached, go backward, printing each character, until another space is found. My firstversion of the program only printed the first word. The currentversion of it only prints the other words. I've been stuck on this for two days, so any help is truly appreciated. Here is my code, as well as an output sample. Hopefully I've properly documented my code. Thanks in advance!
我一直在考虑将单词定义为空格之间的字符序列。因此,当到达一个空格时,向后移动,打印每个字符,直到找到另一个空格。我的程序的第一个版本只打印了第一个单词。它的当前版本只打印其他单词。我已经坚持了两天,所以任何帮助都非常感谢。这是我的代码,以及一个输出示例。希望我已经正确记录了我的代码。提前致谢!
Code
代码
/* 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 */
}
Output:
输出:
采纳答案by eruciform
Another methodology to think about:
另一种思考方法:
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?
^^^
For each thing you want to reverse (be it a whole sentence or a word):
对于您想要反转的每一件事(无论是一个完整的句子还是一个单词):
- Find the beginning and end
- Swap the beginning and end characters
- Move "inwards" once
- keep going until you reach "the middle"
- 寻找开始和结束
- 交换开始和结束字符
- “向内”移动一次
- 继续前进直到到达“中间”
Since reversing a chunk of a string is a common operation, it makes sense to make it its own function. And since the only information the function need to do its job is:
由于反转字符串的一个块是一种常见的操作,因此让它成为自己的功能是有意义的。由于该函数完成其工作所需的唯一信息是:
- the string
- the beginning index
- the ending index
- 字符串
- 起始索引
- 结束索引
What do you think the parameters for the function would be?
你认为函数的参数是什么?
The other common thing that needs to be done over and over is "finding" something, be it a space or a punctuation mark. You may need to write this yourself, or if you can use library functions, or want a hint, look up:
需要一遍又一遍地做的另一件事是“找到”某些东西,无论是空格还是标点符号。您可能需要自己编写,或者如果您可以使用库函数,或者需要提示,请查找:
man strcspn
回答by Quonux
push each word on a stack and read the stack from index 0 to N-1
将每个单词压入堆栈并从索引 0 到 N-1 读取堆栈
回答by Carl Norum
Here's an example that does what I mentioned. First, reverse each word in place, then reverse the entire string. Here is a reverse()function that reverses a string in place with a given delimiting character. You could extend to use multiple delimiters if you like.
这是一个执行我提到的操作的示例。首先,将每个单词原位反转,然后反转整个字符串。这是一个reverse()函数,它使用给定的分隔符将字符串原地反转。如果您愿意,您可以扩展为使用多个分隔符。
char *reverse(char *str, char delim)
{
char *end = strchr(str, delim);
char *ret;
char tmp;
if (end == NULL)
end = strchr(str, 'int main(int argc, char **argv)
{
char *end = strchr(argv[1], '$ ./example "the quick red fox jumps over the lazy brown dog"
dog brown lazy the over jumps fox red quick the
');
char *str = argv[1];
while (str < end)
str = reverse(str, ' ');
reverse(argv[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;
}
');
printf("%s\n", argv[1]);
return 0;
}
');
ret = end + 1;
end--;
while (end > str)
{
tmp = *str;
*str = *end;
*end = tmp;
end--;
str++;
}
return ret;
}
Here is a use case with a little example program:
这是一个带有小示例程序的用例:
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]=='#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;
}
')||(str[pos]=='?')||(str[pos]=='!')){
end = pos - 1;
reverse(str,begin,end);
begin = pos+1; //for the next word
}
pos++;
}
cout<<str;
return 0;
}
Usage example:
用法示例:
/* 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(" ");
}
}
回答by user2161315
/* ... */
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 */
}
回答by user3775831
By taking the input as character array and then reversing the whole array. Following this, reverse word by word where splitting of the sentence into words occur at " ","?","\0" etc. Hope this helps.
通过将输入作为字符数组,然后反转整个数组。在此之后,将句子拆分为单词发生在“”,“?”,“\0”等处,逐字反转。希望这会有所帮助。
Enter a sentence:
you can cage a swallow can't you?
you can't swallow a cage can you?
回答by Sriram Jayaraman
The following code pushes the words on a stack and then reads out the stack backwards, as Quonux hinted at.
以下代码将单词压入堆栈,然后向后读出堆栈,正如Quonux 所暗示的那样。
/**
* 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;
回答by Julian
The answers so far have contributed alternative algorithms, which can be sorted into two classes:
到目前为止的答案贡献了替代算法,可以分为两类:
- Reverse the entire sentence andreverse all the words in it. Some versions first reverse the words while others first reverse the sentence; the order in which these reversals are applied does not matter. The net effect is that the words appear in reverse order but the characters within each word are in their normal order.
- Put the words on a stack, then take them from the stack again so that the last word becomes the first.
- 反转整个句子并反转其中的所有单词。有些版本先颠倒单词,有些则先颠倒句子;应用这些逆转的顺序无关紧要。最终效果是单词以相反的顺序出现,但每个单词中的字符按正常顺序排列。
- 将单词放在堆栈上,然后再次从堆栈中取出它们,使最后一个单词成为第一个单词。
Rather than suggesting yet another alternative algorithm (which would probably fall in one of the above two categories), I will explain why the code in the original question does not work as intended.
与其建议另一种替代算法(可能属于上述两类之一),我将解释为什么原始问题中的代码无法按预期工作。
First, observe that the code in the question is actually a variant of class 1. It first reverses the entire sentence and then reverses each word:
首先观察题中的代码其实是class 1的变体,它先把整个句子倒序,然后再把每个单词倒序:
/**
* 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++;
}
Apart from some beginner mistakes, this is actually an optimal way to reverse the words of a sentence. It uses no additional memory and it does not waste time.
除了一些初学者的错误外,这实际上是颠倒句子单词的最佳方法。它不使用额外的内存,也不会浪费时间。
The asker noted that the algorithm works as intended, except that it does not print the first word of the original sentence (which should become the last word). The reason for this is that the array traversals stop on ' 'in both directions. When the outer loop reaches the start of the sentence, it finds no space, because the first character of the user input overwrites the space in sentence[0]:
提问者指出,该算法按预期工作,只是它不打印原始句子的第一个单词(应该成为最后一个单词)。这样做的原因是数组遍历' '在两个方向上都停止。当外循环到达句子的开头时,发现没有空格,因为用户输入的第一个字符覆盖了 中的空格sentence[0]:
#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 */
}
Hence, when ibecomes 0in the outer loop, there is no space, and the inner loop which should print the word starting at sentence[0]is never entered. ithen decrements to -1and the outer loop terminates.
因此,当外循环中的i变成时0,没有空格,并且sentence[0]永远不会进入应该打印从 at 开始的单词的内循环。i然后递减至-1外循环终止。
You can test this without changing the code by simply running the program as a user. If you enter a space as the first character, the response of the program will be correct:
您只需以用户身份运行程序即可测试,而无需更改代码。如果输入空格作为第一个字符,程序的响应将是正确的:
*/
#include<stdio.h>
int main()
{
int ch;
char sentence[200]; //hard set a limit of 200 character sentence
char word[10] = {' 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();
}
}
}
','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] = '##代码##';
printf("%s ",temp);
}
k = i;
}
}
printf("\b%c",tc);
','##代码##','##代码##','##代码##','##代码##','##代码##','##代码##'}; //hard set limit of 10 character words
int i = 0; //character position in input
int w = 9; //character position in word
char terminator = '##代码##';
printf("Enter a sentence:");
while ( (ch=getchar()) != '\n' )
{
if ( ch == '.' || ch == '?' || ch == '!')
terminator = ch;
else
{
sentence[i] = ch;
i++;
}
// printf("%d",i);
}
sentence[i] = '##代码##';//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] = '##代码##'; //fill the word buffer/array with null
word[1] = '##代码##';
word[2] = '##代码##';
word[3] = '##代码##';
word[4] = '##代码##';
word[5] = '##代码##';
word[6] = '##代码##';
word[7] = '##代码##';
word[8] = '##代码##';
word[9] = '##代码##';
// 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 != '##代码##' ) //prints a . ? or ! if it is including in the inputed sentence
printf("%c",terminator);
printf("\n");
printf("\n");
return 0;
There are two ways in which you can enforce the inclusion of the first word in your code. The first is to simply always put a space at the beginning of your sentencearray. You can do that by starting to copy the user input at i = 1instead of i = 0:
有两种方法可以强制在代码中包含第一个单词。第一个是简单地始终在sentence数组的开头放置一个空格。您可以通过开始复制用户输入来做到这一点,i = 1而不是i = 0:
Another, slightly less elegant way would be to simply repeat the inner loop after the outer loop terminates:
另一种不太优雅的方法是在外循环终止后简单地重复内循环:
##代码##You can make that less repetitive by factoring out the inner loop to a new function. Here's the entire algorithm with inner loop factored out to the print_wordfunction, skipping the comments and blank lines:
您可以通过将内部循环分解为新函数来减少重复。这是将内部循环分解为print_word函数的整个算法,跳过注释和空行:
As a final remark, there's one more thing that you could do better. Right now, the outer loop starts at i = 99, the last possible character in the sentencearray. However, while reading the user input you updated ito point to the next input position, so just before the start of the outer loop, iis already pointing to the first character after the sentence. Why not use that and simply start at i - 1?
最后,还有一件事可以做得更好。现在,外部循环从数组中i = 99最后一个可能的字符开始sentence。但是,在读取您更新i为指向下一个输入位置的用户输入时,就在外循环开始之前,i已经指向句子之后的第一个字符。为什么不使用它并简单地从 开始i - 1?
回答by seamus murray
Here is my answer
这是我的答案
/* write a program that reverses the words in a sentence:
/* 编写一个程序来反转句子中的单词:
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 as 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 finally reached.
打印最后一个单词,然后向后搜索倒数第二个单词。重复直到最终到达数组的开头。
Finally print the terminating character.
最后打印终止字符。
##代码##回答by vran freelancer
Reverse words in a string (words are separated by one or more spaces) - this problem can be handled various ways, few of the solutions i have seen so far use extra memory. The idea is to get the optimum solution, like without using extra memory (in place) solution with time complexity O(N).
字符串中的反向单词(单词由一个或多个空格分隔) - 这个问题可以通过多种方式处理,到目前为止我看到的解决方案很少使用额外的内存。这个想法是获得最佳解决方案,例如不使用时间复杂度为 O(N) 的额外内存(就地)解决方案。
So Let's take the example, lets say string is "Hello World" - and expected O/P "World Hello"
所以让我们举个例子,假设字符串是“Hello World” - 和预期的 O/P “World Hello”
- First we will just reverse the entire sentence IN PLACE, like "dlroW olleH" (We have used XOR operation for swapping. please have a look at Swap() method)
- Now we increase the index and stop when we come across ' '(space).
- Once we encounter any space, we know that we got a word. Let's invoke the reverse function on that word and Reverse that word. So in that case it will be like, "World olleH"
- Now we go further and stop when our index reach till the length of the sentence.
- Once we reach at end, grab the last index -1 and reverse the last word, so it will be like "World Hello"
- 首先,我们将整个句子IN PLACE反转,例如“dlroW olleH”(我们已经使用 XOR 操作进行交换。请查看 Swap() 方法)
- 现在我们增加索引并在遇到''(空格)时停止。
- 一旦我们遇到任何空间,我们就知道我们得到了一个词。让我们对该单词调用 reverse 函数并反转该单词。所以在那种情况下,它会像,“World olleH”
- 现在我们更进一步,当我们的索引达到句子的长度时停止。
- 一旦我们到达末尾,抓住最后一个索引 -1 并反转最后一个单词,所以它会像“World Hello”
One important point to note here, when we invoke the Reverse Function to reverse the word, we will be required to provide the starting index and the ending index of that particular word in respective sentence.
这里需要注意的一个重点是,当我们调用 Reverse 函数来反转单词时,我们将需要在相应的句子中提供该特定单词的起始索引和结束索引。
The sample code would look like as mentioned below. I haven't tested with edge cases - but it will provide basic idea of approach.
示例代码如下所述。我还没有测试过边缘情况 - 但它会提供基本的方法思想。
##代码##
##代码##
回答by Sadat
I havent tried it. hope would be helpful to u.
我没试过。希望对你有帮助。
##代码##
