所以我试图制作一个程序,从标准输入中获取一定数量的字符串,然后输出到文本文件中。 到目前为止我的代码是:
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
int cmpstr(const void * a, const void *b){
const char* aa = (const char*) a;
const char* bb = (const char*) b;
return strcmp (aa, bb);
}
int main(int argc, char *argv[]){
int i =0;
int scount;
char ** data = NULL;
FILE * ofile;
if (argc != 3){
printf("%s \n", "The format to use this is: mySort <#of strings> <output filename>",argv[0]);
exit(EXIT_FAILURE);
}
scount = atoi(argv[1]);
if(!scount){
printf("%s \n", "Invalid number.");
exit(EXIT_FAILURE);
}
data = (char **) malloc(scount * sizeof(char*));
if(NULL == data){
printf("Memory allocation failed\n");
exit(EXIT_FAILURE);
}
for(i = 0; i< scount; i++){
if(NULL == fgets(data[i], (int) sizeof(data), stdin)){
printf("Could not get line\n");
exit(EXIT_FAILURE);
}
}
qsort(data, scount, sizeof(char*), cmpstr);
ofile = fopen(argv[2], "w+");
if(ofile == NULL){
printf("Could not open output file. \n");
}
for(i = 0; i<scount; i++){
fputs(data[i], ofile);
}
fclose(ofile);
for(i=0; i<scount; i++){
if(data[i]) free(data[i]);
}
if (data) free(data);
exit (EXIT_SUCCESS);
return 0;
}
但是,当我编译它时,它给了我一个段错误。我尝试使用 gdb 调试器来尝试调试它,但它并没有给我任何真正的东西,而且我几乎不明白如何使用 gdb。但我从 gdb 的使用中得到的结论是没有分配足够的内存,这让我很困惑,因为我使用 malloc 分配了内存。
最佳答案
data = (char **) malloc(scount * sizeof(char*));
这里为指针数组分配内存。您永远不会初始化该数组的内容。因此,当您通过将下面的 data[0]
传递给 fgets
来访问它时,您正在访问一个未初始化的指针对象。如果幸运的话,未初始化内存的内容会构成无效地址,并且当 fgets 尝试在那里存储数据时,您的程序会崩溃。如果你运气不好,未初始化内存的内容恰好是某个其他对象使用的某个内存块的地址,并且你会遇到内存损坏,很难调试。
您需要初始化malloc分配的指针。与任何其他指针对象一样,根据您想要执行的操作,您可以将它们初始化为 NULL、指向现有对象的指针或调用函数(例如 malloc)的结果。在此程序中,您需要获取要读取的行的存储空间,因此您需要对每一行调用 malloc
。由于您事先不知道一行有多长,因此最好在阅读该行时完成。
分配指针数组后,最好首先将所有元素设置为 NULL,然后为各个行分配内存。您不必这样做,但跟踪数组的哪些元素已初始化以及哪些元素尚未初始化会更容易。特别是,它可以让您对所有数组元素调用 free
,而不必担心已经达到了多少个。
fgets(data[i], (int) sizeof(data), stdin)
在这里传递sizeof(data)
是没有意义的。变量 data
是一个指向 char*
的指针,因此 sizeof(data)
只是指针的大小。它不是指针指向的数组的大小:该大小在编译时未知,而是传递给 malloc
的参数。即使这个大小在这里也不相关:大小是您可以读取的最大行数(乘以指向行内容的指针的大小),但是 fgets
需要的是为该行分配的内存。
为了简单起见,假设您有一个最大行长度 max_line_length
。
data = (char **) malloc(scount * sizeof(char*));
if (data == NULL) ... // omitted error checking
for (i = 0; i < scount; i++)
data[i] = NULL;
for (i = 0; i < scount; i++) {
data[i] = malloc(max_line_length+2); // +2 for line break character and null byte to terminate the string
if (data[i] == NULL) ... // omitted error checking
if(NULL == fgets(data[i], max_line_length, stdin)) ... // omitted error checking
...
}
在此之后,您将遇到注释中描述的另一个问题,因为 cmpstr
接收指向行内容的指针,而不是指向行内容的指针。 How to qsort an array of pointers to char in C?对此进行了解释。
关于c - 对程序中的字符串进行排序 - C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47467875/