简体   繁体   English

如何在C中逐字翻译句子?

[英]how to perform reversing a sentence Word by Word in C?

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

I tried in this way but i am getting this output: 我试过这种方式,但我得到这个输出:
siht is a test
my expected output is: 我的预期输出是:
test a is this

I would appreciate if some one could come with a different approach for which time complexity is very less or correct me if it is the right approach. 如果有人采用不同的方法,时间复杂度非常低,或者如果这是正确的方法,那么我会很感激。 Thanks 谢谢

Simply we can just use an*1 2D character array tailored to suit our needs!!! 我们只需使用适合我们需求的* 1 2D字符阵列!

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

You can create a double linked list as a base data structure. 您可以创建双链表作为基础数据结构。 Then, iterate through the words and insert them in the list as you find them. 然后,迭代单词并在找到它们时将它们插入列表中。

When you reach the end of the sentence, simply traverse the list backwards and print the words as you go through them 当您到达句子的末尾时,只需向后遍历列表并在您浏览时打印单词

Perhaps this belongs on the code review site instead? 也许这属于代码审查网站而不是?

Your approach seems very efficient to me (except that I would only call strlen(words) once and save the result in a register). 你的方法对我来说似乎非常有效(除了我只调用strlen(单词)一次并将结果保存在寄存器中)。

Two possible bugs look like: 两个可能的错误看起来像:

wordend = strlen(words);

should be 应该

wordend = strlen(words)-1;

and

