【问题标题】:Reverse a sentence in C?在C中反转一个句子?
【发布时间】:2009-07-03 18:44:59
【问题描述】:

我刚刚编写了一个程序,它可以反转用户给出的任何句子。例如:如果用户输入“你好吗”,我的程序会生成“uoy era woH”。

我编写的程序如下所示。我只是有一种疯狂的直觉,认为可以有比这更智能的程序。非常感谢您提供的宝贵意见,或者任何比这更好的程序也很受欢迎。

int ReverseString(char *);
main() {
  char *Str;
  printf("enter any string\n");
  gets(Str);
  ReverseString(Str);
  getch();
}
int ReverseString(char *rev) {
  int len = 0;
  char p;
  while(*rev!='\0') {
    len++;
    rev++;
  }
  rev--;
  while(len>0) {
    p = *rev;
    putchar(p);
    rev--;
    len--;
  }
}

非常感谢。

【问题讨论】:

  • 你能说得清楚一点吗??
  • @GNR 你在学习哪本 C 教科书?学习如何将字符串读入缓冲区应该是一本好教科书教给你的第一件事。
  • 不要执行 "printf("enter any string\n");",因为这可能会在格式字符串攻击中被利用。
  • 如果我们通过gets或scanf来做会有什么不同?我们应该检查缓冲区溢出吗?如果我们分配一些80字节的缓冲区说..但我们只是输入字符串20个字节,但是整个60个字节就这样浪费了。你能证明这一点吗
  • @John Kugelman:我的立场是正确的,对不起

标签: c string


【解决方案1】:

你可以使用递归。

int ReverseString(char *rev) {
  if(*rev!='\0') {
    ReverseString(rev + 1);
    putchar(*rev);
  }
  return 1;
}

【讨论】:

  • 这很好,而且是我所知道的最简洁的反转链表的方法——似乎是一个常见的面试问题。然而,迭代方法可能更适合字符串。
  • 有一些方法可以改变它,以便您可以反转字符串本身,而不仅仅是输出,但它并不那么漂亮=P
【解决方案2】:
void ReverseString( char* str, int len ) {
  if( len > 1 ) {
    swap( &str[0], &str[len - 1] );
    ReverseString( ++str, len - 2 );
  }
}

或者,展开尾递归:

void ReverseString( char* str, int len ) {
  while( len > 1 ) {
    swap( &str[0], &str[len - 1] );
    ++str;
    len -= 2;
  }
}

其中swap定义为:

void swap( char* a, char* b ) {
  *a ^= *b;
  *b ^= *a;
  *a ^= *b;
}

如果你使用这个,你的助教肯定会知道你自己没有弄明白这个:)

【讨论】:

  • std::swap 对 C 初学者来说可能很重要。
  • 尤其是因为它是 C++,而不是 C。
  • @NotSure 您的交换函数仍然不是 C,它没有引用。
  • @NotSure,三步异或是一种花哨的矫枉过正。对于这两种方案,最好保留一个本地(堆栈)变量并在 ReverseString while() 循环或 if() 块中直接交换它。
  • 同意 - 在 C 代码中进行异或交换通常,在这种情况下,只是为了好玩而聪明。唯一的借口是在汇编代码中,您正在交换两个寄存器并且不想溢出到堆栈以使用另一个寄存器。此外,一个名为“swap”的函数应该有大量的警告注释,或者应该使用相同的参数。不应使用 a == b 调用此 xor-swap...
【解决方案3】:

好的,这是我的功能。前段时间写的,仅供练习。

char* reverse(char *string){

    int length = 0;
    int half = 0;

    length = strlen(string);
    half = (length/2) - 1;
    --length;

    int i = 0;
    register char interim;
    for(; i<=half; ++i){
        interim = string[i];
        string[i] = string[length - i];
        string[length - i] = interim;
    }

    return string;

}

现在我看到它,我并不为它感到骄傲,而不是当它开始工作时。我只是发布它,因为你让我在找到它时发布它——为了完整起见。

查看其他一些答案后,我意识到计算一半字符串是不必要的,我可以减少 length 直到 ilength 相等。哦,好吧——就在这里。

另外,请不要因为使用register 关键字而抨击我:P

【讨论】:

  • 'strlen' 也是一个 'O(n)' 操作,所以你的代码中还有两个循环,其中一个是隐藏的。
  • 我最初有自己的长度计算,但将其更改为 strlen,因为反转是代码的重点。但实际上,无论如何都必须知道长度,无论是在调用函数之前还是之后计算。
【解决方案4】:

又一个变种...

void ReverseString( char *str, int len ) {
  int i;
  for(i=0; i < len/2; i++) {
    swap( &str[i], &str[len -1 -i] );
  }
}
void swap( char *a, char *b ) {
  char tmp = *a;
  *a = *b;
  *b = tmp;
}

