【问题标题】:Print pointer string which is return from function in C打印从 C 函数返回的指针字符串
【发布时间】:2021-03-16 17:50:40
【问题描述】:

尝试编写一个 C 程序来反转给定的字符串(使用指针),这是代码。

[示例.c]

#include <stdio.h>
#include <stdlib.h>

int _len(char s[])
{
    int i = 0;
    while (s[i++] != '\0');
    return i;
}

char *_reverse(char s[])
{
    int len = _len(s);
    char *r = malloc(len * sizeof(char));
    for (int i=len-1; i >= 0; i--) {
        *r++ = s[i];
    }

    *r = '\0';  // Line 21
    r -= len;   // Line 22
    return r;
}

int main(int argc, char *argv[])
{

    char s[10] = "Hello";
    printf("Actual String: %s\n", s);
    printf("Reversed: %s\n", _reverse(s));
    return 0;
}

当前 O/P:

Actual String: Hello

Reversed: (null)

预期 O/P:

Actual String: Hello

Reversed: olleH

这里有什么问题或遗漏..?请纠正我。提前致谢。

【问题讨论】:

  • 您没有在 char 数组的末尾添加 '\0'
  • @pavi2410 在函数中的return语句之前添加*r = '\0'后结果相同
  • 在命名函数或变量时不要使用下划线。 a) C 标准不允许 b) 不对代码添加任何内容(只会降低可读性)

标签: c reverse c-strings strlen function-definition


【解决方案1】:

第一个函数实现

int _len(char s[])
{
    int i = 0;
    while (s[i++] != '\0');
    return i;              // Old code
}

虽然没有标准行为,但声明或多或少是正确的。只有您必须考虑返回值包括终止零。

因此内存分配

char *r = malloc(len * sizeof(char));

是正确的。

但是for循环中变量i的初始值

for (int i=len-1; i >= 0; i--) {

不正确,因为索引表达式len - 1 指向将写入新字符串第一个位置的源字符串的终止零。因此,新数组将包含一个空字符串。

另一方面,这个函数定义(更新后你在帖子中显示的)

int _len(char s[])
{
    int i = 0;
    while (s[i++] != '\0');
    // return i;              // Old code
    return i == 0 ? i : i-1;  // Line 9 (Corrected)
}

没有多大意义,因为 i 由于 while 循环中的 prost-increment 运算符而永远不能等于 0。而且现在内存分配

char *r = malloc(len * sizeof(char));

不正确。终止零字符 '\0' 没有空格。

另外,在标识符前加上下划线也是一个坏主意。此类名称可由系统保留。

函数可以通过以下方式声明和定义

size_t len( const char *s )
{
    size_t n = 0;

    while ( s[n] ) ++n;

    return n;
}

要反转一个字符串,不需要分配内存/如果你想创建一个新字符串并以相反的顺序复制源字符串,那么函数必须声明为

char * reverse( const char * s );

即参数应具有限定符const。否则,如果没有限定符 const,函数声明会令人困惑。函数的使用者可以认为是逆序的源字符串。

所以如果函数声明如下

char * reverse( char *s );

那么可以这样定义。

char * reverse( char *s )
{
    for ( size_t i = 0, n = len( s ); i < n / 2; i++ )
    {
        char c = s[i];
        s[i] = s[n - i - 1];
        s[n - i - 1] = c;
    }

    return s;
} 

如果你想以相反的顺序从源字符串创建一个新字符串,那么函数可以看起来像

char * reverse_copy( const char *s )
{
    size_t n = len( s );

    char *result = malloc( len + 1 );

    if ( result != NULL )
    {
        size_t i = 0;

        while ( n != 0 )
        {
            result[i++] = s[--n];
        }

        result[i] = '\0';
    }

    return result;
}

当不再需要结果数组时,不要忘记释放 main 中的结果数组。

例如

char s[10] = "Hello";
printf("Actual String: %s\n", s);

char *t = reverse_copy( s );
printf("Reversed: %s\n", _reverse(t));
free( t );

尝试编写一个 C 程序来反转给定的字符串(使用 指针),这里是代码

如果您想在不使用下标运算符和索引变量的情况下定义函数,那么函数 lenreverse_copy 可以如下所示

size_t len( const char *s )
{
    const char *p = s;

    while (*p) ++p;

    return p - s;
}

char * reverse_copy( const char *s )
{
    size_t n = len( s );

    char *p = malloc( n + 1 );

    if (p)
    {
        p += n;
        *p = '\0';

        while (*s) *--p = *s++;
    }

    return p;
}

请注意,我的答案是最好的答案。:)

【讨论】:

    【解决方案2】:

    首先,_len 函数的定义不正确,它应该排除最后一个 '\0' 终止符(应该是:return i-1;)。另一个上面已经指出,需要使用不同的变量来遍历char *。

    #include <stdio.h>
    #include <stdlib.h>
    
    int _len(char s[]) {
        int i = 0;
        while (s[i++] != '\0');
        return i-1;
    }
    
    char *_reverse(char s[]) {
        int len = _len(s);
        //printf("Len: %d\n", len);
        char *r =  (char *) malloc((len+1) * sizeof(char));
        char *ptr = r;
        for (int i=len-1; i >= 0; i--) {
            //printf("%d %c\n", i, s[i]);
            *(ptr++) = s[i];
        }
        *(ptr++) = '\0';
        return r;
    }
    
    int main(int argc, char *argv[]) {
        char s[10] = "Hello";
        printf("Actual String: %s\n", s);
        printf("Reversed: %s\n", _reverse(s));
        return 0;
    }
    
    Actual String: Hello
    Reversed: olleH
    

    【讨论】:

    • 谢谢,现在已修复。 (_len() 函数是一个大错误)& 只是为了额外注意,而不是声明另一个指针(即 *ptr),正如@Julien 所说,添加 r -= len; 也可以正常工作。再次感谢。
    【解决方案3】:

    您正在修改新分配内存的指针“r”。因此,在反向函数的末尾,它仅指向您分配的缓冲区的末尾。 您可以通过执行以下操作将其移回开头:

    r -= len;
    

    但为了简化事情,我建议在开始时使用 i 和 len 来计算索引。

    另外,你不要用 '\0' 终止反转的字符串。

    【讨论】:

    • 已添加(请检查“第 22 行”).. 仍然是相同的结果。
    【解决方案4】:

    你在循环中增加r,然后返回它。显然,它指向实际反转字符串之后的地址。将 r 复制到 malloc 之后的另一个变量并返回。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-02
      • 1970-01-01
      相关资源
      最近更新 更多