C语言 Stdin +字典文本替换工具-调试



我正在处理一个项目,其中我有两个主要文件。本质上,程序读入一个文本文件,该文件定义了一个具有键值映射的字典。每个键都有一个唯一的值,文件的格式如下,其中每个键值对都在自己的行上:

ipsum i%#@!
fubar fubar
IpSum XXXXX24
Ipsum YYYYY211

然后程序从stdin读入输入,如果其中任何一个"字"匹配字典文件中的键,它们被替换为值。大小写有个小问题——这是"match priority">

"的顺序。
  1. 确切的单词在替换集
  2. 在替换集
  3. 中,除第一个字符外所有字符都转换为小写的单词
  4. 完全转换为小写的单词在替换集

意思是如果这个词在字典中,它将被替换,但如果没有,则检查下一个可能性(2),依此类推…

我的程序通过了我们提供的基本案例,但随后终端显示输出与引用二进制文件不同

我打开了两个文件(不是c文件,而是二进制文件),其中一个非常长,有大量的数字,而另一个只有一行随机字符。所以这并没有什么帮助。我也审查了我的代码,并做了一些小测试,但它似乎还好吗?一个朋友建议我确保我在processInput()中考虑空操作符,我已经是(或者至少我认为是这样,如果我错了,请纠正我)。我还将getchar()转换为int以正确检查EOF,并为char数组分配了额外的空间。我也试过vimdiff,更困惑了。我希望有一些帮助调试这个,请!我一整天都在做这件事,我很困惑。

processInput()函数存在多个问题:

  • 当字节读取为0时循环不应该停止,你应该处理完整的输入:

    while ((ch = getchar()) != EOF)
    
  • EOF的测试实际上应该以不同的方式完成,以便文件的最后一个单词得到处理的机会,如果它恰好发生在文件的末尾。

  • isalnum((char)ch)中的强制转换是不正确的:您应该将ch直接传递给isalnum。将字节值转换为char实际上是适得其反的,因为它会将超过CHAR_MAX的字节值转换为负值,而isalnum()具有未定义的行为。

  • 测试if(ind >= cap)太松散:如果word包含cap字符,将空终止符设置在word[ind]将写入超出数组的末尾。将测试更改为if (cap - ind < 2),以允许在任何时候都有一个字节和一个空终止符。

  • 您应该检查单词中至少有一个字符,以避免使用空字符串调用checkData()

  • char key[ind + 1];是无用的:你可以把word传递给checkData()

  • checkData(key, ind)是不正确的:你应该为大小写转换传递缓冲区的大小,它至少是ind + 1以允许空终止符。

  • putchar((char)ch);中的强制转换是无用的和令人困惑的。

在代码的其余部分有一些小问题,但没有一个应该引起问题。

首先使用以下命令测试标记器:

$ ./a.out <badhash2.c >zooi
$ diff badhash2.c zooi
$

它也适用于二进制文件吗?:

$ ./a.out <./a.out > zooibin
$ diff ./a.out zooibin
$

是的,它有!


#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
void processInput(void);
int main(int argc, char **argv) {
processInput();
return 0;
}
void processInput() {
int ch;
char *word;
int len = 0;
int cap = 60;
word = malloc(cap);
while(1) {
ch = getchar();                 // (1)
if( ch != EOF && isalnum(ch)) { // (2)
if(len+1 >= cap) {          // (3)
cap += cap/2;
word = realloc(word, cap);
}
word[len++] = ch;
} else {
if (len) {                  // (4)
#if 0
char key[len + 1]; 
memcpy(key, word, len); key[len] = 0; 
checkData(key, len); 
#else
word[len] = 0;
fputs(word, stdout); 
#endif
len = 0; 
}
if (ch == EOF) break;      // (5)
putchar(ch); 
}
}
free(word);
}


我只修复了你的标记器,遗漏了哈希表和搜索&替代的东西。它现在应该生成输入的逐字副本。(这是愚蠢的,但很适合测试)

  1. 如果你想允许二进制输入,你不能使用while((ch = getchar()) ...):输入中的NUL会导致循环结束。您必须推迟EOF的测试,因为在您的缓冲区...&& ch != EOF)

    中仍然可能有一个最终的单词。
  2. 把EOF当作空格:它可以是一个单词的结尾

  3. 您也必须为NUL('')保留空间。

  4. if (len==0)将没有单词,所以不需要查找。

  5. 我们把EOF当作一个空格,但是我们不想把它写到输出中。是时候跳出这个循环了

相关内容

  • 没有找到相关文章

最新更新