繁体   English   中英

"使用 malloc 分配字符串"

[英]Allocating string with 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;
}

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

你的malloc()调用应该是这样的:

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

注意:您不需要转换malloc的返回。 有关更多信息,请阅读此内容

另外要指出的是sizeof(char)1 ,所以在malloc()调用中乘以它是没有必要的。

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

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

此外,您只能在以null结尾的字符串上使用strlen() ,否则最终会出现未定义的行为

一旦调用了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;
}

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

不, malloc()返回一块未初始化的内存。

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

scanf()插入空字节( '\\0'你)当您使用%s格式说明(假设scanf()成功)。

来自man scanf()

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

(强调我的)。

顺便说一下,你应该对scanf()malloc()调用进行错误检查。

C中“string”的定义是一个字符序列,以空字符结尾

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

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

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';

实现这一点的简单方法是包含 cs50 库。 只需使用 get_string 函数:

#include <stdio.h>
#include <cs50.h>

int main(void) {
    // input the string to stringa1
    char *stringa1 = get_string("Insert the string: ");

    // call the string
    printf("The string you type was: %s\n", stringa1);

    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM