• Добро пожаловать на компьютерный форум Tehnari.ru. Здесь разбираемся с проблемами ПК и ноутбуков: Windows, драйверы, «железо», сборка и апгрейд, софт и безопасность. Форум работает много лет, сейчас он переехал на новый движок, но старые темы и аккаунты мы постарались сохранить максимально аккуратно.

    Форум не связан с магазинами и сервисами – мы ничего не продаём и не даём «рекламу под видом совета». Отвечают обычные участники и модераторы, которые следят за порядком и качеством подсказок.

    Если вы у нас впервые, загляните на страницу о форуме и правила – там коротко описано, как задать вопрос так, чтобы быстро получить ответ. Чтобы создавать темы и писать сообщения, сначала зарегистрируйтесь, а затем войдите под своим логином.

    Не знаете, с чего начать? Создайте тему с описанием проблемы – подскажем и при необходимости перенесём её в подходящий раздел.
    Задать вопрос Новые сообщения Как правильно спросить
    Если пришли по старой ссылке со старого Tehnari.ru – вы на нужном месте, просто продолжайте обсуждение.

Подключение модулей

  • Автор темы Автор темы voipp
  • Дата начала Дата начала

voipp

Новые
Регистрация
21 Сен 2009
Сообщения
23
Реакции
0
Баллы
0
Подключение модулей

имеются три сишных модуля и 3 их хидера.
нужно что бы из 1 модуля можно было использовать данные из 2 и3, а из 2 только - 3.по какому принципу их подключать(я имею в виду не синтаксис инклуд)?
Как и где стоит писать директивы препроцессора от двойного копирования, я имею в виду в каких модулях (и)или хидерах.в 1 модуле находится мэйн.
 
Директивы от двойного включения - во всех хидерах, как обычно принято.

А по поводу как подключать - при таком раскладе 2-ой модуль жёстко привязан к 3-му, поэтому логичным было бы (далее для простоты буду описывать в виде номер_модуля.расширение):
в 2.h - include "3.h" - раз уж второй и третий идут исключительно в связке
в 1.h - include "2.h" - на самом деле всё зависит от того, используешь ли ты в интерфейсах первого модуля что-то, определенное во втором и третьем - если да то так, если нет - то можно заинклудить 2.h в файле 1.с
в 3.c - include "3.h"
в 2.c - include "2.h"
в 1.c - include "1.h"

Соответственно в проект (каким бы набором не пользовался) добавляешь три исходника - 1.c,2.c,3.c и всё.

В общем случае - как то так. В некоторых специфических задачах могут быть незначительные вариации - но без них на самом деле как правило спокойно можно обойтись, примерно как без goto))))))))
 
Тоесть получается что бы была связт во ВСЕХ модулях ДОСТАТОЧНО подключить их таким образом что бы между ними всеми был ПУТЬ? Путь это значит что открывая для некоторого файла a.c файл b.h(b проинклюден в a.h) а в b.h - c.h(который опять же проинклюден в b.h) и так далее то можно добраться до любого .h файла внутренности которого используются в a.c(я имею ввиду конечно же не сам .h файл а соответствующий ему .c файл).Получается как бы дорога между городами - Для города можно достать товары из других городов если между ними есть дорога?

А как насчет подключения библиотек? Если в каком нибудь модуле она используется то где писать ее инклуд и нэймспэйс?
 
Последнее редактирование:
Тоесть получается что бы была связт во ВСЕХ модулях ДОСТАТОЧНО подключить их таким образом что бы между ними всеми был ПУТЬ? Путь это значит что открывая для некоторого файла a.c файл b.h(b проинклюден в a.h) а в b.h - c.h(который опять же проинклюден в b.h) и так далее то можно добраться до любого .h файла внутренности которого используются в a.c(я имею ввиду конечно же не сам .h файл а соответствующий ему .c файл).Получается как бы дорога между городами - Для города можно достать товары из других городов если между ними есть дорога?

Формально - да.
А фактически - есть некоторое ограничение на максимальную вложенность, поэтому увлекаться проектированием библиотеки или программы в виде таких цепочек зависимостей - не стоит. На практике 5-6 уровней - это нормально.
На самом деле всё намного проще понимается, если учитывать, что include просто вставляет кусок текста программы в место где инклудится. Соответственно когда ты инклудишь файл, в котором подключен другой файл - ты автоматом его тоже подхватываешь.


