从scanf()到fgets(),我们需要首先指定字符串输入的最大长度,因为输入受到限制,这不是很好。由于输入可能与[0,∞)不同,由于计算机的限制,输入永远不会到达∞,但可能非常大。
我在C++中见过,字符串输入没有限制。
std::string x;
std::cin >> x;因此,为了在C中实现这个特性,我创建了一个函数,该函数从用户那里获取一个字符,并将其附加到缓冲区的最后一个位置,然后调用realloc()作为缓冲区。
#include <stdio.h>
#include <stdlib.h>
static inline void exit_heap_fail(const void *ptr)
{
if (!ptr)
{
fprintf(stderr, "err: null-pointer\n");
exit(EXIT_FAILURE);
}
}
static char *input(void)
{
char *ptr = calloc(2, sizeof(char)), ch;
exit_heap_fail(ptr);
size_t len = 0;
while ((ch = getchar()))
{
if (ch == 10 || ch == 0)
break;
ptr[len++] = ch;
ptr = realloc(ptr, len + 1);
exit_heap_fail(ptr);
}
ptr[len] = 0;
return ptr;
}
int main(void)
{
puts("Enter:");
char *data = input();
printf("DATA = `%s`\n", data);
free(data);
return EXIT_SUCCESS;
}发布于 2022-04-30 13:10:43
当不读取任何内容时,代码将返回分配的""。这与只读取一个'\n'是没有区别的,因为它也返回""。
要像其他标准输入函数一样工作,代码应该返回一些指示,比如NULL:
当文件结束时,getchar()返回EOF,而代码永远不会退出循环。
// Infinite loop
while ((ch = getchar())) {
if (ch == 10 || ch == 0)
break;对空字符进行两次代码测试。
getchar()返回257个不同的值(EOF和all unsigned char)。保存在char中会丢失信息。
使用int ch。
realloc(ptr, len + 1);每次迭代都调用realloc()。一种更有效的通用方法将每个循环的大小大约加倍,并在最后进行适当的大小分配。
上的输入
这与fgets(), scanf()不同。
编辑
一些示例代码来说明这些想法,还有一些更多。只是轻微的测试。
标题:
/*
* Allocate as needed to form a string from user input.
*
* Return NULL on
* * End of file with no input
* * Input error
* * Out of memory
* Caller to use feof(), ferror() to distinguish.
*
* Otherwise return allocated buffer.
* Caller to free buffer.
*/
char* line_alloc(void);来源
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define LINE_ALLOC_MIN 63 /* Some power-of-2 minus 1 */
static char* line_alloc_helper(char *buf, size_t *len_max_ptr) {
// Is input longer than supportable size?
if (*len_max_ptr > SIZE_MAX / 2 - 1) {
free(buf);
return NULL;
}
size_t sz = *len_max_ptr + 1; // Old buffer size
sz = 2 * sz + 1; // New buffer size
if (sz < LINE_ALLOC_MIN) {
sz = LINE_ALLOC_MIN;
}
char *buf_new = realloc(buf, sz);
if (buf_new == NULL) {
free(buf);
return NULL;
}
*len_max_ptr = sz - 1;
return buf_new;
}
char* line_alloc(void) {
size_t len = 0;
size_t len_max = 0;
char *buf = NULL;
int ch;
bool nothing_read = true;
while ((ch = getchar()) != EOF) {
nothing_read = false;
if (ch == '\n' || ch == '\0') { // Remove ch == '\0' if desired.
break;
}
if (len >= len_max) {
buf = line_alloc_helper(buf, &len_max);
if (buf == NULL) {
return NULL;
}
}
buf[len++] = (char) ch;
}
if (ch == EOF) {
if (nothing_read || !feof(stdin)) { // Note 1
free(buf);
return NULL;
}
}
char *buf_right_size = realloc(buf, len + 1);
if (buf_right_size == NULL) {
free(buf);
} else {
buf_right_size[len] = '\0';
}
return buf_right_size;
}
/* Note 1: Better as !feof() than ferror() to identify
end-of-file with input error set from prior activity. */测试:
#include <string.h>
int main(void){
char * buf;
while ((buf = line_alloc()) != NULL) {
size_t len = strlen(buf);
printf("%2zu <%s>\n", len, buf);
free(buf);
fflush(stdout);
}
}今后的改进/设想:
FILE *input_stream。malloc()。转换到为长行分配的缓冲区。增加了复杂性,但只为公共行分配了一次。'\r' '\n'对。len,以便更好地支持嵌入空字符的行。SIZE_MAX,以帮助防止黑客滥用代码。https://codereview.stackexchange.com/questions/276173
复制相似问题