我是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;
}
答案 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。
scanf
和strcpy
等函数添加空字符;像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';