我有一个名为 unscramble
的代码,它接受两个文件 Jumbled.txt
和 dictionary.txt
并查找两个文件中是否有任何单词包含相同的字符,例如,这是
Jumbled.txt:
Hello
Wassup
Rigga
Boyka
Popeye
dictionary.txt:
olleH
Yello
elloH
lloeH
aggiR
ggiRa
giRag
yokaB
Bakoy
kaBoy
eyePop
poePye
上面代码的输出是:
Hello: olleH elloH lloeH
Wassup: NO MATCHES
Rigga: aggiR ggiRa giRag
Boyka: yokaB Bakoy kaBoy
Popeye: eyePop poePye
这是我试图解决它的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_WORD_LENGTH 50
#define MAX_NUM_WORDS 500000
int compare_char(const void *a, const void *b) {
return *(char*)a - *(char*)b;
}
void sort_word(char *word) {
qsort(word, strlen(word), sizeof(char), compare_char);
}
int is_valid_word(char *jumbled_word, char *word) {
char sorted_jumbled_word[MAX_WORD_LENGTH];
char sorted_word[MAX_WORD_LENGTH];
strcpy(sorted_jumbled_word, jumbled_word);
strcpy(sorted_word, word);
sort_word(sorted_jumbled_word);
sort_word(sorted_word);
return strcmp(sorted_jumbled_word, sorted_word) == 0;
}
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Usage: unscramble <dictionary> <jumbles>\n");
exit(1);
}
char *dict_filename = argv[1];
char *jumbles_filename = argv[2];
char dictionary[MAX_NUM_WORDS][MAX_WORD_LENGTH];
int num_words = 0;
FILE *dict_file = fopen(dict_filename, "r");
if (dict_file == NULL) {
printf("Error: Could not open dictionary file %s\n", dict_filename);
exit(1);
}
char line[MAX_WORD_LENGTH];
while (fgets(line, sizeof(line), dict_file) != NULL) {
// Remove trailing newline character
line[strcspn(line, "\n")] = '\0';
// Copy word into dictionary
strcpy(dictionary[num_words], line);
num_words++;
}
fclose(dict_file);
// Loop over jumbled words file
FILE *jumbles_file = fopen(jumbles_filename, "r");
if (jumbles_file == NULL) {
printf("Error: Could not open jumbled words file %s\n", jumbles_filename);
exit(1);
}
while (fgets(line, sizeof(line), jumbles_file) != NULL) {
line[strcspn(line, "\n")] = '\0';
char sorted_word[MAX_WORD_LENGTH];
strcpy(sorted_word, line);
sort_word(sorted_word);
int found_match = 0;
for (int i = 0; i < num_words; i++) {
if (is_valid_word(sorted_word, dictionary[i])) {
if (!found_match) {
printf("%s:", line);
found_match = 1;
}
printf(" %s", dictionary[i]);
}
}
if (!found_match) {
printf("%s: NO MATCHES", line);
}
printf("\n");
}
fclose(jumbles_file);
return 0;
}
但是,将其转换为可执行格式并检查同一目录中是否存在 Jumbled.txt AND dictionary.txt 后,我收到此错误消息:
xxxxxxxxx@LAPTOP-xxxxxxxx:~$ gcc -Wall -W -pedantic -o unscramble unscramble.c
xxxxxxxxx@LAPTOP-xxxxxxxx:~$ vim Jumbled.txt
xxxxxxxxx@LAPTOP-xxxxxxxx:~$ vim dictionary.txt
xxxxxxxxx@LAPTOP-xxxxxxxx:~$ vim unscramble.c
xxxxxxxxx@LAPTOP-xxxxxxxx:~$ ./unscramble dictionary.txt Jumbled.txt
Segmentation fault
xxxxxxxxx@LAPTOP-xxxxxxxx:~$
我应该改变什么,我的问题是什么?
第一步是在调试器中运行您的程序以找出它的段错误:
Program received signal SIGSEGV, Segmentation fault.
0x00005555555552c6 in main (argc=<error reading variable: Cannot access memory at address 0x7ffffe82657c>, argv=<error reading variable: Cannot access memory at address 0x7ffffe826570>) at 1.c:26
26 int main(int argc, char *argv[]) {
这很奇怪,即内存损坏,甚至在开始之前,所以您查看分配并看到:
char dictionary[MAX_NUM_WORDS][MAX_WORD_LENGTH];
500k * 50 字节或 25 MB。我系统上的默认堆栈是 8 MB。要么减少常量,这样您就不会使用超过 8 MB,要么使用 malloc()
来分配堆上的空间。我在这里使用一维数组:
char (*dictionary)[MAX_WORD_LENGTH] = malloc(MAX_NUM_WORDS * sizeof(*dictionary));
if(!dictionary) {
printf("malloc failed\n");
return 1;
}
现在返回:
Hello: olleH elloH lloeH
Wassup: NO MATCHES
Rigga: aggiR ggiRa giRag
Boyka: yokaB Bakoy kaBoy
Popeye: eyePop poePye
您将 dictionary
数组放入 main
中,因此该数组将存在于 main
的函数堆栈中;这大约是堆栈上的 23.8M,超过了几乎所有操作系统的通常堆栈大小限制(Linux 上为 8M)。
如果您仍然想使用二维数组,请将此数组作为全局变量放在 main
之外,这样它就不会再存在于 main
的栈帧中了。或者使用 malloc
分配这个数组,所以它存在于程序的堆中。请参阅堆栈和堆是什么以及在哪里?