首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C中的退出分割故障结构

C中的退出分割故障结构
EN

Stack Overflow用户
提问于 2021-01-23 11:03:52
回答 3查看 114关注 0票数 0

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

这里是错误:

代码语言:javascript
复制
> clang-7 -pthread -lm -o main main.c
> ./main
4
ath
67
68
thes
exited, segmentation fault
>

这里是代码:

代码语言:javascript
复制
#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;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-01-23 12:21:09

这一项将起作用:

代码语言:javascript
复制
//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以节省内存空间。

票数 0
EN

Stack Overflow用户

发布于 2021-01-23 13:02:28

通常情况下,要求输入包含将要出现的数据的总数是一个糟糕的设计选择,而且很容易删除该要求。例如:

代码语言:javascript
复制
    #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;                                                                  
    }  
票数 0
EN

Stack Overflow用户

发布于 2021-01-23 14:14:49

要使程序正常运行,您需要做三件重要的事情:

  1. 为每个城市分配N个城市
  2. ,在正确读取名称
  3. 终止名称之前为名称分配内存(指定空字符,而不是字符串)

以下是修正后的代码:

代码语言:javascript
复制
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的第一个调用不会失败。您可能还需要一个释放分配内存的函数。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65858442

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档