[英]Exited segmentation fault Struct in C
所以我有一個結構,我想制作一個 function 並從用戶輸入中獲取循環並將它們存儲到結構中。 但是在 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;
}
這將起作用:
//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);
}
我還建議使用較小的行長緩沖區並循環運行 fgets 以節省內存空間。
要求輸入包括即將到來的數據的總數通常是一個糟糕的設計選擇,並且很容易刪除該要求。 例如:
#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;
}
要使您的程序正常運行,您需要做三件基本的事情:
這是更正后的代碼:
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 的第一次調用沒有失敗。 您可能還需要一個 function 來釋放分配的 memory。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.