gpt4 book ai didi

c - 在 C 中检测数组的行并查找两个数组的共同词

转载 作者:行者123 更新时间:2023-11-30 15:32:33 26 4
gpt4 key购买 nike

我有一个名为 a1.txt 的文件,其中包含以下单词

太棒了
恶毒的
永久

另一个名为a2.txt,其中

太棒了

恶意

这是我用来将文件读入数组的代码,感谢 @M Oehm。

注意:void b();void a() 相同,但它读取的是 a2.txt

void a();
void b();
char (*a1)[50];
char (*a2)[50];
int n;


int main(int argc, char *argv[]) {
a();
printf("\n\n");
b();
int i=0, j=0;
for (i; i < strlen(*a1); i++)
{
for (j; j <strlen(*a2); j++)
{
printf("\n%d", strcmp(a1[i], a2[j]));
}
}
return 0;
}

void a(){
FILE *f;
int i;

f = fopen("a1.txt", "r");
if (f == NULL) {
fprintf(stderr, "Can't open file\n");
exit(1);
}

/* first pass */
n = 0;
while (fscanf(f, "%*s") != EOF) n++; /* star means: scan, but don't store */

a1 = malloc((n + 1) * sizeof(*a1));
if (a1 == NULL) {
fprintf(stderr, "Allocation failed\n");
exit(1);
}

/* second pass */
fseek(f, 0, SEEK_SET);
for (i = 0; i < n; i++) {
fscanf(f, "%49s", a1[i]);
}
*a1[n] = '\0';

/* process words */
for (i = 0; i < n; i++) {
printf("%s\n",a1[i]);
}}

正如您所看到的,数组的行是动态的(我使用了三个单词作为测试,但是这应该针对未知数量的单词来完成,因此需要使用calloc)。是否可以检测每个数组的行并将每个数组的常用字写入新文件中?我认为使用 strstr 查找常用单词是一件简单的事情。

最佳答案

您似乎对内存分配有一些误解:

  • char *str[50] 创建一个包含 50 个(未初始化)char 指针的数组。也许您需要 char (*str)[50],它是一个指向 50 个字符的数组的指针,您可以为其分配内存。

  • lSize 是文件的长度,即字符数。看起来有点像你想计算单词数。

我将介绍两种将单词读入字符数组的策略。

读取固定大小的单词

此策略使用固定字长 50,如您的示例所示。它打开文件并分两遍读取它。首先确定字数,接下来分配足够的空间后读取实际字数。

int main(int argc, char *argv[])
{
FILE *f;
char (*str)[50]; /* Pointer to words of max length 49 */
int n; /* number of words */
int i;

if (argc != 2) {
fprintf(stderr, "Usage: $fifo file_name.ip\n");
exit(1);
}

f = fopen(argv[1], "r");
if (f == NULL) {
fprintf(stderr, "Can't open file\n");
exit(1);
}

/* first pass */
n = 0;
while (fscanf(f, "%*s") != EOF) n++; /* star means: scan, but don't store */

str = malloc((n + 1) * sizeof(*str));
if (str == NULL) {
fprintf(stderr, "Allocation failed\n");
exit(1);
}

/* second pass */
fseek(f, 0, SEEK_SET);
for (i = 0; i < n; i++) {
fscanf(f, "%49s", str[i]);
}
*str[n] = '\0';

/* process words */
for (i = 0; i < n; i++) {
printf("%4d: '%s'\n", i, str[i]);
}
free(str);

return 0;
}

这种方法相当简单,但有两个缺点: 您会浪费内存,因为大多数单词的长度不会是 50 个字符。而且你必须扫描文件两次。这两个缺点在现代计算机上并不严重。

随用随分配

您还可以将单词维护为指向 char、char **str 的指针。 str[i] 为您提供一个单词,该单词作为指针存储到以 null 结尾的字符串的现有内存中。函数 strtok 为您提供这样的字符串。

这个“现有内存”是作为字符缓冲区的文件内容。 Rohan 向您展示了如何获取 ti:通过获取文件长度、分配和读取。

此方法只需要一次传递,因为它会根据需要重新分配内存。从 64 个单词的空间开始,阅读它们,发现我们需要更多,因此重新分配以容纳 128 个单词,阅读单词 64-127,依此类推。

int main(int argc, char *argv[])
{
FILE *f;
char *buf; /* Buffer that hold the file's contets */
size_t size; /* Size of that buffer */
char **str; /* Array of pointers to words in that buffer */
int n; /* number of words */
int nalloc; /* For how many words space is allocated */
int i;

if (argc != 2) {
fprintf(stderr, "Usage: $fifo file_name.ip\n");
exit(1);
}

f = fopen(argv[1], "r");
if (f == NULL) {
fprintf(stderr, "Can't open file\n");
exit(1);
}

fseek(f, 0, SEEK_END);
size = ftell(f);
fseek(f, 0, SEEK_SET);

buf = malloc(size + 1);
if (buf == NULL) {
fprintf(stderr, "Allocation failed\n");
exit(1);
}

/* read whoe file */
fread(buf, 1, size, f);
buf[size] = '\0';
fclose(f);

n = 0;
nalloc = 0;
str = NULL;

for (;;) {
if (n >= nalloc) {
/* reallocate */
nalloc = nalloc * 2;
if (nalloc == 0) nalloc = 64;
str = realloc(str, nalloc * sizeof(*str));
if (str == NULL) {
fprintf(stderr, "Reallocation failed\n");
exit(1);
}
}
str[n] = strtok(n ? NULL : buf, " \t\n\r");
if (str[n] == NULL) break;
n++;
}

/* process words */
for (i = 0; i < n; i++) {
printf("%4d: '%s'\n", i, str[i]);
}
free(buf);
free(str);

return 0;
}

这种方法更有效,但也更复杂。请注意我需要多少个变量来跟踪所有内容:分配的大小、实际大小、文本缓冲区的大小。而且我必须处理两个分配的数组。

鉴于您想要读取两个个文件,将这些变量打包到一个结构中并将每个文件读取到这样的结构中是有意义的。

结论

这些只是从文件中读取单词的多种方法中的两种。两者都不是微不足道的,需要您了解如何管理内存。

我认为要学习的最基本的事情之一是指针可以用于许多不同的事情。它可以只指向现有的内存,无论是已分配的内存还是自动数组。但它也可以用作已分配内存的句柄;然后它的行为就像一个数组,只不过你必须在使用后释放内存。您不应该“移动”此类指针,即更改它们指向的地址。

两种指针在代码中看起来相同,但您必须知道哪个指针充当什么。

关于c - 在 C 中检测数组的行并查找两个数组的共同词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24189663/

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