【问题标题】:Edit a body of text from the command line in C从 C 中的命令行编辑正文
【发布时间】:2009-05-09 08:02:43
【问题描述】:

我正在用 C 编写一些小程序——一些登录、注销、创建帐户、发送消息到另一个帐户的交易——我可以在这些程序的基础上进行构建、更改、创新和完善以完善我的C中的技能。

我想弄清楚的是如何实现“撰写消息”选项的一部分。在提示您输入消息的收件人、主题和正文后,我希望能够返回并编辑它们——而不必重新输入整个内容。因此,如果我选择“编辑消息”选项,它会写出我拥有的内容,然后让我回去更改一些内容。

我在x86 assembly 中做过类似的事情,或者开始做类似的事情,所以我基本上了解这将如何在机器级别实现,但我不知道如何在C. 我该怎么做?

在 C 语言中,以下内容让我感到困惑:

  • 处理可能冗长的输入的好方法
  • 如何写出文本并允许用户对其进行编辑,而不会超过某个特定点
  • 如何控制光标的位置

此外,如果之前已经这样做过,并且存在用于此类事情的函数库(甚至是我不知道的标准库),请注意我确实想推出自己的

strong> 以学习为目的。

我想我脑海中的方法是一次读取一个字符的消息正文,以便我可以考虑回车并创建多行消息。但我不确定我将如何退格通过它。我想从命令行执行此操作真的很难(?)。

如果不是不可能,将光标移回并删除已经超出输入缓冲区的字符...我每次都必须“重新绘制屏幕”吗?就像我可以控制整个控制台并在某些位置读取和写入击键吗?还是离机器太近了?我有点用汇编来做,但是使用了 16 位中断,我不允许在 C 中使用它...这是我在汇编中写的:

(以前在这里的图像已经消失)

程序将一个字节值转换为代表该字节的两个字符代码,然后跳转到右列并写入原始字节(显示为字符),然后跳回并写出另外两个十六进制数字,在下一个插槽中...等等,从左到右,从上到下...这很容易,但我知道如何在 C 中实现它。我能做的就是是INT 21 样式的输入和输出,向控制台写入行,从而向上滚动窗口等等。

【问题讨论】:

  • 正如我在回答中所说的那样——你不能在 C 中这样做——你必须使用库或操作系统特定的调用(不是 INT 21——那些日子一去不复返了)。

标签: c input


【解决方案1】:

在 ANSI C 中没有办法制作可移植的行编辑器。如果您自己滚动,您将必须为您希望程序运行的每个新操作系统重新滚动它。

如果我可以提出建议,我会使用一个预先存在的库来完成所有困难的、特定于平台的肮脏工作,并通过这种方式学习如何处理诸如任意长度输入之类的事情.然后,当你的代码工作(并且很好)时,学习如何做所有那些肮脏的工作,并拿走图书馆的拐杖。这样一来,您就不会解决整个问题 - 您正在将其分解成更易于管理的部分。

即使这样也有点过于简单化了。我花了很长时间才学会如何处理任意长度的输入。

另外,要知道,如果你希望你的代码是可移植的,那么移除库依赖意味着,如果你想移植它,你必须要么 a) 重写所有脏活的代码,要么 b ) 重新添加库。

用一个笑话来结束这一切,这是你的大脑与图书馆:

Pigmaei gigantum humeris impositi plusquam ipsi gigantes viident。
(如果我看得更远,那就是站在巨人的肩膀上。)
--Isaac牛顿

这是你没有图书馆的大脑:

如果我没有看到其他人,那是因为巨人站在我的肩膀上。
--Hal Abelson

【讨论】:

    【解决方案2】:

    您说您想避免使用库(标准库或其他库),但不幸的是,在 C 中,所有输入和输出都是通过库执行的 - 该语言本身绝对没有输入/输出设施。

    所以你注定要使用某种库。鉴于您似乎想要一个文本界面,我建议您看看cursesPDCurses 的便携版。

    【讨论】:

    • PDCurses 是否比 ncurses 更便携?
    • 我只在windows上用过,没用过ncurses,所以真的不好评论。
    【解决方案3】:

    我写了一个文本编辑器。

    我从事 C 语言已有 20 年了。

    文本的数据结构是我写过的最复杂的单一数据结构;这是一种数据结构,可以按照您的指定有效地处理任意长度的文本。

    如果您是 C 的新手,那么您会咬牙切齿。

    我建议使用简单的数据结构,例如缓冲区或链表 - 您无法处理任意长度的文本,但总比没有好。

    【讨论】:

    • 好吧,我的想法是我可以一次读取一个字符,将其添加到缓冲区中,当缓冲区填满 realloc() 时,等等。但我没有知道该怎么做就是通过它退格...我会更新我的问题,我已经考虑了这个过程
    • realloc() 通常会将现有缓冲区 memcpy() 放入新缓冲区。这不是可扩展的。单行没问题 - 但如果你只有一行,为什么不只是 malloc() 1024 字节并完成它。
    • 如果我将每个 realloc() 的缓冲区大小加倍会怎样?这样它就会成倍增长......此外我发现最大的问题是能够编辑缓冲区中的文本
    • 对于平面缓冲区,直接的方法是,当添加或删除一个字符时,memcpy() 将插入/删除点右侧的缓冲区向上或向下加一。您可以想象,这很糟糕 :-) 但它很简单,并且对于小缓冲区是可以容忍的。
    【解决方案4】:

    这与系统(OS)高度相关。我认为您正在尝试在 Windows 上执行此操作。

    您可以使用Windows Console API 来执行此操作。

    如果你想研究一些库以供参考(在你自己动手之前),一个好的库是GNU Readline

    【讨论】:

    • 那个人指定他想自己动手。
    • Windows 控制台 API 是他自己开发的。 Readline 非常适合学习。
    • 好的,我会看看那个 API 并看看如何使用它,并阅读那个库来看看我如何实现它
    【解决方案5】:

    至于保存数据,我猜rope'将是可用的最佳数据结构:在简化形式中,它是一个字符串树。当您想在屏幕上打印它时,您需要做的就是预先订购并打印它。将一条线一分为二涉及一个相对简单的树操作:添加一个叶子。困难的部分是拆分字符串本身(复制字符串,将旧端设置为 0,添加叶子,添加指针)...

    现在,有一个跟踪光标的问题......你可以留下一个面包屑跟踪从根到光标当前所在的位置。

    还考虑了一个可调整大小的控制台...也就是说,如果您希望您的编辑器在终端是 80 或 200 个字符宽的情况下都能正常工作...

    【讨论】:

    • 当你加载一个单行文件时会发生什么,比如 10mb 长?你有一根绳子,它的一个元素包含一个 10mb 的绳子吗?如果是这样,当您从该字符串中删除第一个字符时会发生什么?一个 10mb 的内存?
    • 我从来没有真正使用过绳子;但我猜你可以首先确定叶字符串的最大长度(通常是 BUFSIZ,这对于任何与磁盘相关的东西来说都是一个很好的数字),然后一次读取一个块。
    猜你喜欢
    • 2014-12-24
    • 2014-10-09
    • 2017-09-16
    • 2013-03-24
    • 2011-06-05
    • 1970-01-01
    • 2015-06-10
    • 2013-03-20
    • 2015-05-12
    相关资源
    最近更新 更多