我一直在hackerrank上尝试解决这个问题https://www.hackerrank.com/challenges/post-transition但我的代码似乎产生分割错误,当我试图运行它。我已经把它看了几十遍,并把它和别人的解决方案进行了比较,但我仍然不明白我可能做错了什么。
这是我得到的错误信息:
Reading symbols from Solution...done.
[New LWP 1602418]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `./Solution'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 send_all_acceptable_packages (source=source@entry=0x16eeec8,
source_office_index=0, target=target@entry=0x16eeee0,
target_office_index=<optimized out>) at Solution.c:58
58 int src_pk_count = (source->offices[source_office_index].packages_count);
这是我的代码
#include <stdlib.h>
#include <string.h>
#define MAX_STRING_LENGTH 6
struct package
{
char* id;
int weight;
};
typedef struct package package;
struct post_office
{
int min_weight;
int max_weight;
package* packages;
int packages_count;
};
typedef struct post_office post_office;
struct town
{
char* name;
post_office* offices;
int offices_count;
};
typedef struct town town;
void print_all_packages(town t)
{
printf("%s:n",t.name);
//offices loop
for(int i=0;i<t.offices_count;i++)
{
printf("t%i:n",i);
//packages loop
for(int j=0;j<t.offices[i].packages_count;j++)
{printf("tt%sn", t.offices[i].packages[j].id);}
}
}
void send_all_acceptable_packages
(town* source, int source_office_index, town* target, int target_office_index)
{
int trg_pk_count = (target->offices[target_office_index].packages_count);
int src_pk_count = (source->offices[source_office_index].packages_count);
//weight condition
int min_w = (target->offices[target_office_index].min_weight);
int max_w = (target->offices[target_office_index].max_weight);
for(int i=0;i<src_pk_count;i++)
{
int pckg_w = (source->offices[source_office_index].packages[i].weight);
if ((pckg_w >= min_w) && (pckg_w <= max_w))
{
target->offices[target_office_index].packages = realloc (target->offices[target_office_index].packages, sizeof(package)* (trg_pk_count+1));
(target->offices[target_office_index].packages_count)++;
(source->offices[source_office_index].packages_count)--;
target->offices[target_office_index].packages[(trg_pk_count)]= source->offices[source_office_index].packages[i];
for(int x=0; x<(src_pk_count-1);x++)
{
source->offices[source_office_index].packages[i+x] = source->offices [source_office_index].packages[i+x+1] ;
source->offices[source_office_index].packages= realloc(source->offices [source_office_index].packages, sizeof(package)*((source->offices [source_office_index].packages_count)));
}
}
}
}
town town_with_most_packages(town* towns, int towns_count)
{
//count
int town_pkcount[towns_count];
for(int i=0;i<towns_count;i++)
{
town_pkcount[i]=0;
int sum=0;
for(int j=0;j<towns[i].offices_count;j++)
{
sum+= towns[i].offices[j].packages_count;
}
town_pkcount[i]=sum;
}
//find max
int max=-1 , max_index;
for(int i=0; i<towns_count;i++)
{
if (town_pkcount[i]>max)
{
max = town_pkcount[i];
max_index=i;
}
}
return towns[max_index];
}
town* find_town(town* towns, int towns_count, char* name)
{
int town_index=-1;
for(int i=0; i<towns_count; i++)
{
if(strcmp(name,towns[i].name)==0)
{town_index = i;}
break;
}
return(&towns[town_index]);
}
int main()
{
int towns_count;
scanf("%d", &towns_count);
town* towns = malloc(sizeof(town)*towns_count);
for (int i = 0; i < towns_count; i++) {
towns[i].name = malloc(sizeof(char) * MAX_STRING_LENGTH);
scanf("%s", towns[i].name);
scanf("%d", &towns[i].offices_count);
towns[i].offices = malloc(sizeof(post_office)*towns[i].offices_count);
for (int j = 0; j < towns[i].offices_count; j++) {
scanf("%d%d%d", &towns[i].offices[j].packages_count, &towns[i].offices[j].min_weight, &towns[i].offices[j].max_weight);
towns[i].offices[j].packages = malloc(sizeof(package)*towns[i].offices[j].packages_count);
for (int k = 0; k < towns[i].offices[j].packages_count; k++) {
towns[i].offices[j].packages[k].id = malloc(sizeof(char) * MAX_STRING_LENGTH);
scanf("%s", towns[i].offices[j].packages[k].id);
scanf("%d", &towns[i].offices[j].packages[k].weight);
}
}
}
int queries;
scanf("%d", &queries);
char town_name[MAX_STRING_LENGTH];
while (queries--) {
int type;
scanf("%d", &type);
switch (type) {
case 1:
scanf("%s", town_name);
town* t = find_town(towns, towns_count, town_name);
print_all_packages(*t);
break;
case 2:
scanf("%s", town_name);
town* source = find_town(towns, towns_count, town_name);
int source_index;
scanf("%d", &source_index);
scanf("%s", town_name);
town* target = find_town(towns, towns_count, town_name);
int target_index;
scanf("%d", &target_index);
send_all_acceptable_packages(source, source_index, target, target_index);
break;
case 3:
printf("Town with the most number of packages is %sn", town_with_most_packages(towns, towns_count).name);
break;
}
}
return 0;
}
请记住,结构体和main函数已经预先写好了
seg故障似乎与send_all_acceptable_packages函数有关
还要记住,在输入这行输入之后会发生segfault2 B 0 A 1触发main
中的情形2case 2:
scanf("%s", town_name);
town* source = find_town(towns, towns_count, town_name);
int source_index;
scanf("%d", &source_index);
scanf("%s", town_name);
town* target = find_town(towns, towns_count, town_name);
int target_index;
scanf("%d", &target_index);
send_all_acceptable_packages(source, source_index, target, target_index);
break;
在中,您可以看到find_town函数的返回值被用作send_all_acceptable_packages函数的输入,这使我相信错误存在于这两个函数
中的一个。请帮我找出这里的问题,谢谢你的建议。
下面的循环永远不会迭代:
town* find_town(town* towns, int towns_count, char* name)
{
int town_index=-1;
int i = 0;
for(i=0; i < towns_count; i++)<-warning points here (i++)
{
if(strcmp(name,towns[i].name)==0)
{ town_index = i;}
break;<- cause of warning
}
return(&towns[town_index]);
}
我从调试器中看到以下警告:
150,31警告:将永远不会执行
break语句保证循环永远不会迭代。
您可能打算将它放在if()
语句
town* find_town(town* towns, int towns_count, char* name)
{
int town_index=-1;
int i = 0;
for(i=0; i < towns_count; i++)
{
if(strcmp(name,towns[i].name)==0)
{
town_index = i;
break;
}
}
return(&towns[town_index]);
}
一些额外的项目看:
int main(void);
是C
(不是int main()
)中main
函数的最小原型- 代码不检查应该检查的函数的返回值(例如
scanf()
)。 - 最好限制呼叫
scanf()
的输入长度以防止溢出,即使用#define MAX_STRING_LENGTH 6
,用户被限制为一些非常短的名称,但如果城市输入为"达拉斯";scanf("%s", towns[i].name);
程序将溢出。将其写入scanf("%(MAX_STRING_LENGTH-1)s", towns[i].name);
以限制用户输入的合法长度。 - 建议将
#define MAX_STRING_LENGTH 6
更改为更实际的值 - 内存泄漏。代码不会释放创建的任何内存。每调用一次
malloc()
,调用一次free()
- 在每个
scanf()
之前使用printf()
列出用户输入的指令。(例如:printf("enter town namen");
)