0

我是 C 新手,我想知道如何做到这一点,当通过控制台输入 X 个字符的单词时,会创建一个字符数组,并为其分配正确的内存,例如我输入“hello”然后它保存在 6 个空格字符的字符串中。谢谢!

4

3 回答 3

1

ISO C 标准库规范或 Microsoft C 库中没有任何内容可以直接满足您的需求。

然而,在C POSIX 库有什么区别?scanf函数族支持m字符串s输入的修饰符。使用时mscanf()分配适当大小的缓冲区,并将其分配给您提供的指针

Linuxscanf()手册页

可选的“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 库:

于 2021-10-14T01:01:47.743 回答
0

尝试使用标准库函数直接满足 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>
于 2021-10-14T03:54:01.643 回答
0

如果你只需要读到换行符,你可以使用定义stdio.h. 它会自动分配内存。该函数将分配一个额外的字符来存储换行符,您可以使用buf[strcspn(buf, '\n')] = '\0'.

如果您希望它一直读取到空格,遗憾的是没有标准的 C 库函数可以满足您对任意字符串长度的需求(无需编写一堆您自己的代码)。如果您是学习 C 的初学者并且需要简单的 I/O,那么使用scanf("%s", buf)固定大小的缓冲区应该足够了。

于 2021-10-14T04:27:17.850 回答