for(j = wordstart ; j <= (wordend - wordstart) / 2 ; ++j) {

should be 应该

for(j = wordstart ; j <= (wordend + wordstart) / 2 ; ++j) {

Final code looks like (with some extra {}): 最终代码看起来像(有一些额外的{}):

    #include <stdio.h>
    int main(int argc,char *argv[])
    {
        int i,j;
        char words[]= "this is a test";
        int L=strlen(words);

        // Reverse each word
        for(i = 0; i < L; ++i) {
          int wordstart = -1;
          int wordend = -1;
          if(words[i] != ' ') 
          {
            wordstart = i;

            for(j = wordstart; j < L; ++j) {
              if(words[j] == ' ') {
                wordend = j - 1;
                break;
              }
            }
            if(wordend == -1)
              wordend = L-1;
            for(j = wordstart ; j <= (wordend + wordstart) / 2 ; ++j) {
              char temp = words[j];
              words[j] = words[wordend - (j - wordstart)];
              words[wordend - (j - wordstart)] = temp;
            }
            i = wordend;
          }
        }
        printf("reversed string is %s:",words);
        return 0;   
    }
 #include <iostream>
 #include <string>   
  using namespace std;
  char* stringrev(char s[], int len)
  {
    char *s1 = (char*)malloc(len+1);
    int i=0;
    while (len>0)
    {
      s1[i++] = s[--len];
    }
   s1[i++] = '\0';
    return s1;   
  }

   void sentrev(char s[], int len)
 {
    int i=0; int j=0;
     char *r = (char*)malloc(len+1);
     while(1)
     {
     if(s[j] == ' ' || s[j] == '\0')
     {
       r = stringrev(s+i, j-i);
       i = j+1;
       cout<<r<<" ";
     }
    if (s[j] == '\0')
    break;
    j++;
   }

 }


int main()
{
char *s = "this is a test";
char *r = NULL;
int len = strlen(s);
cout<<len<<endl;
r = stringrev(s, len);
cout<<r<<endl;
sentrev(r, len);
return 0;
}

The above code snap reverse the sentence, using char *r and printing cout< 上面的代码使用char * r和打印cout <来快速反转句子

#include<stdio.h>
#include<conio.h>
#include<string.h>
int main()
{
char st[50], rst[50];
printf("Enter the sentence...\n");
gets(st);
int len=strlen(st), p;
int j=-1,k;
p=len;
for(int i=(len-1); i>=0; i--)
{
    //searching for space or beginning
    if(st[i]==' ')
    {
        //reversing and storing each word except the first word
        for(k=i+1;k<p;k++)
        {
            //printf("%c",st[k]);
            rst[++j]=st[k];
        }
        j++;
        rst[j]=' ';
        printf("\n");
        p=i;
    }
    else if(i==0)
    {
        //for first word
        for(k=i;k<p;k++)
        {
            //printf("%c",st[k]);
            rst[++j]=st[k];
        }
    }

}
printf("Now reversing the sentence...\n");
puts(rst);
return 0;
}

Use a main for loop to traverse till the end of the sentence: Copy the letters in a string until you find a space. 使用main for循环遍历到句子的结尾:复制字符串中的字母,直到找到空格。 now call add@beginning function and in that function add the string each time you pass a string to the linked list. 现在调用add@beginning函数,并在每次将字符串传递给链表时添加字符串。 print the contents of the linked list with a space inbetween to get the expected output 打印链表的内容,其间有空格以获得预期的输出

My code,just traverse from the last and if you find a space print the characters before it,now change the end to space-1;This will print till the second word,finally just print the first word using a single for loop.Comment for alter approach. 我的代码,只是从最后一个遍历,如果你发现空格打印前面的字符,现在将结束更改为空格-1;这将打印到第二个单词,最后只使用单个for循环打印第一个单词。改变方法。

Program: 程序:

#include<stdio.h>
int main()
{
 char str[200];
int i,j,k;
scanf("%[^\n]s",&str);
for(i=0;str[i]!='\0';i++);
i=i-1;
for(j=i;j>=0;j--)
{
    if((str[j])==' ')
    {
        for(k=j+1;k<=i;k++)
        {
            printf("%c",str[k]);
        }
        i=j-1;
        printf(" ");
    }

}
for(k=0;k<=i;k++)
{
    printf("%c",str[k]);
}
}
using stack 

#include <iostream>  
#include <stdio.h>
#include <stack>

int main()
{ 

    std::stack<string> st;
    char *words= "this is a test";
    char * temp =   (char *)calloc(1, sizeof(*temp));
    int size1= strlen(words);
    int k2=0;
    int k3=0;
    for(int i=0;i<=size1;i++)
    {
       temp[k2] = words[i];
       k2++;
        if(words[i] == ' ')     
        {  
            k3++;
            if(k3==1)
                temp[k2-1]='\0';

            temp[k2]='\0';
            st.push(temp);
            k2=0;           
        }
        if(words[i] == '\0')
        {
            temp[k2]='\0';
            st.push(temp);
            k2=0;
            break;
        }               
    }

  while (!st.empty())
  {
       printf("%s",st.top().c_str());
        st.pop();
  }

Start tokenizing the line from the last character and continue to the first character. 开始标记最后一个字符的行并继续第一个字符。 Keep one pointer anchored at the base of the current word, and another pointed which will decrease while a word start is not found. 保持一个指针锚定在当前单词的基础上,另一个指针指向,当找不到单词start时将减少。 When you find a word start while scanning like this, print from the word start pointer to the word end anchor. 当你在这样的扫描中发现一个单词开始时,从单词开始指针打印到单词结束锚点。 Update the word end anchor to the previous character of the current word start char. 将单词结束锚更新为当前单词start char的前一个字符。

You might want to skip the blankspace characters while scanning. 您可能希望在扫描时跳过空白字符。

UPDATE UPDATE

This is a quick implementation: 这是一个快速实现:

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

The end_anchor points to each end word, and the start_ptr finds the start of the word of which the end is held by end_anchor . end_anchor指向每个结束字, start_ptr查找end_anchor持有结尾的单词的end_anchor When we find a word start (by blankspace characters or start_ptr = -1), we print all the characters from start_ptr + 1 to end_anchor . 当我们找到一个单词start(通过blankspace字符或start_ptr = -1)时,我们打印从start_ptr + 1end_anchor所有字符。 The + 1 is because of the implementation: start_ptr points to the blankspace character, and the print routine will print all the characters from i to n . + 1是因为实现: start_ptr指向空白字符,打印例程将打印从in所有字符。 Once we have detected one blank space we print it and we skip adjacent blankspaces (in case 2 ) and preserve only one which is manually printed. 一旦我们检测到一个空白区域,我们将其打印出来并跳过相邻的空白区域(在case 2 ),并且只保留一个手动打印的空白区域。 Once a non blankspace is detected, we have got another word end, for which we set the end_anchor to this index in the case 2 , and set state = 0 , so that we can search for the word start again. 一旦检测到非空白空间,我们就会得到另一个单词结束,为此我们将end_anchor设置为case 2中的该索引,并设置state = 0 ,以便我们可以再次搜索单词start。

I would use write function similar to strrchr for finding last occurence of ' ' , if its found print word that follows, rewrite this ' ' with '\\0' and repeat it in loop till no more words are found. 我会使用类似于strrchr的写函数来查找' '最后一次出现,如果找到后面的打印字,用'\\0'重写这个' ' '\\0'并在循环中重复它直到找不到更多的单词。 At the end I would print the content of this string again because there is most likely no ' ' before the first word. 最后我会再次打印这个字符串的内容,因为在第一个单词之前很可能没有' '

I would write own function instead of strrchr because strrchr calculates the lenght of the given string, which is redundant in this case. 我会编写自己的函数而不是strrchr,因为strrchr计算给定字符串的长度,在这种情况下这是多余的。 This length doesn't have to be calculated more than once. 该长度不必多次计算。

Here's the code: 这是代码:

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

output: 输出:

six
five
four
three
two
one

Hope this helps ;) 希望这可以帮助 ;)

if(words[i] != ' ') 
    wordstart = i;

This statement what about the else part? 这个说法怎么样呢? if words[i] == ' ', and wordstart remains -1. 如果单词[i] =='',则wordstart保持为-1。 So maybe try to use: 所以也许尝试使用:

while (words[i] && words[i] == ' ') ++i;
  if (!words[i])
      break;
wordstart = i;

Then you should output the result out of the i loop. 然后你应该从i循环中输出结果。 Finally, if you want to get the result you expected, you should reverse the whole sentence once more, with the way you used in the loop. 最后,如果你想得到你期望的结果,你应该再次用你在循环中使用的方式反转整个句子。

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

void reverse(char *str, size_t len)
{
    char tmp;
    size_t beg, end;
    if (len <=1) return;

    for (beg=0,end=len; beg < --end ; beg++) {
        tmp = str[beg];
        str[beg] = str[end];
        str[end] = tmp;
    }
}

int main(void)
{
    char sentence[] = "one two three four five";
    size_t pos, len;

    printf("Before:%s\n",sentence);
    for (pos = len= 0;  sentence[pos]; pos += len) {
        pos += strspn( sentence+pos, " \t\n" );
        len = strcspn( sentence+pos, " \t\n" );
        reverse ( sentence + pos, len );
        }
    reverse ( sentence , pos );

    printf("After:%s\n",sentence);

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM