[英]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 -g
與GCC一起使用 (了解有關調用GCC的信息 )。 改進您的代碼,不發出任何警告。 在使用每個功能之前,請閱讀其文檔 。 學習使用調試器gdb
。 努力避免不確定的行為 ,並對此感到非常恐懼 。
另請閱讀有關C動態內存分配 , 指針別名 , 虛擬地址空間 , 內存泄漏 , 垃圾回收 , 引用計數的更多信息 。 除了gdb
調試器外, valgrind有時也很有用。 還要研究現有 自由軟件的源代碼(例如在github上 ),您將學到很多東西。
除了指出的其他錯誤之外,您的fscanf
變量也是錯誤的。 您不需要傳遞prenum
或nom
的地址,因為它們已經是指針,例如
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
,則可以返回0
或1
來指示成功/失敗,而無需自動從函數中退出程序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.