我是 C 新手,我想知道如何做到这一点,当通过控制台输入 X 个字符的单词时,会创建一个字符数组,并为其分配正确的内存,例如我输入“hello”然后它保存在 6 个空格字符的字符串中。谢谢!
3 回答
ISO C 标准库规范或 Microsoft C 库中没有任何内容可以直接满足您的需求。
然而,在C POSIX 库中(有什么区别?),scanf
函数族支持m
字符串s
输入的修饰符。使用时m
,scanf()
将分配适当大小的缓冲区,并将其分配给您提供的指针:
可选的“m”字符。这与字符串转换 (
%s
,%c
,%[
) 一起使用,并且使调用者无需分配相应的缓冲区来保存输入:而是scanf()
分配一个足够大小的缓冲区,并将该缓冲区的地址分配给相应的指针参数,它应该是一个指向char *
变量的指针(这个变量不需要在调用之前初始化)。调用者随后应free(3)
在不再需要此缓冲区时使用此缓冲区。
这是一个例子:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *input = NULL;
if (scanf("%ms", &input) != 1) {
fprintf(stderr, "scanf() failed\n");
return 1;
}
printf("scanf() allocated string: \"%s\"\n", input);
free(input);
return 0;
}
支持的 C 库:
不支持的C 库:
- Dietlibc——至少 0.34
- Microsoft C 运行时库 (CRT)
尝试使用标准库函数直接满足 OP 的 <enter "hello" 目标并保存在 6 个空格字符的字符串中,这看起来很有趣,即使它需要一些代码。
可悲的是,标准 C 并没有像@Jonathon Reinhart好的答案所建议的那样提供不错的选择。
相反,下面是一种不适合学习者的方法,但确实有效。它没有预先的行长度限制。它递归地形成输入字符的链接列表(递归不适合长行),然后根据深度分配数组,并分配数组。
#include <stdlib.h>
#include <stdio.h>
typedef struct link_s {
struct link_s *prev;
char ch;
} llink;
char* foo(llink *prior) {
int ch = fgetc(stdin);
if (ch == '\n' || ch == '\r' || ch == EOF) {
llink *ll = prior;
size_t len = 1;
while (ll) {
len++;
ll = ll->prev;
}
char *buf = malloc(len);
if (buf) {
buf[--len] = '\0';
llink *ll = prior;
while (ll) {
buf[--len] = ll->ch;
ll = ll->prev;
}
}
return buf;
}
llink node = {.prev = prior, .ch = (char) ch};
return foo(&node);
}
int main() {
char *s = foo(NULL);
printf("<%s>\n", s);
free(s);
return 0;
}
输入
Hello<enter>
输出
<Hello>
如果你只需要读到换行符,你可以使用定义在stdio.h
. 它会自动分配内存。该函数将分配一个额外的字符来存储换行符,您可以使用buf[strcspn(buf, '\n')] = '\0'
.
如果您希望它一直读取到空格,遗憾的是没有标准的 C 库函数可以满足您对任意字符串长度的需求(无需编写一堆您自己的代码)。如果您是学习 C 的初学者并且需要简单的 I/O,那么使用scanf("%s", buf)
固定大小的缓冲区应该足够了。