gpt4 book ai didi

c - 迭代机器代码时遇到问题

转载 作者:行者123 更新时间:2023-11-30 18:55:14 25 4
gpt4 key购买 nike

我正在尝试在 c 中重新创建 wc 命令,但在包含机器代码(核心文件或编译的 c)的任何文件中获取正确的单词数时遇到问题。记录的单词数总是比 wc 返回的单词数少 90% 左右。

这里是项目信息供引用

编译语句

gcc -ggdb wordCount.c -o wordCount -std=c99

wordCount.c

/*
* Author(s) - Colin McGrath
* Description - Lab 3 - WC LINUX
* Date - January 28, 2015
*/

#include<stdio.h>
#include<string.h>
#include<dirent.h>
#include<sys/stat.h>
#include<ctype.h>

struct counterStruct {
int newlines;
int words;
int bt;
};

typedef struct counterStruct ct;

ct totals = {0};

struct stat st;

void wc(ct counter, char *arg)
{
printf("%6lu %6lu %6lu %s\n", counter.newlines, counter.words, counter.bt, arg);
}

void process(char *arg)
{
lstat(arg, &st);
if (S_ISDIR(st.st_mode))
{
char message[4056] = "wc: ";
strcat(message, arg);
strcat(message, ": Is a directory\n");
printf(message);
ct counter = {0};
wc(counter, arg);
}
else if (S_ISREG(st.st_mode))
{
FILE *file;
file = fopen(arg, "r");
ct currentCount = {0};
if (file != NULL)
{
char holder[65536];
while (fgets(holder, 65536, file) != NULL)
{
totals.newlines++;
currentCount.newlines++;
int c = 0;
for (int i=0; i<strlen(holder); i++)
{
if (isspace(holder[i]))
{
if (c != 0)
{
totals.words++;
currentCount.words++;
c = 0;
}
}
else
c = 1;
}
}
}
currentCount.bt = st.st_size;
totals.bt = totals.bt + st.st_size;
wc(currentCount, arg);
}
}

int main(int argc, char *argv[])
{
if (argc > 1)
{
for (int i=1; i<argc; i++)
{
//printf("%s\n", argv[i]);
process(argv[i]);
}
}

wc(totals, "total");

return 0;
}

厕所输出示例:

    135     742  360448 /home/cpmcgrat/53/labs/lab-2/core.22321
231 1189 192512 /home/cpmcgrat/53/labs/lab-2/core.26554
5372 40960 365441 /home/cpmcgrat/53/labs/lab-2/file
24 224 12494 /home/cpmcgrat/53/labs/lab-2/frequency
45 116 869 /home/cpmcgrat/53/labs/lab-2/frequency.c
5372 40960 365441 /home/cpmcgrat/53/labs/lab-2/lineIn
12 50 1013 /home/cpmcgrat/53/labs/lab-2/lineIn2
0 0 0 /home/cpmcgrat/53/labs/lab-2/lineOut
39 247 11225 /home/cpmcgrat/53/labs/lab-2/parseURL
138 318 2151 /home/cpmcgrat/53/labs/lab-2/parseURL.c
41 230 10942 /home/cpmcgrat/53/labs/lab-2/roman
66 162 1164 /home/cpmcgrat/53/labs/lab-2/roman.c
13 13 83 /home/cpmcgrat/53/labs/lab-2/romanIn
13 39 169 /home/cpmcgrat/53/labs/lab-2/romanOut
7 6 287 /home/cpmcgrat/53/labs/lab-2/URLs
11508 85256 1324239 total

重建输出示例(./wordCount):

   139     76 360448 /home/cpmcgrat/53/labs/lab-2/core.22321
233 493 192512 /home/cpmcgrat/53/labs/lab-2/core.26554
5372 40960 365441 /home/cpmcgrat/53/labs/lab-2/file
25 3 12494 /home/cpmcgrat/53/labs/lab-2/frequency
45 116 869 /home/cpmcgrat/53/labs/lab-2/frequency.c
5372 40960 365441 /home/cpmcgrat/53/labs/lab-2/lineIn
12 50 1013 /home/cpmcgrat/53/labs/lab-2/lineIn2
0 0 0 /home/cpmcgrat/53/labs/lab-2/lineOut
40 6 11225 /home/cpmcgrat/53/labs/lab-2/parseURL
138 318 2151 /home/cpmcgrat/53/labs/lab-2/parseURL.c
42 3 10942 /home/cpmcgrat/53/labs/lab-2/roman
66 162 1164 /home/cpmcgrat/53/labs/lab-2/roman.c
13 13 83 /home/cpmcgrat/53/labs/lab-2/romanIn
13 39 169 /home/cpmcgrat/53/labs/lab-2/romanOut
7 6 287 /home/cpmcgrat/53/labs/lab-2/URLs
11517 83205 1324239 total

请注意前两个文件(核心文件)以及 roman 文件和 parseURL 文件(机器代码,无扩展名)的字数(第二个整数)的差异。

最佳答案

C 字符串不存储其长度。它们由一个 NUL 终止。 (0) 字节。

因此,strlen需要逐字符扫描整个字符串,直到到达 NUL 。这使得:

for (int i=0; i<strlen(holder); i++)

效率极低:对于 holder 中的每个字符,需要统计 holder 中的所有字符为了测试是否 i仍在范围内。这转换了一个简单的线性 Θ(N)算法转化为Θ(N<sup>2</sup>)循环燃烧器。

但在这种情况下,它也会产生错误的结果,因为二进制文件通常包含大量 NUL人物。自 strlen实际上会告诉你第一个NUL在哪里是,而不是“行”有多长,您最终会跳过文件中的很多字节。 (好的一面是,这使得扫描速度成倍加快,但更快地计算错误结果并不是真正的胜利。)

您不能使用fgets读取二进制文件,因为 fgets界面不会告诉您它读取了多少内容。您可以使用 Posix 2008 getline接口(interface),或者您可以使用 fread 进行二进制输入,这更有效,但会迫使您自己计算换行符。 (这不是世界上最糟糕的事情;你似乎也算错了。)

或者,当然,您可以使用 fgetc 一次读取一个字符。 。对于学校练习来说,这不是一个坏的解决方案。生成的代码很容易编写和理解,典型的实现是 fgetc比 FUD 所显示的更有效率。

关于c - 迭代机器代码时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28204948/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com