А как насчет подключения библиотек? Если в каком нибудь модуле она используется то где писать ее инклуд и нэймспэйс?

Если она используется только в коде функций/методов - то инклуд в начале c-файла с этими функциями/методами. Если же и в интерфейсе (т.е. в header'ах модуля используется, например, константа или определение класса из этой библиотеки или функция/метод где используется определены прям в .h-файле) - то в хидере к модулю.
А namespace - смотря какой вариант используешь - но либо в начале файла сразу после инклуда, либо, например, в теле определения класса.

На самом деле библиотека или другой модуль - практически нет разницы. Просто библиотека, как правило, уже скомпилирована - а в остальном в использовании это тот же модуль. (Ну, есть правда такая вещь как, например, шаблоны - тут могут быть проблемы с инстанцированием некоторых конкретных классов в случае библиотек - но не думаю что на данном этапе это тебя коснётся).
 
я подключил в 1.cpp - 1.h и в 1.h - 1.cpp.Но выдается ошибка в загаловке функции в 1.cpp - forward.В этой функции я использую переменную мною определенного типа, описание которого находится в 1.h(там же я написал заголовки всех функций модуля все глобальные переменные и опеределения новых типов).Может все дело в том что в 1.h файле инклуд"1.cpp" стоит почти на самом 1 месте до определений функций и типов?
 
Так...зачем инклуд 1.cpp в 1.h?? Опечатка, на самом деле наоборот?
Вообще предлагаю код "в студию", тогда смогу сказать что не так. Без исходников сложно гадать))
 
Tree.cpp(не весь) :

#include"Tree.h"
#include<stdlib.h>
#include<iostream>

using namespace std;

void Print_Error(int i){
cout<<"ERROR: ";
switch (i) {
case 0:
cout<<"OK";
break;
case 1:
cout<<"No Memory";
break;
case 5:
cout<<"NoSuchWord";
break;
case 6:
cout<<"Duplicate dict element";
break;
case 7:
cout<<"Bad file format";
break;
case 9:
cout<<"Incorrect type of data elements";
break;
case 129:
cout<<"Incorrect input";
break;
cout<<endl;
};
};


void Left_Rotate(struct RBTree* NIL,struct RBTree* x){
if(x->right!=NIL){
struct RBTree* y;
y=x->right;
x->right=y->left;
if(y->left!=NIL)
y->left->parent=x;
y->parent=x->parent;
if(x->parent!=NIL){
switch (x==x->parent->left){
case true:
x->parent->left=y;
break;
case false:
x->parent->right=y;
break;
};
}
else{
//y->parent=x->parent;
x->parent->left=y;
x->parent->right=y;
NIL->parent=y;
};

y->left=x;
x->parent=y;

};

};

Tree.h :

#pragma once
#ifndef TREE
#define TREE

//#include<string.h>

//#include "Tree.cpp"

// cvet uzla dereva
enum color{RED,BLACK};

// dlina stroki v sluchae tipa STRING
int len=0;

// tipbI kluchey
enum type{SHORT,INT,LONG,STRING};


typedef unsigned int Int;
typedef unsigned long int Long;
typedef unsigned short int Short;

// element slovaria - kluch i znachenia
struct dict{
void* word;
unsigned long int* number;
int size;
};

// struktura dereva
struct RBTree{
enum color col;
struct RBTree* left;
struct RBTree* right;
struct RBTree* parent;
dict* key;
};




// pechatb oshibok
void Print_Error(int i);

// izmenenie znachenii ukazateley sohraniauchee svoistva RB dereva
void Left_Rotate(struct RBTree* NIL,struct RBTree* x);
void Right_Rotate(struct RBTree* NIL,struct RBTree* x);

// pechatb dereva na ekran
void Print_Tree(RBTree* node,int h,RBTree*NIL,type TP);

//void Space(char *str,int* i);

// vosstanovlenie svoistv RB dereva posle vstavki
void Fixup_Insert(RBTree* node,RBTree* NIL);

// vstavka novogo uzla v derevo
void Insert(struct RBTree* NIL,RBTree* node,enum type dict_type);

