首页 > 解决方案 > 在非规范模式中复制和粘贴

问题描述

我正在创建一个程序来实现一个 linux shell

我已将终端模式更改为非规范

void    ft_getch_prepare(void)
{
int             ret;
struct termios  new_opts;

ret = tcgetattr(STDIN_FILENO, &new_opts);
new_opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK
        | ECHONL | ECHOPRT | ECHOKE | ICRNL);
new_opts.c_cc[VMIN] = 1;
new_opts.c_cc[VTIME] = 1;
ret += tcsetattr(STDIN_FILENO, TCSANOW, &new_opts);
}

int     ft_getch(void)
{
int c;

c = 0;
ft_getch_prepare();
read(0, &c, 4);
return (c);
}

但是当我想复制一个字符串并粘贴它时,它只显示复制字符串的第一个字符

例如,我想将此字符串粘贴"HELLO WORLD"到我的终端中,但它只显示第一个字符"H"

标签: clinuxterminal

解决方案


ICRNL标志常数适用于,c_iflag而不适用于。c_lflag您在错误的地方将其关闭。我不清楚你为什么要关闭它但如果你想这样做,那么你需要修改正确的标志集。

, ECHOE, ECHOL, ECHONL,ECHOPRTECHOKElocal-mode 标志仅与您要关闭的规范模式相关。关闭这些也不应该是有害的,但它确实使你的代码比它需要的更难阅读和遵循。

关于

当我想复制一个字符串并粘贴它时,它只显示复制字符串的第一个字符

,我怀疑您被输入计时器和/或非规范模式的最小字符数属性所困扰。这些由您的 termios 结构中的“特殊字符”数组的c_cc[VTIME]和元素控制。c_cc[VMIN]如果您正在配置一个支持交互式输入的终端,或者在输入中可能存在无限长度暂停,那么您需要关闭计时器并通过设置确保读取正确阻塞

new_opts.c_cc[VTIME] = 0;
new_opts.c_cc[VMIN] = 1;

. 但是,我不确定这是否足以满足您的目的,部分原因是我无法判断您阅读输入的方式是否会导致问题。

更新

既然您现在已经公开了您的输入功能,我可以说如果它应该提供一个等效于getc(). 您一次读取四个字节而不是一个字节,并且您没有正确处理 EOF 或错误。此外,多字节读取引入了您无法检测或处理的短读取的可能性。

如果您尝试一次读取一个字符,请执行此操作。的返回值getc()不是因为尝试从流中读取 s 是合适的,而是提供了无效s 的结果值——特别是.intcharintcharEOF

我拒绝为您重写您的代码,但要模拟getc(),它需要这样做:

  • 一次读char一个
  • 检查的返回值read。如果它不是 1(对于单字符读取),则返回EOF
  • 否则,返回读取的字符,转换为 typeunsigned char

推荐阅读