gpt4 book ai didi

c - 40条简单的行,1条令人讨厌的分割错误。我真的不知道现在还能去哪里

转载 作者:行者123 更新时间:2023-12-04 11:23:41 25 4
gpt4 key购买 nike

如果这是浪费时间和/或不是本网站上的内容,我深表歉意,但是我有点没主意...我仍然是编程的新手,无法控制我的老师寻求指导,所以...到互联网!

#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中进行编译,除分段错误外,所有内容似乎都可以正常工作。任何指导将不胜感激。

编辑
感谢所有花时间为我提供一些见解的人,我一直无法解决问题。我感觉像是在异乡长者村里的小孩。非常感谢您的礼貌和指导。

最佳答案

恐怕您还没有意识到您做对了还有多远。坐好,这会很长。欢迎来到C。

char** monthGroup


这实际上意味着“指向 char的指针”。但是,C有许多原因导致您想要指向某些内容。在您的情况下,“内部”指向实际上是指向内存中的一个 char序列(通俗地将其视为“字符串”,而C通常没有),而“外部”则指向指向是指您可以指向这些 char*的序列,并将该序列视为“数组”(即使不是);您将对其进行动态分配)。

问题出在这里:当您传入来自 char**main时,实际上并没有指向任何东西。你说:“很好”。 “该函数将使其指向一些我将使用 malloc()分配的内存”。

不。

C通过价值传递一切。 char**接收的 monthschar**局部变量块中 main的副本。您覆盖指针(使用 malloc的结果),将一些指针写入该指向的内存(更多的 malloc结果),将一些数据复制到这些指向的内存块中,然后,在函数末尾,参数 monthGroup(这是 months中的局部变量)不再存在,并且您丢失了所有数据,并且main中的变量 monthGroup仍然指向没有。当您尝试使用它好像指向某物时,繁荣就死定了。

那么我们如何解决这个问题?当然,换种说法,C适当地没有“按引用传递”,因此我们必须伪造它。我们接受 char***,并通过 &monthGroup。这仍然是一个复制的值,但它直接指向用于调用 main的局部变量存储(在堆栈上)。这样我们就可以编写一个在 main中可见的值。我们将第一个 malloc结果分配给 *monthGroup,并将指针写入该存储区( *monthGroup[count]),依此类推。

除非我们真的不想要这样做,否则它会令人难以置信的丑陋,混乱和难以实现。取而代之的是,做应该做的一件非常明显的事情,而基本指令却没有足够强调:使用函数的返回值返回计算结果-这就是为什么将其称为返回值。

也就是说,我们在 char**中设置了 months(不接受任何类型的参数),将其返回,然后使用它来初始化 main中的值。

我们完了吗?没有。

您仍然存在一些逻辑错误:


您可以在while循环中重新分配“外”层。显然这不是您想要的。您要分配几个“字符串”,但只能分配一个“数组”,因此分配不在循环之内。否则,您每次都会丢弃(没有正确地重新分配它们!)旧数组。


实际上,您确实想做这样的事情,但这仅仅是因为您事先不知道需要多少元素。问题在于,新分配只是一个新分配-不包含先前设置的指针。

幸运的是,C为此提供了一个解决方案: realloc。这将分配新的内存,复制旧内容(指向分配的“字符串”的指针),并取消分配旧块。万岁!更好的是,如果我们为“旧内存”赋予NULL指针,则 realloc的行为将与 malloc相似。这样我们就可以避免对循环进行特殊处理。


您错误地使用了值 count。第一次通过循环,您将把 count递增到1,为 monthGroup[1]指向分配一些空间,然后尝试将其写入从未设置的 monthGroup[0]指向的空间。您想在刚分配的“字符串”的相同空间中写入。 (顺便说一句, sizeof(char)是无用的:它始终为1。即使您的系统使用8位以上的字符表示一个字符! char是系统上存储的基本单位。)


除外,因为有一种更简单的方法:使用 strdup获取指向缓​​冲区分配副本的指针。

char** months(FILE* monthfp) {
char buffer[50];
int count = 0;
char** monthGroup = NULL;

while (fgets(buffer, sizeof(buffer), monthfp) != NULL) {
// (re-)allocate the storage:
monthGroup = realloc(monthGroup, count * sizeof(char*));
// ask for a duplicate of the buffer contents, and put a pointer to the
// duplicate sequence into the last element of the storage:
monthGroup[count - 1] = strdup(buffer);
}

return monthGroup;
}


调整 main使其匹配以完成一项(希望是微不足道的)练习。另请阅读 reallocstrdup的文档。

我们完了吗?没有。

您仍然应该检查 NULLreallocstrdup返回值(因为它们都试图分配内存,因此在C语言中可能会失败),并且您仍然需要代码来 free分配的内存。

而且,正如其他人指出的那样,您不应该假设会有12个月的时间。如果可以假设的话,那么就不会动态分配 monthGroup。您将只使用一个数组。因此,您需要以某种方式传达结果“数组”的大小(在末尾添加一个显式NULL指针是一种方法;另一种方法是做一件非常丑陋的事情,传入 char***,然后使用返回值进行计数规模)。

关于c - 40条简单的行,1条令人讨厌的分割错误。我真的不知道现在还能去哪里,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9681924/

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