英文:
How can I call my function as a command line without segmentation fault?
问题
It appears you've made some improvements to your code, but you're still encountering a segmentation fault issue. The code you provided looks mostly correct. However, there's a small issue with the printf
statements where you are using HTML entities ("
) for double quotes. You should replace these with regular double quotes ("
).
Here's the corrected code:
#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 *(const char*)a - *(const char*)b;
}
void sort_word(char *word) {
qsort(word, strlen(word), sizeof(char), compare_char);
}
int is_valid_word(const char *jumbled_word, const 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");
return 1;
}
char *dict_filename = argv[1];
char *jumbles_filename = argv[2);
char (*dictionary)[MAX_WORD_LENGTH] = malloc(MAX_NUM_WORDS * sizeof(*dictionary));
if (!dictionary) {
printf("Error: malloc failed\n");
return 1;
}
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);
return 1;
}
char line[MAX_WORD_LENGTH];
while (fgets(line, sizeof(line), dict_file) != NULL && num_words < MAX_NUM_WORDS) {
// Remove trailing newline character
line[strcspn(line, "\n")] = '\0';
// Copy word into dictionary
strncpy(dictionary[num_words], line, MAX_WORD_LENGTH - 1);
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);
return 1;
}
while (fgets(line, sizeof(line), jumbles_file) != NULL) {
// Remove trailing newline character
line[strcspn(line, "\n")] = '\0';
if (strlen(line) > MAX_WORD_LENGTH - 1) {
printf("Error: Jumbled word %s is too long\n", line);
continue;
}
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);
free(dictionary);
return 0;
}
With these corrections, your code should work as intended without the segmentation fault issue.
英文:
I have a code called unscramble
that takes two files, Jumbled.txt
and dictionary.txt
and finds if any words contain the same characters in both the files or not, for instance, here is a sample input for
Jumbled.txt:
Hello
Wassup
Rigga
Boyka
Popeye
dictionary.txt:
olleH
Yello
elloH
lloeH
aggiR
ggiRa
giRag
yokaB
Bakoy
kaBoy
eyePop
poePye
and the output of the code above is:
Hello: olleH elloH lloeH
Wassup: NO MATCHES
Rigga: aggiR ggiRa giRag
Boyka: yokaB Bakoy kaBoy
Popeye: eyePop poePye
Here is my code that attempts to solve it:
#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;
}
However, after converting it into executable format and checking that Jumbled.txt AND dictionary.txt is available in the same directory, I get this error message:
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:~$
what should I change and what is my problem?
Edit What I have so far:
#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 *(const char*)a - *(const char*)b;
}
void sort_word(char *word) {
qsort(word, strlen(word), sizeof(char), compare_char);
}
int is_valid_word(const char *jumbled_word, const 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");
return 1;
}
char *dict_filename = argv[1];
char *jumbles_filename = argv[2];
char (*dictionary)[MAX_WORD_LENGTH] = malloc(MAX_NUM_WORDS * sizeof(*dictionary));
if(!dictionary) {
printf("Error: malloc failed\n");
return 1;
}
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);
return 1;
}
char line[MAX_WORD_LENGTH];
while (fgets(line, sizeof(line), dict_file) != NULL && num_words < MAX_NUM_WORDS) {
// Remove trailing newline character
line[strcspn(line, "\n")] = '\0';
// Copy word into dictionary
strncpy(dictionary[num_words], line, MAX_WORD_LENGTH - 1);
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);
return 1;
}
while (fgets(line, sizeof(line), jumbles_file) != NULL) {
// Remove trailing newline character
line[strcspn(line, "\n")] = '\0';
if (strlen(line) > MAX_WORD_LENGTH - 1) {
printf("Error: Jumbled word %s is too long\n", line);
continue;
}
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);
free(dictionary);
return 0;
}
答案1
得分: 4
以下是翻译好的部分:
"The first step is to run your program in a debugger to figure out where it segfaults" :
"第一步是在调试器中运行您的程序,找出它在哪里出现分段错误:"
$ gdb ./unscramble
(gdb) set args dictionary.txt Jumbled.txt
(gdb) r
(gdb) bt
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[]) {"
这是奇怪的,即内存损坏,甚至在开始之前,所以您查看分配并看到:
"这是奇怪的,即内存损坏,即使在开始之前也是如此,因此您查看分配并看到:"
which is 500k * 50 bytes or 25 MB. The default stack on my system is 8 MB. You could up your stack size with, say, ulimit -s 30000
, and your program would run as it. It would be better to reduce memory usage, or use malloc()
to allocate space on the heap instead:
"这是500k * 50字节,或25 MB。我的系统上的默认堆栈大小为8 MB。您可以使用ulimit -s 30000
来增加堆栈大小,这样您的程序就可以运行。最好减少内存使用,或者改用malloc()
来在堆上分配空间:"
if(!dictionary) {
printf("malloc failed\n");
return 1;
}
// ...
free(dictionary);
and it now returns:
"现在它返回:"
Wassup: NO MATCHES
Rigga: aggiR ggiRa giRag
Boyka: yokaB Bakoy kaBoy
Popeye: eyePop poePye"
英文:
The first step is to run your program in a debugger to figure out where it segfaults:
$ gcc -g3 -Wall -W -pedantic -o unscramble unscramble.c
$ gdb ./unscramble
(gdb) set args dictionary.txt Jumbled.txt
(gdb) r
(gdb) bt
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[]) {
This is strange, i.e. memory corruption, before even starting, so you look at allocations and you see:
char dictionary[MAX_NUM_WORDS][MAX_WORD_LENGTH];
which is 500k * 50 bytes or 25 MB. The default stack on my system is 8 MB. You could up your stack size with, say, ulimit -s 30000
, and your program would run as it. It would be better to reduce memory usage, or use malloc()
to allocate space on the heap instead:
char (*dictionary)[MAX_WORD_LENGTH] = malloc(MAX_NUM_WORDS * sizeof(*dictionary));
if(!dictionary) {
printf("malloc failed\n");
return 1;
}
// ...
free(dictionary);
and it now returns:
Hello: olleH elloH lloeH
Wassup: NO MATCHES
Rigga: aggiR ggiRa giRag
Boyka: yokaB Bakoy kaBoy
Popeye: eyePop poePye
答案2
得分: 1
你将dictionary
数组放在main
函数中,所以这个数组将存在于main
函数的栈上;这在栈上大约占用了23.8M的空间,超出了几乎所有操作系统的通常栈大小限制(在Linux上为8M)。
如果你仍然想要使用二维数组,请将该数组放在main
函数外部作为全局变量,这样它就不再存在于main
的栈帧中。或者使用malloc
来分配这个数组,使它存在于程序的堆中。请参考栈和堆是什么,它们位于哪里?。
英文:
You put the dictionary
array in main
, so this array is going to live on main
' s function stack; that's approximately 23.8M on the stack, over the usual stack size limit of almost all the operating systems (8M on Linux).
If you still want to use a bi-dimensional array, put this array outside main
as a global variable, so it won't live on main
's stack frame anymore. Alternatively use malloc
to allocate this array, so it lives in the program's heap. See What and where are the stack and heap?
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论