【发布时间】:2022-07-20 21:37:37
【问题描述】:
我正在阅读 BeeJ 的 C 编程指南并复制了他的 readline() 函数,该函数从标准输入读取一行。由于它的实现方式,读取多字节字符没有问题,因为它根据接收到的字节总数重新分配空格,因此,它没有 unicode 输入问题。这是一个包含该功能的程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define printPrompt printf("db > ")
/* The readLine function, allocates memory for a short string and
** reads characters into it. When the string's size limit is met,
** the same memory block is reallocated, but twice the size.
** Shamelessly stolen from BeeJ's guide to C programming |=
*/
char* read_line(void) {
int i = 0; /* Position of the current character */
int linbuf = 4; /* Size of our line in memory, will be
duplicated once the line length surpasses it */
char* lin; /* The pointer value to our line */
int c; /* The value we'll use to accept characters */
if( !(lin = malloc( linbuf*sizeof(char))) )
return NULL;
while( c = getchar(), c != '\n' && c != EOF ) {
/* Check if the amount of bytes accepted has surpassed the
* amount of memory we've allocated so far */
if(i == linbuf - 1) {
/* If it did, reallocate double the space */
linbuf *= 2;
char* tmpbuf = realloc(lin, linbuf);
/* If the space couldn't have been allocated then we'd
* run out of memory. Delete everything and abort. */
if(tmpbuf == NULL) {
free(tmpbuf);
return NULL;
}
/* If we've arrived here that means there were no
* problems, so we'll assign the newly reallocated
* memory to "lin" */
lin = tmpbuf;
}
/* Add the new character to our allocated space */
lin[i++] = c;
}
/* If we've received an EOF signal after having read 0
* characters, we'd like to delete our allocated memory and
* return a NULL */
if(c == EOF && i == 0) {
free(lin);
return NULL;
}
/* Here we'll shrink the allocated memory to perfectly fit our
* string */
if(i < linbuf - 1) {
char* tmpbuf = realloc(lin, i + 1);
if(tmpbuf != NULL)
lin = tmpbuf;
}
/* Here we'll terminate the string */
lin[i] = '\0';
/* Finally, we'll return it */
return lin;
}
int main(int argc, char* argv[]) {
char* hey = read_line();
printf("%s\n", hey);
return 0;
}
输入Hello, World! (:
将导致Hello, World! (:
多字节字符的输入,例如שלום, עולם! (:
将导致שלום, עולם! (:
但是,如果我按退格键,它只会删除一个字节字符,导致输出乱码; (标记为 \b 的退格)的输入:שיהיה לכם בוקר טוב\b\b\b\b\b\b\b\bערב טוב
最终应该是:שיהיה לכם ערב טוב
实际上最终是:�שיהיה לכם בוק�ערב טוב
我的电脑运行 Musl-libc 版本的 Void Linux,我使用 tcc 和 gcc 编译了程序,都产生了相同的结果。
这个问题是否与我的 libc、我的终端(suckless st)、我的内核有关,还是我在代码中缺少的东西?不管是什么情况,我有什么办法可以处理它,最好不使用任何外部库,如 ICU 或你有什么?
【问题讨论】:
标签: c command-line-interface stdio