簡體   English   中英

C指針和動態分配

[英]C pointer and dynamic alloc

我現在僅學習C語言兩個星期,而動態分配和指針卻遇到了問題,我對以下代碼有些困惑。

我試圖了解讀取功能的工作方式,但是*m使我感到困惑。 我只是找不到使用*m參數的方法,而且

if((*h = (struct inhabitant *)malloc(sizeof(struct inhabitant) * (*m))) == NULL)

我只是被吹走了。

這是代碼:

#include <stdlib.h>
#include "inhabitants.h"
#include "sort.h"

void read(FILE *s, struct inhabitant **h, int *m) {
  int i, ntok;
  struct inhabitant *tmph;

  ntok = fscanf(s, "%d", m);
  if(ntok != 1 || *m < 0) {
    fprintf(stderr, "Unable to read file.\n");
    exit(-1);
  }

  if((*h = (struct inhabitant *)malloc(sizeof(struct inhabitant) * (*m))) == NULL) {
    fprintf(stderr, "Unable to allocate space for inhabitants.\n");
    exit(-1);
  }

  tmph = *h;
  for(i = 0; i < (*m); ++i) {
    ntok = fscanf(s, "%d %s %s %d", &(tmph[i].distance), (char *)&(tmph[i].prenom), (char *)&(tmph[i].nom), (int *)&(tmph[i].zip));
    if(ntok != 4) {
      fprintf(stderr, "File wrongly formatted.\n");
      exit(-1);
    }
  }

}

int compare_inhabitants_by_distance(struct inhabitant *a, struct inhabitant *b) {
    if (a->distance > b->distance)
        return 1;
    else
        return 0;
  //à compléter
}

int compare_inhabitants_by_zipcode(struct inhabitant *a, struct inhabitant *b) {
  if (a->enum zipcode > b->enum zipcode)
        return 1;
    else
        return 0;
  //à compléter
}

void show(int n, struct inhabitant *a) {
  int i;
  for(i = 0; i < n; ++i) {
    printf("%d, %s, %s, %d\n", a[i].distance, a[i].prenom, a[i].nom, a[i].zip);
  }
}

void printout(FILE *s, int n, struct inhabitant *a) {
  int i;
  for(i = 0; i < n; ++i) {
    fprintf(s, "%d %s %s %d\n", a[i].distance, a[i].prenom, a[i].nom, a[i].zip);
  }
}

#define PERSONS_TO_SAVE_FILE_IN "evacuation_plan0.txt"
#define PERSONS_TO_SAVE_FILE_OUT "better_evacuation_plan0.txt"

int main(int argc, char **argv) {
  FILE *s;
  int n;
  /*For testing purpose :
  struct inhabitant inhabs[] = {
                                { 100, "Jean", "France", GUADELOUPE },
                                { 10, "Ameni", "Braminia", STBARTH },
                                { 12, "Mathieu", "Krister", GUADELOUPE },
                                { 23, "Hilaire  ", "Blanchi", STMARTIN }
                              };
  n = sizeof(inhabs) / sizeof(*inhabs);*/

  struct inhabitant *inhabs0;


  if((s = fopen(PERSONS_TO_SAVE_FILE_IN, "r")) == NULL) {
    fprintf(stderr, "Unable to open file.");
    exit(-1);
  }

  read(s, inhabs, )

  /*
  A compléter :
  - Lecture du fichier.
  - Tris.
  */

  if((s = fopen(PERSONS_TO_SAVE_FILE_OUT, "w+")) == NULL) {
    fprintf(stderr, "Unable to open file.");
    exit(-1);
  }
  printout(s, n, inhabs0);
  fclose(s);

  free(inhabs0);

  return EXIT_SUCCESS;
}

謝謝閱讀。 希望您能找到解決方案。

在C語言中, 賦值是一些表達式 ,而表達式是一種簡單(且非常常見)的語句

所以代替