// vosstanovlenie svoistv RB dereva posle udaleniya
void Fixup_Delete(RBTree* NIL,RBTree* node);

// kopirovanie znachenii odnogo uzla v drugoi
void Copy(RBTree* from,RBTree* to,type dict_type);

// udalenie uzla dereva
bool Delete(RBTree* NIL,RBTree* node,type dict_type);

// poisk uzla v dereve
RBTree* Find(RBTree* NIL,RBTree* top,void* wrd,enum type dict_type);

// polnoe udalenie dereva
void Delete_Tree(RBTree* node,RBTree* NIL);


#endif

Ошибка :
forward declaration в void Left_Rotate(struct RBTree* NIL,struct RBTree* x)

invalid use of: y=x->right;
 
Так...всё очень интересно. Формальных ошибок не нашёл, более того мой компилятор (GCC) съел код за милую душу (при добавлении строчки int main(){;} в конец cpp-файла).
Вообще говоря, forward declaration - это просто предварительное объявление - в данном случае это объявление в h-файле перед непосредственно реализацией в cpp и ошибкой обычно не является - ошибка только если в нескольких местах идёт определение одной и той же функции с разными параметрами (но не перегрузка).
Почему не работает присваивание - из кода тоже непонятно.

Соответственно возможны варианты:
а) Проблема в другой части кода - попробуй собери код из двух обрезанных файлов, что выложил сюда - добавив пустую функцию main. Есть шанс что заработает как и у меня - тогда ошибка в другой части;
б) Проблема в компиляторе? Напиши каким и какой версией пользуешься.



P.S. В след. раз лучше будет выглядеть, если каждый кусок кода (каждый файл) обрамишь в сообщении тегами CODE /CODE
Код:
Будет выглядеть так...и с отступами - читабельнее
 
main:
Код:
#include"Parsing.h"
#include<stdio.h>

int main(void){
int y;
scanf("%d",&y);
return 0;
};

Parsing.h:
Код:
#pragma once
#ifndef PARSING
#define PARSING
#include<iostream>

#include "Tree.h"
//#include "WorkWithDeq.h"

using namespace std;
// .....

#endif

Parsing.cpp:
Код:
#include"Parsing.h"
#include<stdlib.h>
#include<fstream>
#include<iostream>
using namespace std;
//.......

Tree.h:
Код:
#pragma once
#ifndef TREE
#define TREE

//#include<string.h>

//#include "Tree.cpp"

// cvet uzla dereva
enum color{RED,BLACK};

// dlina stroki v sluchae tipa STRING
int len=0;

// tipbI kluchey 
enum type{SHORT,INT,LONG,STRING};


typedef unsigned int Int;
typedef unsigned long int Long;
typedef unsigned short int Short;

// element slovaria - kluch i znachenia
struct dict{
	void* word;
	unsigned long int* number;
	int size;
};

// struktura dereva
struct RBTree{
	enum color col;
	struct RBTree* left;
	struct RBTree* right;
	struct RBTree* parent;
	dict* key;
};




// pechatb oshibok
void Print_Error(int i);

// izmenenie znachenii ukazateley sohraniauchee svoistva RB dereva
void Left_Rotate(struct RBTree* NIL,struct RBTree* x);


#endif

Tree.cpp
Код:
#include"Tree.h"
#include<stdlib.h>
#include<iostream>

using namespace std;

void Print_Error(int i){
//.....
};


void Left_Rotate(struct RBTree* NIL,struct RBTree* x){
//.....

};

Ошибка - previous declaration в Tree.h строка с enum type{SHORT,INT,LONG,STRING};
 
Последнее редактирование:
хотя до этого места этого перечисления нигде нет.компилятор g++ непонятно какой версии
 
Последнее редактирование:
previous declaration для len, я так понял судя по мессагам моего компилятора?

Попробуй заменить в Tree.h
int len=0;
на
extern int len;

а в Tree.cpp после
using namespace std;
вставить int len = 0;
 
компилятор выводит какой-то модуль на строчке typedef int INT.Я взял в перечислении в файле Tree.h и заменил INT на tpINT.после перестройки ничего не изменилось
 
все ошибка исчезла - компилятор не мог нормально перестроить проект
 
Назад
Сверху