ORIGINAL:练习1.18 of Kernighan和Ritchie的 C编程语言要求读者编写一个程序,从每行输入中删除尾随空格和制表符,并且删除完全空行。如果决定将输入的最大长度或空白和制表符的序列限制为某个预定大小,则练习相对容易:只需缓冲输入行或空白和制表符序列;如果输入或某些空白和制表符序列超过预定大小,则程序失败。但是,这只是练习的部分解决方案。
问题是Kernighan和Ritchie没有引入指针或结构,因此动态分配内存非常棘手。对于像我这样的初学者来说,它很棘手,我无法使用文本中此处提供的工具模仿动态内存分配。我写了一个使用不可用工具的解决方案,但想知道是否只使用那些可用的练习的一般解决方案。作为参考,我还尝试使用递归来生成一系列函数调用,这些函数调用依赖于后续函数调用的成功或失败,但是无法通过调用堆栈传播必要的信息。我还考虑过编写一个库来编码空白和制表符序列作为整数;唉,积分类型有大小。
因此,我的问题是:是否可以编写一个程序,只使用 C语言中练习1.18的语句引入的工具,从每个输入行中删除尾随空白和制表符?< / p>
编辑:我刚刚发现整数类型的大小取决于实现。因此,我认为没有理由相信依赖于整数大小的程序不满足问题规范。这似乎与相关问题非常相似,例如程序必须在具有有限内存量的计算机上运行。这当然消除了这个问题,但感觉有点像作弊。
答案 0 :(得分:3)
如评论中所述,可用的工具包括:函数,变量; for
和while
次循环; (固定大小)数组;函数putchar
和getchar
;基本类型和定义。这意味着文件IO操作不可用。
鉴于这些工具,我认为你不能为每个任意文件解决问题;可用的工具不足。
例如,您可以通过记录您读取的最后一个非空白字符的位置来复制整个文件,然后读取数十亿字节的空白和标签(不写任何内容),然后找到一个数字。那时候,你会回到你开始阅读空白和标签的地方,并且知道(如果你正在处理它的时候没有其他任何东西改变了文件)那么你要找到数字,所以你要复制它们需要将数十亿个空格和制表符复制到输出文件中。 (如果你遇到一个换行而不是一个数字,那么你当然只输出换行符。)但这需要一个搜索操作 - 不允许。它还需要可寻找的输入;并非所有输入都是可寻找的(管道,终端)。由于更常规的文件IO操作不可用,因此无法解决问题。
您可以编写一个程序,可以正确处理多达一百万个连续空格或制表符,但会从包含超过一百万个连续行(或复制它们)的行中删除空白块或制表符块。但对于十亿个连续的空白或标签示例来说,这将是错误的。对于任何固定大小,有一个更大的尺寸会破坏程序。
所以,IMNSHO,你不能用你可用的工具做你想做的事。这并非完全不合理;第1章是对C的快速介绍 - 它不会让你能够处理你在每个C程序中可能遇到的每一个异常情况。
答案 1 :(得分:1)
我只能回答这个问题,因为你把它作为我的Kernighan&amp;里奇是第二版(1988年),没有练习。
是的,对于每个输入行,循环遍历字符串并检查字符串的最后一个字符。 strlen(str)给出字符串中当前字符的数量。使用length-1作为索引(从零开始)。如果它不是一个空间突破循环。如果是空格或制表符,请将其替换为“\ 0”。如果每个字符都被删除,你当然会退出循环。
退出循环后,如果长度为0,则删除该行。
我会将明确的代码留给您,但您可以使用一段时间。
根据您的问题,for或while似乎是正在测试的内容。如果你使用read命令的numread作为长度,那么再次假设这是一个大的(足够的)缓冲区,输入是一个完整的字符串,并且你要把'\ 0'字符放在最后找到的实际字符串。在这种情况下,从numread开始,并为您向后移动时找到的每个空格或制表符添加'\ 0'。这也假设输入都是有效的ascii字符,这样你就找不到'\ 0'或其他nonascii字符,这些字符会使你的输入不是一个字符串。
我现在看到你正在使用getchar和putchar。在这种情况下,假设一个大(足够)的缓冲区,使用getchar,直到你看到'\ n'或获得一个EOF。然后遍历你现在拥有的那条线(再次在这个开头,你必须假设你有足够的空间)并将'\ n'返回到前一个空格或制表符,并使'\ n'成为'\ 0'
使用putchar作为你现在拥有的字符串的大小。
由于这是一个开始练习,您不必担心大量的缓冲区大小。练习旨在仅假设正在测试的内容。
答案 2 :(得分:1)
您可以通读文件,逐个字符地复制。每当你偶然发现一段空间时,要算出你发现的数量。如果它们以'\n'
结束,只输出'\n'
,否则写下看到的空格数并继续复制。如果空间的延伸位于一条线的开头,请记住;如果该行是完全空白的,则不要写出'\n'
。
警惕Kernighan,Ritchie,Pike,Bentley和所有人群。他们有一个不可思议的诀窍来编写你会阅读的代码并且看得很明显。只有在稍后您才发现它们(以及其他人)花了年来获得这样一个简单的解决方案。你永远不会写那个,而不是一辈子。