int a = 2+3;
if (a>4) { 

你可能會編碼

int a;
if ((a=2+3) > 4) {

具有相同的語義

因此,您的if語句類似於:

*h = (struct inhabitant *)malloc(sizeof(struct inhabitant) * (*m));
if (*h == NULL) 

(使用復雜的( if像原始代碼中那樣),或者將其拆分為兩個語句,是易讀性和趣味性;但是,請注意序列點

順便說一句,原始代碼中的內容是不好的味道(並且將exit(3)與-1一起使用也是不好的味道)。 您最好將perror(3)strerror(3)errno(3)結合使用,以解釋為什么malloc失敗。 所以我建議

  { // when *h is NULL because malloc failed
     fprintf(stderr, 
             "Unable to allocate space for %d inhabitants: %s\n", 
             *m, strerror(errno));
     exit(EXIT_FAILURE);
  }

並且在您的特殊情況下(分配數組),我建議使用calloc(3) (以獲得一些零初始化的內存區域)而不是malloc

順便說一句,我建議更改read功能的名稱。 可以將它與POSIX read混淆。

不要忘記編譯所有警告和調試信息,因此將gcc -Wall -Wextra -gGCC一起使用 (了解有關調用GCC的信息 )。 改進您的代碼,不發出任何警告。 在使用每個功能之前,請閱讀其文檔 學習使用調試器gdb 努力避免不確定的行為 ,並對此感到非常恐懼

另請閱讀有關C動態內存分配指針別名虛擬地址空間內存泄漏垃圾回收引用計數的更多信息 除了gdb調試器外, valgrind有時也很有用。 還要研究現有 自由軟件的源代碼(例如在github上 ),您將學到很多東西。

除了指出的其他錯誤之外,您的fscanf變量也是錯誤的。 您不需要傳遞prenumnom地址,因為它們已經是指針,例如

    for (i = 0; i < *m; ++i) {
        /* casts should not be necessary, prenom & nom already pointers */
        ntok = fscanf (s, "%d %s %s %d", &tmph[i].distance, (tmph[i].prenom),
                        (tmph[i].nom), &(tmph[i].zip));

此外,分配本身有些笨拙。 對於sizeof使用變量名而不是類型,並且不需要malloc的返回值,例如

    /* allocate/validate space for 'm' inhabitants */
    if ((*h = malloc (sizeof **h * *m)) == NULL) {
        fprintf (stderr, "Unable to allocate space for inhabitants.\n");
        exit (-1);
    }

請參閱: 是否強制轉換malloc的結果?

未經測試,但總而言之,您的讀取功能可以更新為類似於以下內容的內容:

void read (FILE *s, struct inhabitant **h, int *m)
{
    int i, ntok;
    struct inhabitant *tmph;

    ntok = fscanf (s, "%d", m);
    if (ntok != 1 || *m < 0) {
        fprintf (stderr, "Unable to read file.\n");
        exit (-1);
    }

    /* allocate/validate space for 'm' inhabitants */
    if ((*h = malloc (sizeof **h * *m)) == NULL) {
        fprintf (stderr, "Unable to allocate space for inhabitants.\n");
        exit (-1);
    }

    tmph = *h;
    for (i = 0; i < *m; ++i) {
        /* casts should not be necessary, prenom & nom already pointers */
        ntok = fscanf (s, "%d %s %s %d", &tmph[i].distance, (tmph[i].prenom),
                        (tmph[i].nom), &(tmph[i].zip));
        if (ntok != 4) {
            fprintf (stderr, "File wrongly formatted.\n");
            exit (-1);
        }
    }
}

試試看,讓我知道您是否還有其他問題。

注意:main() ,您也有明顯的錯別字, read(s, inhabs, )read (s, &inhabs0); 如果您給read賦予了有意義的返回類型(例如int ,則可以返回01來指示成功/失敗,而無需自動從函數中退出程序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM