#c #compiler-errors #compilation
#c #ошибки компилятора #Сборник
Вопрос:
Я создаю программу для своего семестрового проекта, которая принимает растровое изображение в формате .pbm, упрощает его с помощью кривых Безье и выводит результат в формате .eps. Университет предложил нам поработать над проектом с массивами переменного размера и уже предоставил объявления.
Структура для массива квадратичных Безье переменного размера:
typedef struct TTV_Bezier2_
{
UINT nb;
UINT cap;
UINT taille_e<
Bezier2 * tab;
}TTV_Bezier2;
UINT — это объявление, данное из университета (typedef unsigned int)
Bezier2 — это тип, созданный мной. Это репрезентация квадратичного Безье в моей программе, определяемого ее 3 контрольными точками:
typedef struct Bezier_q
{
Point C0;
Point C1;
Point C2;
}Bezier2;
Точка — это другая структура typedef :
typedef struct Point_ {
double x,y;
} Point;
Вот моя проблема: массив Beziers с переменным размером определен внутри файла с именем TTV_Bezier.h, а тип Bezier2 определен внутри файла с именем bezier.h . Я включил файлы друг в друга, потому что каждый файл использует эти типы из другого. Однако при компиляции я получаю следующую ошибку:
gcc -c -g -O2 -Wall -I. test_simplification_bezier2.c
In file included from TTV_Bezier2.h:8,
from test_simplification_bezier2.c:8:
bezier.h:91:1: error: unknown type name ‘TTV_Bezier2’; did you mean ‘Bezier2’?
TTV_Bezier2 * simplification_douglas_peucker_bezier2(TTV_Point CONT, int j1, int j2, double d);
Мне сказали, что есть проблема с моими зависимостями внутри Makefile, но я так не думаю, потому что я уже включил их в нужные файлы. Не могли бы вы мне помочь, пожалуйста?
Файлы:
TTV_Bezier2.h:
#ifndef _TTV_BEZIER2_H_
#define _TTV_BEZIER2_H_
#include <stdio.h>
#include <stdlib.h>
#include "types_macros.h"
#include "bezier.h"
typedef struct TTV_Bezier2_
{
UINT nb;
UINT cap;
UINT taille_e<
Bezier2 * tab;
}TTV_Bezier2;
TTV_Bezier2 * creer_TTV_Bezier2_vide();
Bezier2 element_TTV_Bezier2(TTV_Bezier2 T, UINT i);
UINT nb_elements_TTV_Bezier2(TTV_Bezier2 * T);
TTV_Bezier2 * ajouter_element_TTV_Bezier2(TTV_Bezier2 * T, Bezier2 e);
TTV_Bezier2 * concatener_TTV_Bezier2(TTV_Bezier2 * T1, TTV_Bezier2 * T2);
void supprimer_TTV_Bezier2(TTV_Bezier2 *ptr_T);
#endif
bezier.h:
#ifndef _BEZIER_H_
#define _BEZIER_H_
#include "TTV_Bezier2.h"
#include "TTV_Point.h"
#include "geom2d.h"
//Definition du type Bezier2
typedef struct Bezier_q
{
Point C0;
Point C1;
Point C2;
}Bezier2;
//Definition du type Bezier3
typedef struct Bezier_s
{
Point C0;
Point C1;
Point C2;
Point C3;
}Bezier3;
//Fonction qui calcule le point de la Bezier quadratique C(t) au parametre t
Point calculate_bezier_2(Bezier2 b, double t);
//Fonction qui calcule le point de la Bezier cubique C(t) au parametre t
Point calculate_bezier_3(Bezier3 b, double t);
//Fonction qui calcule la distance entre un point et une bezier quadratique
double distance_point_bezier2(Point P, Bezier2 B, double t);
//Fonction qui calcule la distance entre un point et une bezier cubique
double distance_point_bezier3(Point P, Bezier3 B, double t);
//Fonction qui calcule le factoriel d'un nombre
double factorial (int i);
//Fonction qui prend une Bezier quadratique et la transforme en Bezier cubique
Bezier3 convert_bezier2_to_3(Bezier2 b);
//Fonction qui calcule la base bernstein B(i,d,t)
double calculate_bernstein_base(int i, int d, double t);
//Fonction qui calcule γ(k)
double calculate_gamma(int i, int n);
//Fonction qui approxime la sequence de points CONT par une Bezier quadratique
Bezier2 approx_bezier2(Point * tab, int j1, int j2);
//Fonction qui approxime la sequence de points CONT par une Bezier cubique
Bezier3 approx_bezier3(Point * tab, int j1, int j2);
//Fonction qui simplifie le contour avec une Bezier cubique
Bezier3_t * simplification_douglas_peucker_bezier3(Point * CONT, int j1, int j2, double d);
//Fonction qui simplifie le contour avec une Bezier quadratique
TTV_Bezier2 * simplification_douglas_peucker_bezier2(TTV_Point CONT, int j1, int j2, double d);
#endif /* _BEZIER_H_ */
test_simplification_bezier2.c :
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "image_pbm.h"
#include "geom2d.h"
#include "TTV_Point.h"
#include "TTV_Bezier2.h"
#include "calcul_contours_multiples.h"
int main(int argc, char * argv[])
{
if (argc != 4)
{
printf("Usage: ./test_simplification_bezier <source.pbm> <destination.eps> <distance_seuil>n");
return 0;
}
FILE * f;
double distance_seuil;
int i = 0;
Image M, P;
Point init;
TTV_Point contour;
TTV_Bezier2 * L;
L = creer_TTV_Bezier2_vide();
contour = creer_TTV_Point_vide();
f = fopen(argv[2], "w");
distance_seuil = atof(argv[3]);
//Lecture de l'image
M = lire_fichier_image(argv[1]);
//Creation de l'image masque
P = create_mask_image(M);
fprintf(f, "%%!PS-Adobe-3.0 EPSF-3.0n%%%%BoundingBox: 0 0 %d %dn0 setlinewidthn", M.L, M.H);
while(is_empty(P) == -1)
{
init = trouver_point_init(P);
contour = trouver_pixel_depart_TTV(M,P,init);
while(i < nb_elements_TTV_Point(contour))
{
contour.tab[i].y = fabs((double) M.H - contour.tab[i].y);
i ;
}
i = 0;
L = simplification_douglas_peucker_bezier2(contour, 0, nb_elements_TTV_Point(contour) - 1, distance_seuil);
write_to_file_bezier2(L,f);
}
fprintf(f, "nfillnshowpage");
fclose(f);
return 0;
}
Комментарии:
1. Циклическое включение? Включает ли какой-либо из ваших заголовочных файлов (прямо или косвенно ) первый заголовочный файл?
2. @Someprogrammerdude ну, каждый файл включает в себя другой. bezier.h включает TTV_Bezier2.h, потому что ему нужен тип TTV_Bezier2 для определения функции simplification_douglas_peucker2, а TTV_Bezier2.h включает bezier.h, потому что ему нужен тип Bezier2 для определения типа TTV_Bezier2 и функции element_TTV_Bezier2 . И я не знаю, почему это было бы проблемой, потому что в безье. h Я включаю TTV_Bezier.h и после этого определяю функцию simplification_douglas_peucker_bezier2 .
Ответ №1:
в TTV_Bezier2.h
том, что вы включаете bezier.h, и в том, что вы включаете bezier.h TTV_Bezier2.h
, это источник вашей проблемы
но в bezier.h вам не нужно знать точное определение TTV_Bezier2
, потому что вы ссылаетесь на него только через указатель, поэтому в bezier.h :
- удалить
#include "TTV_Bezier2.h"
- Добавить
struct TTV_Bezier2_;
- замените возвращаемый тип
simplification_douglas_peucker_bezier2
наstruct TTV_Bezier2_ *
И добавляйте #include "TTV_Bezier2.h"
исходные тексты, когда это необходимо
Ответ №2:
У вас циклическая зависимость между bezier.h и TTV_Bezier2.h
Если вы думаете о #include
функции предварительного процессора как о простом сведении исходного кода в один гигантский файл для компилятора, начиная с main.c:
- main включает в себя (среди прочего) TTV_Bezier.h
- TTV_Bezier.h включает bezier.h перед определением или объявлением TTV_Bezier2
- bezier.h будет включать TTV_Bezier.h, но это не будет иметь никакого эффекта из-за включаемых защитных устройств (и это хорошо)
Если вы представите себе сжатый вывод препроцессора в памяти компилятора, содержимое bezier.h присутствует перед любым упоминанием TTV_Bezier , поэтому вы получите ошибку, которую вы видите.
Чтобы исправить это, вы можете либо:
- Переместите
TTV_Bezier2 * simplification_douglas_peucker_bezier2
прототип в TTV_Bezier2.h - ИЛИ переместите структуры, необходимые для обоих заголовков, в новый третий заголовок и включите его в оба.
- или сделайте то, что указано в ответе Бруно, и переадресуйте объявление структуры