C 这个函数有什么问题?

C 这个函数有什么问题?,c,find,C,Find,我今天有个问题。它有一个方法,我需要找到这个函数中的问题。函数的目标是将新行附加到传递的字符串中。下面是代码 char* appendNewLine(char* str){ int len = strlen(str); char buffer[1024]; strcpy(buffer, str); buffer[len] = '\n'; return buffer; } 我已经发现了这个方法的问题。有点直截了当。该方法可能使数组的索引超出范围。这不是我的

我今天有个问题。它有一个方法,我需要找到这个函数中的问题。函数的目标是将新行附加到传递的字符串中。下面是代码

char* appendNewLine(char* str){
    int len = strlen(str);
    char buffer[1024];
    strcpy(buffer, str);
    buffer[len] = '\n';
    return buffer;
}
我已经发现了这个方法的问题。有点直截了当。该方法可能使数组的索引超出范围。这不是我的疑问。在java中,我使用“\n”表示换行符。(我基本上是一名Java程序员,在C语言中工作了很多年)。但我模糊地记得“\n”在C中表示字符串的终止。这也是这个程序的问题吗


请告知。

在换行符后添加空值:

buffer[len] = '\n';
buffer[len + 1] = 0;

C中字符串的终止符是“\0”而不是“\n”。它只代表新行。

首先,这是一个函数,而不是一个程序

此函数返回指向局部变量的指针。此类变量通常在堆栈上创建,但在函数退出时不再可用

另一个问题是,如果传递的长度超过1024个字符;在这种情况下,
strcpy()
将写入缓冲区。 一种解决方案是在动态内存中分配一个新的缓冲区,并返回指向该缓冲区的指针。缓冲区的大小应为len+2(所有字符+
换行符
+
\0
字符串终止符),但必须有人释放此缓冲区(可能还有初始缓冲区)


strlent()
不存在,它应该是
strlen()
,但我想这只是一个输入错误。

不,一个“\n”在c中是一个新行,就像在Java中一样(Java从c中获取了它)。您已经发现了一个问题:如果输入字符串长于
缓冲区
,您将写入超过
缓冲区
的末尾。更糟糕的是,您的
返回缓冲区返回函数本地的内存地址,该地址在函数退出时将不再存在。

代码有几个问题:

  • 由于
    缓冲区
    硬编码为仅分配
    1024个
    字符,因此它可能会导致缓冲区溢出。更糟糕的是,缓冲区甚至没有在堆中分配
  • 换行符“字符”实际上依赖于操作系统。严格地说,它只在Unix等Windows中是
    \n
    ,在严格的internet协议中是
    \r\n
  • 函数返回的字符串不是以null结尾的。这很可能不是你想要的

此外,考虑到您的Java背景,以下是一些您应该考虑的事项:

  • 由于您使用的是C
    char*
    而不是(不可变的)Java字符串,那么您是否可以在适当的位置追加换行符
  • 在运行时不再检查数组访问,因此您必须非常小心超出边界。确保所有缓冲区大小适当
  • 该语言没有标准的自动垃圾收集功能,因此如果您选择为字符串操作分配新的缓冲区,请确保正确管理内存,并且不会到处泄漏

此函数返回缓冲区,缓冲区是堆栈上的局部变量。只要函数返回内存,缓冲区就可以用于其他用途

如果要从函数返回内存,则需要使用malloc或类似方法分配内存


代码还存在其他问题-您不能确保缓冲区足够大以包含要复制到其中的字符串,也不能确保字符串以空终止符结尾。

您的程序至少有两个问题

首先,您似乎想要构建一个字符串,但您从不以零结束它


其次,函数返回一个指向本地声明缓冲区的指针。这样做毫无意义。

这段代码中有很多问题

  • strlent而不是strlent,除非你有一个奇怪的库函数
  • 您正在堆栈上定义一个静态缓冲区。这是一个潜在的错误(也是一个安全性错误),因为一行之后,您将在不检查长度的情况下将字符串复制到该行。 可能的解决方案可以是在堆上分配内存(结合strlen和malloc),或者使用strncpy并接受字符串的截断
  • 添加“\n”确实解决了添加新行的问题,但这会造成另一个错误,因为字符串当前不是以null结尾的。 解决方案:将“\n”和“\0”追加为null,以终止新字符串
  • 正如其他人所提到的,您正在返回一个指向局部变量的指针,这是一个严重的错误,会使返回值在短时间内损坏
  • 为了扩展您对这些问题的理解,请查找C样式字符串是什么,可能来自。另外,教自己在堆栈上分配的变量和在堆上分配的变量之间的区别


    编辑:AndreyT是正确的,长度的定义是有效的

    C字符串必须以
    '\0'
    结尾

    buffer[len+1] = '\0';
    
    您应该将缓冲区动态分配为指向大小为
    len
    的字符的指针:

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

    也许\n应该是\r\n。返回+新行。这是我经常使用的,对我有用。

    C字符串以“\0”结尾。
    由于您的目标是追加换行符,下面的内容就可以了(这样可以避免将整个字符串复制到缓冲区中):

    编辑:
    字符串应该有空间容纳额外的“\n”,因为目标本身是追加,这意味着添加到原始字符串中,所以可以安全地假设字符串至少还有一个字符的空间!!
    但是,如果你不想假设什么

    char* appendNewLine(char* str){
        int length = strlen(str);
        char *newStr = (char *)malloc(1 + length);
        *(newStr + length) = '\n';
        *(newStr + length + 1) = '\0';
        return newStr;
    }
    另一个重要问题是缓冲变量;它应该是一个局部堆栈变量。函数一返回,就会从堆栈中销毁它。将指针返回到缓冲区可能意味着,如果您试图在返回的指针(ad)处写入,您的进程将崩溃
    char* appendNewLine(char* str){
        int length = strlen(str);
        char *newStr = (char *)malloc(1 + length);
        *(newStr + length) = '\n';
        *(newStr + length + 1) = '\0';
        return newStr;
    }
    char* appendNewLine(char* str){
        int len = strlen(str);
        char buffer[1024];
        strcpy(buffer, str);
        buffer[len] = '\n';
        return buffer;
    }
    
    int len = strlen(str);
    char buffer[1024];
    ...
    buffer[len] = '\n';
    
    char buffer[1024];
    strncpy(buffer, str, 1024); // truncate string if it is too long
    int len = strlen(buffer);
    if (len < 1022) {
       buffer[len] = '\n';
       buffer[len + 1] = '\0';
    }