Stdin + 字典文本替换工具 -- 调试
Stdin + Dictionary Text Replacement Tool -- Debugging
我正在处理一个项目,其中有两个主要文件。本质上,该程序读取一个文本文件,该文件定义了一个具有键值映射的字典。每个键都有一个唯一的值,文件格式如下,其中每个键值对都在其自己的行上:
ipsum i%#@!
fubar fubar
IpSum XXXXX24
Ipsum YYYYY211
然后程序从 stdin 读取输入,如果任何“单词”与字典文件中的键匹配,它们将被替换为值。大写和小写有点不同——这是“匹配优先级”的顺序
- 确切的单词在替换集中
- 除了第一个字符以外的所有字符都转换为小写的单词在替换集中
- 完全转换为小写的单词在替换集中
意思是如果字典中有确切的词,它就会被替换,但如果没有,则检查下一个可能性 (2),依此类推...
我的程序通过了我们提供的基本案例,但随后终端显示
输出与参考二进制文件不同。
我进入了两个文件(不是 c 文件,而是二进制文件),一个超长,有很多数字,另一个只有一行随机字符。所以这并没有真正的帮助。我还检查了我的代码并进行了一些小测试,但似乎没问题?一位朋友建议我确保我正在考虑 processInput() 中的 null 运算符,而我已经这样做了(或者至少我是这么认为的,如果我错了请纠正我)。我还将 getchar() 转换为 int 以正确检查 EOF,并为 char 数组分配了额外的 space。我也尝试了 vimdiff
并且变得更加困惑。请帮我调试一下!我弄了一整天,我很困惑。
首先使用以下方法测试您的分词器:
$ ./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);
}
我只修复了你的分词器,遗漏了哈希 table 和搜索与替换的东西。现在应该生成输入的逐字副本。 (这很愚蠢,但非常适合测试)
如果要允许二进制输入,则不能使用 while((ch = getchar()) ...)
:输入中的 NUL 会导致循环结束。您必须推迟对 EOF 的测试,因为它们可能仍然是您缓冲区中的最终决定 ...&& ch != EOF)
在这里把 EOF 当作 space 对待:它可以是一个词的结尾
你也必须为 NUL ('\0') 保留 space。
if (len==0) 就没有字了,不用查了
我们像对待 space 一样对待 EOF,但我们不想将其写入输出。是时候打破循环了。
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);
中的演员表无用且令人困惑。
其余代码中存在一些小问题,但none应该会导致问题。
我正在处理一个项目,其中有两个主要文件。本质上,该程序读取一个文本文件,该文件定义了一个具有键值映射的字典。每个键都有一个唯一的值,文件格式如下,其中每个键值对都在其自己的行上:
ipsum i%#@!
fubar fubar
IpSum XXXXX24
Ipsum YYYYY211
然后程序从 stdin 读取输入,如果任何“单词”与字典文件中的键匹配,它们将被替换为值。大写和小写有点不同——这是“匹配优先级”的顺序
- 确切的单词在替换集中
- 除了第一个字符以外的所有字符都转换为小写的单词在替换集中
- 完全转换为小写的单词在替换集中
意思是如果字典中有确切的词,它就会被替换,但如果没有,则检查下一个可能性 (2),依此类推...
我的程序通过了我们提供的基本案例,但随后终端显示 输出与参考二进制文件不同。
我进入了两个文件(不是 c 文件,而是二进制文件),一个超长,有很多数字,另一个只有一行随机字符。所以这并没有真正的帮助。我还检查了我的代码并进行了一些小测试,但似乎没问题?一位朋友建议我确保我正在考虑 processInput() 中的 null 运算符,而我已经这样做了(或者至少我是这么认为的,如果我错了请纠正我)。我还将 getchar() 转换为 int 以正确检查 EOF,并为 char 数组分配了额外的 space。我也尝试了 vimdiff
并且变得更加困惑。请帮我调试一下!我弄了一整天,我很困惑。
首先使用以下方法测试您的分词器:
$ ./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);
}
我只修复了你的分词器,遗漏了哈希 table 和搜索与替换的东西。现在应该生成输入的逐字副本。 (这很愚蠢,但非常适合测试)
如果要允许二进制输入,则不能使用
while((ch = getchar()) ...)
:输入中的 NUL 会导致循环结束。您必须推迟对 EOF 的测试,因为它们可能仍然是您缓冲区中的最终决定...&& ch != EOF)
在这里把 EOF 当作 space 对待:它可以是一个词的结尾
你也必须为 NUL ('\0') 保留 space。
if (len==0) 就没有字了,不用查了
我们像对待 space 一样对待 EOF,但我们不想将其写入输出。是时候打破循环了。
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);
中的演员表无用且令人困惑。
其余代码中存在一些小问题,但none应该会导致问题。