所以我有一个struct,我想用循环从用户输入中提取并存储到struct中来创建一个函数。但是,经过1循环,程序崩溃,与分割错误,我找不到问题。
这里是错误:

> clang-7 -pthread -lm -o main main.c
> ./main
4
ath
67
68
thes
exited, segmentation fault
>这里是代码:
#define STR 100000
typedef struct city{
float x;
float y;
char *name;
}City;
City *GetCities(int *N){
int i;
City *p;
char c;
scanf("%d",&*N);
p=malloc(sizeof(City));
p->name=malloc(STR*sizeof(char));
if (p->name==NULL){
printf("Could not find enough memory");
}
for (i=0; i<*N; i++){
while((c = getchar()) !='\n' && c!= EOF);
fgets(p[i].name,STR,stdin);
p[strcspn(p[i].name,"\n")].name="\0";
p[i].name=realloc(p[i].name,(strlen(p[i].name)+1)*sizeof(char));
scanf("%f ",&p[i].x);
scanf("%f",&p[i].y);
}
return p;
}发布于 2021-01-23 12:21:09
这一项将起作用:
//includes were missing
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR 100000
typedef struct city{
float x;
float y;
char *name;
}City;
City *GetCities(int *N){
int i;
char c;
City *list, *city;
//N is already a pointer so using a '&*' is confusing and I'm unsure whether this is at all valid syntax
scanf("%d", N);
//allocate enough memory! multiplied by number of cities
list = malloc(sizeof(City) * (*N));
for (i=0; i < *N; i++) {
//use pointer arithmetic to get the current city from the allocated block
//this needs to be done only once, now you can go on and reuse it extensively
city = list + i;
city->name = malloc(STR * sizeof(char));
if (city->name==NULL){
printf("Could not find enough memory");
}
while((c = getchar()) !='\n' && c!= EOF);
//i hope rest is clear
fgets(city->name, STR, stdin);
//use city->name[strlen(city->name)-1]='\0' instead?
city->name[strcspn(city->name,"\n")]='\0';
//at least you didn't forget the +1 in the realloc! :-)
city->name = realloc(city->name,(strlen(city->name)+1)*sizeof(char));
scanf("%f ", &city->x);
scanf("%f", &city->y);
}
return list;
}
//please also show the main, but I guess it was something like this
int main () {
int i, n;
City *cities, *city;
cities = GetCities(&n);
for (i=0; i < n; i++) {
city = cities + i;
printf("The %dth city \"%s\" got coordinates x=%f and y=%f!\n", i, city->name, city->x, city->y);
//don't forget to free the name
free(city->name);
}
//don't forget to free the memory
free(cities);
}我还建议使用较小的行长缓冲区,并在循环中运行fget以节省内存空间。
发布于 2021-01-23 13:02:28
通常情况下,要求输入包含将要出现的数据的总数是一个糟糕的设计选择,而且很容易删除该要求。例如:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
FILE * xfopen(const char *, const char *);
void * xrealloc(void *, size_t, size_t, void *);
struct city{
float x, y;
char *name;
};
int
get_city(struct city *e)
{
int c;
char *end;
size_t cap = 32;
e->name = xrealloc(NULL, 1, cap, &end);
/* Copy one line. We coould use getline(), or "%m[^\n]" */
while( (c = getchar()) != EOF && c != '\n' ){
*end++ = c;
if( end == e->name + cap ){
e->name = xrealloc(e->name, 1, cap += 32, &end);
}
}
*end = '\0';
if( c == EOF ){
return EOF;
}
if( (c = scanf("%f %f ", &e->x, &e->y)) != 2 ){
if( c != EOF ){
fprintf(stderr, "Invalid input\n");
}
return EOF;
}
return 0;
}
struct city *
GetCities(int *n)
{
size_t cap = 4;
struct city *e, *p = xrealloc(NULL, sizeof *p, cap, &e);
while( get_city(e) != EOF ){
if( ++e == p + cap ){
p = xrealloc(p, sizeof *p, cap += 4, &e);
}
}
*n = e - p;
return p;
}
int
main(void)
{
int n;
while( (n = getchar()) != EOF && n != '\n' ){
; /* Discard first line of input */
}
struct city *p = GetCities(&n);
struct city *e = p + n;
for( ; p < e; p++ ){
printf("%s: %f, %f\n", p->name, p->x, p->y);
}
return 0;
}
void *
xrealloc(void *buf, size_t num, size_t siz, void *endvp)
{
char **endp = endvp;
char *b = buf;
ptrdiff_t offset = b && endp && *endp ? *endp - b : 0;
b = realloc(b, num * siz);
if( b == NULL ){
perror("realloc");
exit(EXIT_FAILURE);
}
if( endp != NULL ){
*endp = b + offset;
}
return b;
} 发布于 2021-01-23 14:14:49
要使程序正常运行,您需要做三件重要的事情:
以下是修正后的代码:
City *GetCities(int *N)
{
int i;
City *p;
char c;
scanf("%d", N);
p = malloc(*N * sizeof(City));
for (i = 0; i < *N; i++) {
p[i].name = malloc(STR * sizeof(char));
if (p[i].name == NULL) {
printf("Could not find enough memory");
}
while ((c = getchar()) != '\n' && c != EOF);
fgets(p[i].name, STR, stdin);
p[i].name[strcspn(p[i].name, "\n")] = '\0';
scanf("%f ", &p[i].x);
scanf("%f", &p[i].y);
}
return p;
}剩下的就是验证输入,并确保对malloc的第一个调用不会失败。您可能还需要一个释放分配内存的函数。
https://stackoverflow.com/questions/65858442
复制相似问题