PsySc0rpi0n Posted August 29, 2013 at 11:55 AM Report #522869 Posted August 29, 2013 at 11:55 AM (edited) Boas... Ando de novo a tentar perceber como funciona a divisão de código por vários ficheiros e tenho a seguinte dúvida: Tenho um ficheiro que lida com a entrada de dados do utilizador, ou seja, pede os dados ao utilizador, digamos input.c e que tem o respectivo input.h ende estão os protótipos das funções. Depois tenho o fichero (main.h) main.c que interage com o utilizador mostrando mensagens como "Introduça uma das opções" e de seguida preciso de chamar uma das funções do ficheiro input.c. No ficheiro main.c, tenho que fazer o include apenas do input.h ou tenho que fazer apenas do input.c? É que estou com esta dúvida porque normalmente fazem-se includes apenas de ficheiros .h e não de ficheiros .c, mas neste caso eu preciso de usar uma função que está no ficheiro input.c cujos protótipos de funções estão no input.h... Edited August 29, 2013 at 10:20 PM by PsySc0rpi0n Kurt Cobain - Grunge misses you Nissan GT-R - beast killer
HappyHippyHippo Posted August 29, 2013 at 06:23 PM Report #522920 Posted August 29, 2013 at 06:23 PM dois pontos fundamentais : - .h >> só protótipos - .c >> implementação das funções dos protótipos declarados no respectivo .h (e mais se necessitares) agora, nos .c fazes include de todos os .h (nunca .c) onde estão declarados os protótipos da funções que necessitas/usadas no ficheiro .c IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
PsySc0rpi0n Posted August 29, 2013 at 10:25 PM Author Report #522940 Posted August 29, 2013 at 10:25 PM Vi que me enganei a escrever no post anterior. Mas o que eu queria perguntar é se o main.c tem acesso às funções do input.c através do input.h Ou seja: main.c #iclude "main.h" #include "input.h" int main(){ ... func1();//função presente em input.c com o seu protótipo em input.h ... } input.c #include "input.h" int func1(){ //to do stuff } input.h int func1(); Kurt Cobain - Grunge misses you Nissan GT-R - beast killer
HappyHippyHippo Posted August 29, 2013 at 11:37 PM Report #522948 Posted August 29, 2013 at 11:37 PM o compilador ao processar o main.c, irá ler o input.h e assumirá que a função func1 existe, não dando erro. se a função existe na aplicação final é da responsabilidade do linker que irá juntar os ficheiros objectos IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
PsySc0rpi0n Posted September 4, 2013 at 08:37 PM Author Report #523480 Posted September 4, 2013 at 08:37 PM Estou a tentar de novo outro pequeno projecto mas no momento de compilar com o make, dá um montão de erros que eu não sei se acontecem por causa de includes mal feitos ou se acontecem devido mesmo a erros do código. Quando tento compilar um programa de um só ficheiro nunca recebo erros deste tipo: http://pastebin.com/12b0ZET6 Refiro-me a essas colunas compridíssimas. Os restantes erros não sei se têm a ver também com estas colunas ou não. Sintetizando: 2 pastas - src e include src - main.c, menus.c, input_option.c, array_int_control.c, array_str_control.c include - main.h, menus.h, input_option.h, array_int_control.h, array_str_control.h, error_handler.h Os ficheiros .c apenas têm o include dos respectivos files .h e do error_handler.h. O Makefile está assim: CC := gcc CFLAGS := -Wextra -Wall -pedantic -std=c99 -Iinclude #OBJECT FILES obj/%.o: src/array_int_control.c src/array_str_control.c src/main.c src/menus.c src/input_option.c | obj $(CC) -o $@ $(CFLAGS) $^ #BIN FILE bin/array_control: obj/array_int_control.o obj/array_str_control.o obj/main.o obj/menus.o obj/input_option.o | bin $(CC) -o $@ $(CFLAGS) $^ obj bin: mkdir obj bin clean: rm -rf obj rm -rf bin .PHONY: clean Kurt Cobain - Grunge misses you Nissan GT-R - beast killer
HappyHippyHippo Posted September 4, 2013 at 09:38 PM Report #523487 Posted September 4, 2013 at 09:38 PM o problema está claramente na dependência circular. 1º - considero que teres dependências circulares é uma demonstração directa de falta de estruturação do código. 2º - o que quero dizer com dependências circulares: //////////////////////////// // ficheiro : header1.h //////////////////////////// // as definições do ficheiro "header2.h" são necessárias para avaliar o ficheiro "header1.h" #include "header2.h" //////////////////////////// // ficheiro : header2.h //////////////////////////// // as definições do ficheiro "header1.h" são necessárias para avaliar o ficheiro "header2.h" #include "header1.h" conclusão, o compilador vai andar como uma pescadinha de rabo na boca ... ora salta para header1.h ora salta para header2.h 3º - deverias usar código para combater dependências circulares e múltiplas declarações devido a múltiplas inclusões: (sim múltiplas inclusões como teres header1.h que faz inclusão de header2.h e header3.h, e o header2.h voltar a fazer a inclusão de header3.h. isto dá directamente erro do compilador por múltiplas definições dos conteúdos do header3.h) //////////////////////////// // ficheiro : header1.h //////////////////////////// #ifndef HEADER1_H #define HEADER1_H // inclusões dos ficheiros necessários #include "header2.h" // as definições do ficheiro "header1.h" #endif /* HEADER1_H */ este tipo de código (do pré-compilador) impede as reavaliação do código porque nota: - se o valor HEADER1_H ainda não estiver definido (#ifndef), então define-o (#define). logo, nunca mais entrará no if, mesmo que a árvore de dependências volte a fazer inclusão do ficheiro tratado. IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
PsySc0rpi0n Posted September 5, 2013 at 09:28 PM Author Report #523560 Posted September 5, 2013 at 09:28 PM Pois... É isso que tenho andado a tentar compreender... Qual das duas é a melhor prática para a melhor estruturação/divisão de código: 1 - Deixar as definições de funções e interacção como utilizador nos files .c e em cada um incluir um file .h respectivo e neste colocar todos os includes necessários, defines, include guards e assinaturas das funções usadas no file .c, ou 2 - incluir nos files .c os #includes dos headers files nativos do C, #defines necessários localmente (necessários apenas para o ficheiro .c) e deixar eventuais #includes de headers files criados por nós, eventuais #defines necessários ao file .h e assinaturas das funções usadas no file .c???? Kurt Cobain - Grunge misses you Nissan GT-R - beast killer
HappyHippyHippo Posted September 6, 2013 at 05:43 AM Report #523585 Posted September 6, 2013 at 05:43 AM dois pontos fundamentais : - .h >> só protótipos - .c >> implementação das funções dos protótipos declarados no respectivo .h (e mais se necessitares) agora, nos .c fazes include de todos os .h (nunca .c) onde estão declarados os protótipos da funções que necessitas/usadas no ficheiro .c IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
PsySc0rpi0n Posted September 6, 2013 at 03:11 PM Author Report #523679 Posted September 6, 2013 at 03:11 PM Então como faço no seguinte exemplo: Tenho o main.c onde apenas tenho mensagens para o utilizador e depois chamo 2 funções que estão no file string.c. Estas duas funções, uma delas pede uma string ao user e a outra mostra essa string no ecrã... Ora tenho que declarar uma variável para guardar essa string e estou a fazê-lo no file main.c mas preciso de #define uma constante que será o tamanho máximo da string. Este define coloco-o em que ficheiro? No main.c, string.c ou string.h? E depois preciso de fazer #include do ficheiro que tem essa constante tanto no main.c como no string.c... Kurt Cobain - Grunge misses you Nissan GT-R - beast killer
HappyHippyHippo Posted September 6, 2013 at 03:50 PM Report #523681 Posted September 6, 2013 at 03:50 PM mas preciso de #define uma constante que será o tamanho máximo da string. Este define coloco-o em que ficheiro? em absolutamente lado nenhum ///////////////////////////////// // string.h ///////////////////////////////// int request_string(char * string, int size); int show_string(char * string); ///////////////////////////////// // string.c ///////////////////////////////// #include "string.h" #include <string.h> #include <stdio.h> int request_string(char * string, int size) { int strlength = 0; printf("escreva a string : "); fflush(stdout); if (fgets(string, size, stdin) == NULL) return -1; strlength = strlen(string); if (string[strlength + 1] == '\n') string[strlength + 1] = 0; return 0; } int show_string(char * string) { printf("A string inserida : %s\n", string); } ///////////////////////////////// // main.c ///////////////////////////////// #include "string.h" int main(int argc, cha ** argv) { char string[256]; if (request_string(string, 256) == 0) { show_string(string); } return 0; } IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
PsySc0rpi0n Posted September 6, 2013 at 04:30 PM Author Report #523686 Posted September 6, 2013 at 04:30 PM Hum, ok... Mas não tinhas dito o outro dia que as mensagens da interacção com o utilizador deveriam ficar fora das funções e deixá-las no main.c ou percebi mal? Kurt Cobain - Grunge misses you Nissan GT-R - beast killer
HappyHippyHippo Posted September 6, 2013 at 04:39 PM Report #523689 Posted September 6, 2013 at 04:39 PM o que eu disse (acho eu porque não faz sentido não ser) é : - ter as funções de interação com utilizador separadas com as de manipulação/gestão dos dados IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now