C:不影响指针的反向字符串函数


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int reverse(char *, int);
main()
{
    char *word = "Thanks for your help";
    reverse(word, strlen(word));
    printf("%s", word);     
    getchar();
}
int reverse(char *line, int len)
{
    int i, j;
    char *newline = malloc(strlen(line));
    for (i = len - 1, j = 0 ; i >= 0; i--, j++)
    {
        newline[j] = line[i];
    }
    newline[j] = '';
    line = &newline;
}

嘿伙计们。我有一个简单的C问题,我似乎无法解决。

上面的程序旨在接收一个字符串并将其向后打印出来。反向是完成此操作的功能。

具体来说,问题是当我在main((中打印单词时,字符串看起来没有变化。我试图使行的地址成为换行符的地址,但它没有任何效果。

int reverse(char *line, int len)
{
    int i, j;
    char *newline = malloc(strlen(line));
    for (i = len - 1, j = 0 ; i >= 0; i--, j++)
    {
        newline[j] = line[i];
    }
    newline[j] = '';
    line = &newline;             // Your problem is here
}

您只是分配给本地line指针。这对调用函数没有任何影响。

相反,请考虑:

char *reverse(char *line, int len)
{
    // ...
    return newline;
}

其他建议:

  • 打开编译器警告,并注意它们。你有很多小问题(例如 reverse 当前未返回任何内容,但声明为返回int (。
  • 鉴于 reverse 的第一个参数是指向 C 字符串(NUL 终止(的指针,因此也不需要采用长度参数。
  • reverse函数不一定需要定义为返回字符串的副本,反转。它可以就地反转字符串。请注意,不能将字符串文本传递给这样的函数,因为它们是只读的。

这是我怎么写的:

#include <stdio.h>
#include <string.h>
void reverse(char *str)
{
    size_t i, j;
    for (i = strlen(str) - 1, j = 0 ; i > j; i--, j++)
    {
        // Swap characters
        char c = str[i];
        str[i] = str[j];
        str[j] = c;
    }
}
int main(void)
{
    // Mutable string allocated on the stack;
    // we cannot just pass a string literal to reverse().
    char str[] = "Here is a test string";
    reverse(str);
    printf("Result: "%s"n", str);
    return 0;
}

请注意,for循环条件是 i > j ,因为我们希望每个字符只遍历数组的一半,而不是将每个字符交换两次。

结果:

$ ./a.exe
Result: "gnirts tset a si ereH"

看看下面的代码:

void addOne(int a) {
   int newA = a + 1;
   a = newA;
}
int main() {
  int num = 5;
  addOne(num);
  printf("%dn", num);
}

你明白为什么会打印 5 而不是 6 吗?这是因为当你把num传递给addOne时,你实际上是在复制num。当addOne a更改为newA时,它正在更改副本(称为a(,而不是原始变量num。C 具有按值传递语义。

您的代码遇到同样的问题(以及其他一些事情(。调用 reverse 时,将创建 word 的副本(不是字符串的副本,而是指向字符串的字符指针的副本(。当您更改line以指向新字符串时,newLine ,您实际上并没有更改传入的指针;您正在更改指针的副本。

那么,应该如何实现逆向呢?这取决于:有几个选择。

  1. reverse可以返回一个新分配的字符串,其中包含原始字符串,反转。在这种情况下,您的函数签名将是 char *reverse ,而不是 int 反向。
  2. reverse可以就地修改原始字符串。也就是说,您永远不会分配新字符串,而只是移动原始字符串的字符。这通常有效,但不适用于您,因为使用字符串文本初始化的 char 指针不一定指向可写内存。
  3. 反向实际上可以更改传入的指针以指向新字符串(您尝试在当前代码中执行的操作(。为此,您必须编写一个函数void reverse(char **pointerToString)。然后你可以分配*pointerToString = newLine;.但这不是很好的做法。原始传入的参数现在无法访问,如果它是 malloc'd,则无法释放。

最新更新