【讨论】:

    【解决方案5】:
    void revstr(TCHAR *str) {
      if( *str == '\0' ) {
        return;
      }
      TCHAR *start = str;
      TCHAR *end = start + strlen(str) - 1;
      while(start < end) {
        *start ^= *end;
        *end ^= *start;
        *start ^= *end;
        *start++;
        *end-–;
        /*
          could also use *start ^= *end ^= *start++ ^= *end–-; if you want to get fancy
        */
      }
    }
    

    2005 version of myself 偷来的,但是去他妈的那个家伙,他和我妻子睡了。是的,我知道我不需要一些 '*',但我先写了单行代码,然后对其进行了转换,单行代码确实需要它们。

    【讨论】:

      【解决方案6】:

      以下程序以相反的字符顺序打印其参数:

      #include <string.h>
      #include <stdio.h>
      
      char * reverse(char * string) {
        char * a = string;
        char * b = string + strlen(string) - 1;
        for(; a < b; ++a, --b)
          *a ^= *b, *b ^= *a, *a ^= *b; // swap *a <-> *b
        return string;
      }
      
      int main(int argc, char * argv[]) {
        for(int i = 1; i < argc; ++i)
          puts(reverse(argv[i]));
      }
      

      这里没有什么新东西,但 IMO 比大多数其他答案更具可读性。

      【讨论】:

        【解决方案7】:

        如果不知道字符串的长度:

        void reverse_string(char* str) {
          char* p2 = str;
          while (*p2 != '\0') {
            /* assumes the string is null-terminated, will fail otherwise */
            ++p2;
          }
          --p2;
          char* p1 = str;
          while (p1 < p2) {
            char tmp = *p1;
            *p1 = *p2;
            *p2 = tmp;
            ++p1;
            --p2;
          }
        }
        

        如果你这样做:

        void reverse_string(char* str, const size_t len) {
          if (len <= 1) {
            return;
          }
          char* p2 = str + len - 1;
          char* p1 = str;
          while (p1 < p2) {
            char tmp = *p1;
            *p1 = *p2;
            *p2 = tmp;
            ++p1;
            --p2;
          } 
        }
        

        【讨论】:

        • 知道我喜欢 while 循环的什么地方吗?你有的第一个,里面有注释,也可以写成 while(*p2++);
        • 另外,p1 和 p2 都只是指向 str(您还没有将字符串复制到新位置,因此您只是在使用两个变量处理同一个字符串)。真的,你可以用 *str 替换每次出现的 *p1 和 *p2。
        • "你有的第一个,里面有注释,也可以写成 while(*p2++);" - 恕我直言,太简洁了;我不会把它放在生产代码中,也不会放在 C 初学者的示例中
        • "另外,p1 和 p2 都只是指向 str (你还没有将字符串复制到新位置,所以你只是在使用两个变量处理同一个字符串)。真的,你可以用 *str 替换每次出现的 *p1 和 *p2。” -- 不正确,它们指向字符串中的不同位置。
        【解决方案8】:

        这行不通。应该为你的句子分配内存。

        char *Str;
        printf("enter any string\n");
        gets(Str);
        

        应该是:

        char str[81]={0};
        printf("Enter any string up to 80 characters\n");
        scanf("%80s\n",str);
        ReverseString(str)
        

        此外,您应该避免获取函数。它导致buffer overflows

        【讨论】:

        • 正确的关于需要一些内存用于缓冲区 - 关于如何读入缓冲区的错误。
        • Tom,如果说我们只输入 20 个字节的字符串,那么内存浪费怎么办,所以重复 60 个字节被浪费了。我有理由吗??如果我错了,请纠正我跨度>
        • 虽然是一个合理的问题,但在您学习的这一点上,您不应该真正担心 59 字节的“浪费”数据。当你开始使用 *alloc 分配空间时,你可以担心额外的空间。
        • @GNR : 你怎么能期望知道用户要输入多少?如果他输入 20,好吧,太糟糕了,浪费了 60 个字节。这不是问题,因为一旦堆栈展开(即主要完成),这些将被释放
        • 但是可能会想到一个场景,可能是一些实时系统,其中每个字节都是有价值的,过多的浪费会花费您的时间和速度。
        【解决方案9】:
        #include<stdio.h>
        void reverse(char s[])
        {
                int i=0,j,x=0,z;
                printf("\nThe string is : ");
                printf("%s",s);
                printf("\nThe reverse string is : ");
                while(s[i] != ' ')
                {
                        while(s[i] != ' ')
                                i++;
                        z=i+1;
                        for(j=i-1;j>=x;j--)
                                printf("%c",s[j]);
                        printf(" ");
                        i=z;
                        x=z;
                }
        }
        main()
        {
        char s[50];
        int a;
        for(a=0;a<50;a++)
                s[a]=' ';
        puts("\nEnter a sentence : ");
        fgets(s,50,stdin);
        reverse(s);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-26
          • 2022-06-12
          • 1970-01-01
          • 2020-12-30
          • 2017-05-19
          相关资源
          最近更新 更多