【问题标题】:C code to reverse a string - including NULL character at the end of string反转字符串的 C 代码 - 包括字符串末尾的 NULL 字符
【发布时间】:2015-10-11 09:26:57
【问题描述】:

1.) 是否可以反转包含 NULL 字符的字符串 (这意味着“abcd”表示为五个字符,包括空字符。)

2.) 在我目前的实现中,没有考虑到 1.), 我在交换期间遇到分段错误。即在分配时:*str = *end;

void reverse(char *str)
    {
        char * end = str;
        char tmp;
        if (str)
        {  // to handle null string
            while (*end)
            {  // find the end character
                ++end;
            }
            --end; // last meaningful element
            while (str < end) // terminal condition: str and end meets in the middle
            {   tmp = *str; // normal swap subroutine
                *str = *end; // str advance one step
                *end = tmp;   // end back one step

                str++;
                end-- ;
            }
        }
        return;
    }

【问题讨论】:

  • 没有NULL 字符。 NULL 是 空指针 常量。您可能指的是 ASCII-NUL 终止符 '\0'。
  • @arshdeep kaur 您似乎正在尝试反转字符串文字。您不能反转字符串文字。而是用原始字符串声明一个字符数组。
  • 如果你反向包含NUL 终止符,你将有效地得到一个空字符串。这有什么价值?
  • @MartinJames: 取决于char 是签名还是未签名,并且您使用 2s 补码:-P
  • 供将来参考:使用“我在交换过程中遇到分段错误”,同时发布出现错误的调用代码和输入。

标签: c string segmentation-fault reverse


【解决方案1】:

你可以试试这个:

void reverse(char *str) {
    char *end = str;
    char tmp;
    if (str) {
        while (*end){
            ++end;
        }
        --end;
        while (str < end) {
            tmp = *str;
            *str++ = *end;
            *end-- = tmp;
        }
    }
}

【讨论】:

    【解决方案2】:
    1. 我很确定你可以。您只需要字符串的长度并注意测试 NUL。

    2. 字符串可以并且可能应该被认为是字符数组。特别是,尝试将字符串文字定向分配给已经初始化的字符串是无效的操作。

    一个例子:

    Here is one way to reverse a string:
    
    void reverse(char *str) {
      // First calculate the length
      unsigned int length = 0;
      int i = 0;
      for (; str[i] != '\0'; i++) {
        ++length;
      }
      ++length;
      // Allocate temporary storage
      char tmp = malloc(length);
      int x = 0;
      // Loop through starting at the end and go backwards
      // It is perfectly legal to change the characters themselves, just not the pointer
      for (i = length - 1; i >= 0; i++, x++) {
        if (str[i] != '\0') {
          tmp[x] = str[i];
        }
      }
      tmp[length - 1] = '\0';
      // Reassign to the given argument
      for (i = 0; i < length; i++) {
        str[i] = tmp[i];
      }
      // Free memory
      free(tmp);
    }
    

    就像其他答案所述,您正在尝试做一些在标准中未定义的行为。

    【讨论】:

      【解决方案3】:

      你的函数是正确的。似乎问题在于您正在尝试反转字符串文字。您不能更改字符串文字。它们是不可变的。任何更改字符串文字的尝试都会导致程序的未定义行为。

      来自 C 标准(6.4.5 字符串文字)

      7 不确定这些数组是否不同,前提是它们的 元素具有适当的值。 如果程序试图 修改这样的数组,行为未定义

      只考虑写会更好

      if ( *str )
      

      而不是

       if (str)
      

      或者如果你想检查指针不为空,那么

      if ( str && *str )
      

      在这种情况下这个递减

      --end;
      

      即使原始字符串为空也有效。

      尽管如此,函数本身可以按照以下方式定义,如演示程序中所示

      #include <stdio.h>
      
      char * reverse( char *s )
      {
          char *last = s;
      
          while ( *last ) ++last;
      
          if ( last != s )
          {        
              for ( char *first = s; first < --last; ++first )
              {
                  char c = *first;
                  *first = *last;
                  *last = c;
              }
          }
      
          return s;
      }    
      
      int main( void )
      {
          char s[] = "Hello arshdeep kaur";
      
          puts( s );
          puts( reverse( s ) );
      }    
      

      程序输出是

      Hello arshdeep kaur
      ruak peedhsra olleH
      

      【讨论】:

      • 赞成,这是唯一提到修改字符串文字是 UB 的答案。
      • @szczurcio 谢谢。你是一个善良的人。
      • 注意:OP 的代码是 --end;,即 UB 应该是 str = ""。所以不完全是“你的功能是正确的”。
      • 很好地避免了 int 长度和索引,如果使用应该是 size_t - 投票
      • @chux 谢谢。我虽然有 if ( *str ) :)
      【解决方案4】:

      像这样调用你的代码:

      int main()
      {
          char a[]="abcd";
          int i;
          reverse(a);
          for (i=0;i<5;i++) {
              printf("a[%d]=%02x\n",i,a[i]);
          }
      }
      

      输出这个:

      a[0]=64
      a[1]=63
      a[2]=62
      a[3]=61
      a[4]=00
      

      所以你可能传递了一个字符串文字(即char *a="abcd";)。这些文字通常存储在内存的只读部分中,这可能是核心转储的原因。

      话虽如此,在处理字符串时,包括空字符在内的反转并没有太多实际用途。

      【讨论】:

        猜你喜欢
        • 2023-02-14
        • 1970-01-01
        • 2014-09-12
        • 1970-01-01
        • 2013-11-12
        • 2023-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多