我现在只用了2个星期学习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;
}
感谢阅读。希望你能找到解决方案。
答案 0 :(得分:3)
在C中,assignment有些expression,表达式是statement的简单(非常常见)类型。
所以而不是
int a = 2+3;
if (a>4) {
你可以编码
int a;
if ((a=2+3) > 4) {
具有相同的semantics。
所以你的if
statement类似于:
*h = (struct inhabitant *)malloc(sizeof(struct inhabitant) * (*m));
if (*h == NULL)
(使用原始代码中的复杂if
或将其拆分为两个语句,这是一个可读性和品味的问题;但是,请注意sequence points)
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(阅读Invoking GCC)。改进您的代码以获得警告。在使用之前,请阅读每个功能的documentation。学习use the debugger gdb
。努力避免undefined behavior,并且非常scared。
还详细了解C dynamic memory allocation,pointer aliasing,virtual address space,memory leaks,garbage collection,reference counting。除gdb
调试器外,valgrind有时也很有用。还要研究现有 free software的源代码(例如在github上),你会学到很多东西。
答案 1 :(得分:2)
除了指出的其他错误外,您的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);
}
请参阅:Do I cast the result of 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
来表示成功/失败,而不会自动从函数中退出程序。