我已经达成了这个问题。我有一个相当大的C程序,当它应该返回时,它正在给我分段错误。
struct customer{
char *name;
int custID;
double credit;
char *address;
char *state;
char *zip;
};
typedef struct customer customer;
struct custNode{
customer *customer;
struct custNode *next;
};
typedef struct custNode custNode;
// 。
custNode *customerList = (custNode *)malloc(sizeof(custNode));
readDatabase(fp,customerList);
因此,读取数据库的功能是从同一目录中的文件中读取字符串,并从中创建一个custNodes的链接列表。似乎我的代码没有正确地将custNodes附加到列表的前面,我不知道为什么。它在readDatabase函数的return语句中断开。
void attachCustNode(custNode *head, customer *target){
if(!target || !head){
printf("\nTarget or Head is NULL!!!\n");
}
custNode *temp = malloc(sizeof(custNode));
temp->customer = target ;
if(!head->customer){
printf("building new list\n");
temp->next = head;
*head = *temp;
}
else{
printf("ELSE attaching to front\n");
temp->next = NULL;
*head = *temp;
}
return;
}
void readDatabase(FILE *fp , custNode *result){ //reads the database file for the customers
printf("reading database, creating structures.\n");
int i , size;
size_t fSize; //getline wants size_t ... dumb.
char *buff,*tok;
unsigned int error = 1;
char delim[3] = "|\"";
delim[2] = '\0';
result->customer = NULL;
result->next = NULL;
fseek(fp, 0L, SEEK_END);
size = ftell(fp);
fSize = size;
fseek(fp , 0 , SEEK_SET) ; //get size of file, reset fseek
printf("database of size %d \n", size);
buff = malloc( (sizeof(char)*size)+1);
/*
printf("Buffer is %s and error is %d \n", buff, error);
if( error <= 0 ){
printf("getline fell and couldn't get up in %s on line %d\n", __FILE__ , __LINE__);
break;
}
*/
//int len;
while( error > 0 ){
error = getline(&buff, &fSize, fp);
if( error < 0 ){
printf("breaking loop\n");
break;
}
customer *temp = (customer *)malloc(sizeof(customer));
tok = strtok(buff , delim);
temp->name = tok;
tok = strtok(NULL, delim);
temp->custID = atoi(tok); ///int atoi(const char *nptr);
tok = strtok(NULL, delim);
temp->credit = atof(tok); //double atof(const char *nptr);
//printf("added %lf to temp orderNode\n",temp->credit); //%f prints doubles.
tok = strtok(NULL, delim);
temp->address = tok;
tok = strtok(NULL, delim);
temp->state = tok;
tok = strtok(NULL, delim);
temp->zip = tok;
attachCustNode(result,temp);
}
return ;
}
提前感谢您的帮助。
EDIT。我已经在这个github gist中发布了我的代码以使其更容易,它仍然由于某种原因不会退出该函数。我在第148行添加了strdup函数,如响应所示,但由于某种原因,它仍然没有返回。
答案 0 :(得分:3)
我认为这段很小的代码没有做你想做的事情:
result->customer == NULL;
result->next == NULL;
也许
result->customer = NULL;
result->next = NULL;
?然后 attachCustNode()中的if-Statement将起作用,并且应该添加列表项。
答案 1 :(得分:3)
attachCustNode
中使用的逻辑有问题。
head
始终指向内存中的相同位置。我们说它的值是H
。
当列表为空时:
head = H
temp->next = H
*head = *temp;
这意味着:
head = H
head->next = H
您需要的是
head->next = NULL
此时,temp
是内存泄漏。
当列表不为空时:
temp->next = NULL;
*head = *temp;
这使得
head = H
head->next = NULL
此时,temp
是内存泄漏。
用于确定列表是否为空的策略是错误的。而不是
if(!head->customer){
你应该重构你的代码,甚至不用担心列表是否为空。
这是重构的代码:
custNode* attachCustNode(custNode* head, customer *target){
custNode *temp = malloc(sizeof(custNode));
temp->customer = target;
// No matter what head is temp is now the head.
temp->next = head;
return temp;
}
稍微重构readDatabase
。返回新创建的列表,而不是传递指针。
custNode* readDatabase(FILE *fp){ //reads the database file for the customers
custNode *result = NULL;
// Your code
// ....
while( error > 0 ){
// Your code
// ....
result = attachCustNode(result, temp);
}
return result;
}
重构main
以说明对readDatabase
的更改。
custNode *customerList = readDatabase(fp);
<强>更新强>
其中一些线路不正确。您指向从函数返回后无效的内存。您需要为字符串分配内存并使用strcpy
或仅使用strdup
。
customer *temp = (customer *)malloc(sizeof(customer));
tok = strtok(buff , delim);
temp->name = tok; // NOT GOOD
tok = strtok(NULL, delim);
temp->custID = atoi(tok);
tok = strtok(NULL, delim);
temp->credit = atof(tok);
tok = strtok(NULL, delim);
temp->address = tok; // NOT GOOD
tok = strtok(NULL, delim);
temp->state = tok; // NOT GOOD
tok = strtok(NULL, delim);
temp->zip = tok; // NOT GOOD
使用:
temp->name = strdup(tok);
对成员address
,state
和zip
进行类似的更改。
答案 2 :(得分:2)
我至少看到一个问题: strtok返回的指针是buff(读缓冲区)的指针 这些都保存在每个客户结构中。 但是在下一次读取(getline)时,输入缓冲区(buff)会被清除掉, 并且保存在客户结构中的指针现在指向谁知道什么。
您需要为每个名称,地址,状态,zip分配内存, 或者在客户结构中将它们作为char数组。
我不知道你是如何得到段错误的, 但有一种方法是当你自由()buff(你应该这样,即使它没有显示) 所有客户结构中的所有指针都将变为无效。
答案 3 :(得分:0)
不要这样做
tok = strtok(NULL, delim);
temp->address = tok;
DO
tok = strtok(NULL, delim);
temp->address = strdup(tok);
strtok正在返回指向buff中某个位置的指针,该指针可能会或可能不会继续存在。 Strdup会将你的字符串副本复制到malloced内存中 - 你必须释放它
答案 4 :(得分:0)
答案实际上与此无关。 :/我正在使用getline函数,它被设置为unsigned int所以它从来都不是负面的。