使用malloc分配字符串

时间:2017-01-24 14:16:36

标签: c string malloc

我是C语言编程的新手,现在我正在研究字符串。 我的问题是:如果我使用malloc分配一个字符串(如下面的代码所示),是否会在字符串末尾自动插入NULL字符? 我在这里找到另一个问题的答案,似乎不会自动包含NULL字符。 但问题出在这里:我知道如果没有NULL字符,strlen之类的函数不起作用,并且在这段代码中我使用它并且它可以工作。所以我认为在我的字符串末尾有\0,即使我不在任何地方写它。 答案是什么?

以下是代码:

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

int main(int argc, char** argv) {
    char *stringa1;
    int n;
    int i;

    printf("How many characters in the string? ");
    scanf("%d", &n);

    stringa1 = (char*) malloc(n*sizeof(char));

    printf("Insert the string: ");
    scanf("%s", stringa1);

    free(stringa1);

    return 0;
}

4 个答案:

答案 0 :(得分:11)

malloc()返回一个void*指针,指向存储在堆中的内存块。使用malloc()分配不会初始化任何字符串,只会占用等待占用的空间。要添加一个空终止字符,您必须自己执行此操作,或使用类似scanf()的函数,这会添加此你的角色。说完这个,你需要事先为这个\0字符分配空间。

您的malloc()来电应该是这样的:

stringa1 = (char*) malloc((n+1)*sizeof(char)); /*+1 for '\0' character */

注意:您不需要转换malloc的返回值。有关详细信息,请阅读this

要指出的另一点是sizeof(char)1,因此在malloc()来电中将其相乘是没有必要的。

您还需要检查malloc()是否返回NULL。这可以这样做:

if (stringa1 == NULL) {
    /* handle exit */

此外,您只能在以空字符结尾的字符串上使用strlen(),否则最终会成为undefined behaviour

调用scanf()后,stringa1包含一些字符,您可以在其上调用strlen()

此外,检查scanf()的返回也是一个好主意。您可以这样检查:

if (scanf("%d", &n) != 1) {
    /* handle exit */

您的代码包含以下更改:

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

int main(void) {
    char *stringa1 = NULL;
    size_t n, slen;

    printf("How many characters in the string? ");
    if (scanf("%zu", &n) != 1) {
        printf("Invalid input\n");
        exit(EXIT_FAILURE);
    }

    stringa1 = malloc(n+1);
    if (stringa1 == NULL) {
        printf("Cannot allocate %zu bytes for string\n", n+1);
        exit(EXIT_FAILURE);
    }

    printf("Insert the string: ");
    scanf("%s", stringa1);

    slen = strlen(stringa1);
    printf("String: %s Length: %zu\n", stringa1, slen);

    free(stringa1);
    stringa1 = NULL;

    return 0;
}

答案 1 :(得分:8)

  

如果我使用malloc分配一个字符串(如下面的代码所示),是否在字符串的末尾自动插入了NULL字符?

没有。 malloc()返回一块未初始化的内存。

  

我知道如果没有NULL字符,'strlen'之类的函数不起作用,在这段代码中我使用它并且它有效。所以我认为在我的字符串末尾有'\ 0',即使我没有在任何地方写它。

当您使用scanf()格式说明符(假设'\0'成功)时,

%s会为您插入空字节(scanf())。

来自man scanf()

  

s匹配一系列非空白字符;下一个       指针必须是指向a的初始元素的指针       字符数组足够长以容纳输入序列       和添加的终止空字节('\ 0')       自动。输入字符串在空格或at处停止       最大字段宽度,以先到者为准。

(强调我的)。

顺便说一下,您应该对scanf()malloc()来电进行错误检查。

答案 2 :(得分:1)

&#34; string&#34;的定义在C中是一个字符序列,以空字符终止。

要为字符串分配内存,请计算字符数(例如strlen)并为此终止空字符添加1。

scanfstrcpy等函数添加空字符;像strncpy这样的函数并不总能这样做。

答案 3 :(得分:1)

malloc返回指向未初始化内存范围的指针。

如果您希望内存范围由零初始化,那么您可以使用另一个标准函数calloc而不是malloc

考虑到通常这样的问题

printf("How many characters in the string? ");

暗示终止零不计算在内。所以你必须再分配一个字节的内存。例如

stringa1 = ( char* )malloc( ( n + 1 ) *sizeof( char ) );

stringa1 = ( char* )calloc( n + 1, sizeof( char ) );

在最后一种情况下,您可以应用返回0的函数strlen,因为内存范围是零初始化的。

scanf

的来电
scanf("%s", stringa1);

不安全。最好使用fgets代替。例如

fgets( stringa1, n + 1, stdin );

此函数可以使用换行符添加字符串。要从字符串中删除它,您可以编写

stringa1[strcspn( stringa1, "\n" )] = '\0';