我道歉,如果这是浪费时间和/或不应该在这个网站上,但我有点想法...我仍然是编程的新手,不能得到一个保持我的老师的指导,所以...到互联网!
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void months( FILE* monthfp, char** monthGroup );
int main (void){
FILE *monthfp; /*to be used for reading in months from months.txt*/
char** monthGroup;
int i;
if (( monthfp = fopen ( "months.txt", "r" )) == NULL ){
printf( "unable to open months.txt. \n" );
exit ( 1 );
}
months( monthfp, monthGroup );
/*test so far*/
for ( i = 0; i < 12; i++ ){
printf( "%s", monthGroup[i] );
}
fclose( monthfp );
}
void months ( FILE* monthfp, char** monthGroup ){
/*****************************************
name: months
input: input file, data array
returns: No return. Modifies array.
*/
char buffer[50];
int count = 0;
while ( fgets( buffer, sizeof(buffer), monthfp ) != NULL ){
count++;
monthGroup = malloc( count * sizeof ( char* ));
monthGroup[count] = malloc( sizeof( buffer ) * sizeof( char ));
strcpy(monthGroup[ count - 1 ], buffer );
}
}
我正在使用C89进行编译,除了分段错误之外,似乎都可以正常工作。任何指导都将非常感谢。
修改 感谢所有花时间提供一些洞察力的人,我一直无法理解。在异乡的一个长老村里,我感觉自己像个小孩子。非常感谢礼貌和指导。
答案 0 :(得分:1)
对我而言,最明显的问题是您将char** monthGroup
作为参数按值传递,然后将malloc
传递给函数months
,并且之后尝试在调用者函数中使用它。但是,由于您按值传递了该值,因此您只将malloc
ed地址存储在monthGroup
的本地副本中,该副本不会更改main
中原始变量的值。
作为快速修复,您需要将指针传递给 monthGroup
,而不是(当前值的副本):
int main (void){
...
char** monthGroup;
...
months( monthfp, &monthGroup );
...
}
void months ( FILE* monthfp, char*** monthGroup ){
...
*monthGroup = malloc( count * sizeof ( char* ));
...
}
这很难看(恕我直言,在实际代码中应该没有真正的理由使用char***
),但至少朝着正确的方向迈出了一步。
然后,正如其他人正确提到的那样,您还应该重新考虑在循环中重新分配monthGroup
并忘记之前的分配,留下内存泄漏和悬空指针的方法。当前代码循环中发生的事情是
// read the first bunch of text from the file
count++;
// count is now 1
monthGroup = malloc( count * sizeof ( char* ));
// you allocated an array of size 1
monthGroup[count] = malloc( sizeof( buffer ) * sizeof( char ));
// you try to write to the element at index 1 - another segfault!
// should be monthGroup[count - 1] as below
strcpy(monthGroup[ count - 1 ], buffer );
即使使用上面提到的修复,在10次迭代之后,您仍然必须拥有10个元素的数组,其中前9个是悬空指针,只有10个指向有效地址。
答案 1 :(得分:1)
完成的代码将是:
int main (void)
{
FILE *monthfp; /*to be used for reading in months from months.txt*/
char **monthGroup = NULL;
char **iter;
if ((monthfp = fopen("c:\\months.txt", "r")) == NULL){
printf("unable to open months.txt. \n");
exit(1);
}
months(monthfp, &monthGroup);
iter = monthGroup;
/* We know that the last element is NULL, and that element will stop the while */
while (*iter) {
printf("%s", *iter);
free(*iter);
iter++;
}
/* Remember that you were modifying iter, so you have to discard it */
free(monthGroup);
fclose(monthfp);
}
void months(FILE *monthfp, char ***monthGroup)
{
/*****************************************
name: months
input: input file, data array
returns: No return. Modifies array.
*/
char buffer[50];
int count = 0;
while (fgets(buffer, sizeof(buffer), monthfp) != NULL){
count++;
/* We realloc the buffer */
*monthGroup = (char**)realloc(*monthGroup, count * sizeof(char**));
/* Here I'm allocating an exact buffer by counting the length of the line using strlen */
(*monthGroup)[count - 1] = (char*)malloc((strlen(buffer) + 1) * sizeof( char ));
strcpy((*monthGroup)[count - 1], buffer);
}
/* We add a terminating NULL element here. Other possibility would be returning count. */
count++;
*monthGroup = (char**)realloc(*monthGroup, count * sizeof(char**));
(*monthGroup)[count - 1] = NULL;
}
正如其他人所说,char***
很难看。
答案 2 :(得分:1)
你的问题在于月份功能,特别是你对记忆如何运作的理解。
查看您的代码:
monthGroup = malloc( count * sizeof ( char* ));
此行分配一块内存,相当于大小为char *
的{{1}}数组。
count
这里,缓冲区的大小为monthGroup[count] = malloc( sizeof( buffer ) * sizeof( char ));
(sizeof (buffer)
是不必要的)。这是一个问题:您将其分配给sizeof (char)
。 C中的数组是零基数,这意味着数组:
monthGroup[count]
有元素:
int array [3];
array [0], array [1] and array [2]
超出了数组的内存。所以array [3]
也在数组的内存之外。您想要monthGroup[count]
。这将写入数组中的最后一个元素。
第二个问题是,每次进行第一次分配时,都会丢失先前分配的数据(这称为内存泄漏)及其包含的数据。
要解决此问题,有两种方法。
分配数组时,将旧数组的内容复制到新数组:
oldarray = monthGroup; monthGroup = malloc(count * sizeof(char *)) memcpy(monthGroup,oldarray,count-1 * sizeof(char *)); 免费(oldarray); monthGroup [count-1] = ....
或使用monthGroup[count-1]
。
使用链接列表。这个复杂得多,但每次读取新项目时都不需要复制数组。
此外,monthGroup参数不会传递回调用者。将功能更改为:
realloc
或:
char **months (FILE *fp)
最后,调用者当前假定有12个条目并尝试打印每个条目。如果少于12或超过12,会发生什么?应对的一种方法是使用特殊指针来终止void months (FILE *fp, char ***ugly_pointer)
数组,NULL可以很好地完成。只需为数组分配一个额外的元素,并将最后一个元素设置为NULL。
答案 3 :(得分:0)
我立即看到的主要错误是,您对monthGroup
的分配永远不会回到main
。