2018-09-15, 15:32
  #1
Medlem
Ranndalls avatar
Jag vill skriva en del av programmet i en separat c-fil. Hur skulle man kunna göra detta?

Ursäkta den röriga koden nedan men har i alla fall fetstilat den kod som ska placeras i en annan c-fil.

Undrar alltså hur man skulle kunna skriva den separata c filen samt hur man skulle kompilera allt till ett program om man sitter med en terminal.
__________________
Senast redigerad av Ranndall 2018-09-15 kl. 15:38.
Citera
2018-09-15, 15:58
  #2
Medlem
Jag tror det bästa sättet är att dela upp ditt project i 4 olika filer:

Kod:
Makefile               # Make configuration
filehandling.h       # Functions decla ratino för dina fil funktioner
filehandling.c       # Själva fil funktionerna..
main.c                 # Ditt main program..
Namnen kan säkert välja lite bättre än ovan..


Ta något liten enklare Makefile från nätet.. tex:
https://stackoverflow.com/questions/1484817/how-do-i-make-a-simple-makefile-for-gcc-on-linux

En enkel Makefile behöver INTE använda alla de "smartaste features"..
Men tror att lära sig om hur make är ganska lätt och enkelt.

Tips:
Du skall aldrig behöva komma ihåg några "-Wall -W" eller andra "växlar"
Allt sådant finns inne i Makefile
När du vill bygga ditt program skriver du: make


Header filen skall ha med funktions deklarationer, och skall inkluderas från bägge de andra filerna.
Försöker skissa lite nedanför
[PHP]#include "filehandling.h"
[/PHP]

tex:
filehandling.h
[PHP]#ifndef filehandling
#define filehandling

int read_fordon(fordon* f, int *length);

#endif
[/PHP]
filehandling.c

[PHP]#include "filehandling.h"
#include <stdio.h>

int read_fordon(fordon* f, int *length) {
File *F = fopen..
if f==NULL return -1;
fread..
fclose..
return 0;
}

[/PHP]
Ifrån main.c så skall du inkludera filehandling.h på samma sätt.
Sedan kan du bara använda den funktionen.
__________________
Senast redigerad av sagonar 2018-09-15 kl. 16:02. Anledning: rättstavning och PHP tag
Citera
2018-09-15, 16:43
  #3
Medlem
Ranndalls avatar
Citat:
Ursprungligen postat av sagonar
text.
Tackar, jo har egentligen skrivet funktionerna i en header-fil men postade det inte här. Intressant om man sitter på mac och kompilerar i terminalen kan man också använda "make" då?
Citera
2018-09-15, 17:00
  #4
Medlem
Ranndalls avatar
Citat:
Ursprungligen postat av sagonar
text
Jag vet inte hur man ska skriva i terminalen för att kompilera båda .c filerna. Verkar som terminalen vet vad "make" betyder i alla fall.
Vet inte om c-filen med filhantering är korrekt skriven men postar det här.

filhantering.c


header.c


main.c
Citera
2018-09-15, 17:20
  #5
Medlem
Om du kör gcc från commandline så kan du vara nästan helt säker på att make finns det med
Jag vill mycket starkt rekommendera make

Grund ideen med make tycker jag du skall titta en stund på..
Men tror att tup är en intressant möjlighet(Men har bara lekt lite med det) men är kanske lite för avancerat och tror att make är bättre start

Start tutorial om make:
http://mrbook.org/blog/tutorials/make/
Läs början i den, eller något annan turorial !!!!!!

Ett enklare c exempel från Stackoverflow..
Programmet som skall skapas kallas här "program"

Om du vill skapa programmet så kan du göra det genom att skriva
make

Om du vill ta bort alla saker som skapas (inte källkoden och inte MAkefilen)
Då kan du skriva make clean

I exemplet nedan kan du skriva:
make main.o




Men försöka gärna titta på det exemplet och experimentera lite..
Se tutorial ovan..

$@ och $< ... Plockar upp vördet från samma "regel" som du kör..
$@ är namnet på det som skall skapas...
$< är det första "dependency'n" (Det första namns om kommer efter


[PHP]HEADERS = filehandling.h
OBJECTS = filehandling.o main.o

default: program

%.o: %.c $(HEADERS)
gcc -c $< -o $@

program: $(OBJECTS)
gcc $(OBJECTS) -o $@

clean:
-rm -f $(OBJECTS)
-rm -f program[/PHP]
Citera
2018-09-15, 21:40
  #6
Medlem
Ranndalls avatar
Citat:
Ursprungligen postat av sagonar
text
Tack för ditt inlägg och länken. Tyvärr blev jag inte så mycket smartare av detta. Jag kanske är efterbliven, mycket troligt men men. Testade att kompilera i terminalen med " gcc main.c filh.c -o prog" fick då felkommandot "clang: error: linker command failed with exit code 1 (use -v to see invocation)" samt att den klagade på "3 duplicate symbols" i main.c och filh.c
__________________
Senast redigerad av Ranndall 2018-09-15 kl. 21:47.
Citera
2018-09-15, 22:05
  #7
Medlem
kaks avatar
Citat:
Ursprungligen postat av Ranndall
Tack för ditt inlägg och länken. Tyvärr blev jag inte så mycket smartare av detta. Jag kanske är efterbliven, mycket troligt men men. Testade att kompilera i terminalen med " gcc main.c filh.c -o prog" fick då felkommandot "clang: error: linker command failed with exit code 1 (use -v to see invocation)" samt att den klagade på "3 duplicate symbols" i main.c och filh.c
I headern skall du enbart ha deklarationer. Inga definitioner.
Du för dubletter då de symboler du definierat i headern instantieras en gång för varje c-fil den inkluderas i.
Citera
2018-09-15, 22:23
  #8
Medlem
Citat:
Ursprungligen postat av Ranndall
Tack för ditt inlägg och länken. Tyvärr blev jag inte så mycket smartare av detta. Jag kanske är efterbliven, mycket troligt men men.

Nej men det är liksom ingen idé att försöka ge sig på att dela upp programmet i fler än en källkodsfil eller skriva headerfiler, speciellt inte båda på en gång, innan man kan skilja på en definition och en deklaration, eller extern vs statisk länkning.
Citera
2018-09-15, 23:41
  #9
Medlem
Ranndalls avatar
Citat:
Ursprungligen postat av kak
I headern skall du enbart ha deklarationer. Inga definitioner.
Okej, i min kod header.h (skrev fel inte header.c) så består väl endast funktionerna av deklarationer? Eftersom jag inte definierar exakt vad som ska ligga där. Det gör jag väl i main.c med scanf eller filh.c med filhanteringen. Fast struct fordon har jag nog definierat i headern. Tänker jag rätt då?
__________________
Senast redigerad av Ranndall 2018-09-15 kl. 23:48.
Citera
2018-09-16, 00:15
  #10
Medlem
kaks avatar
Citat:
Ursprungligen postat av Ranndall
Okej, i min kod header.h (skrev fel inte header.c) så består väl endast funktionerna av deklarationer? Eftersom jag inte definierar exakt vad som ska ligga där. Det gör jag väl i main.c med scanf eller filh.c med filhanteringen. Fast struct fordon har jag nog definierat i headern. Tänker jag rätt då?
Du har tre definitioner i din header: f, add och delete.
Citera
2018-09-17, 13:29
  #11
Medlem
Multipla filer, del 1.

`gcc main.c meny.c fordon.c` preprocessar, kompilerar och assemblerar var fil för sig, och länkar ihop resultatet till en programfil. Här med namnet a.out, eller a.exe i Windows, då inget angetts med -o. Preprocessingen gör saker som att infoga innehållet i filen stdio.h vid kommandot `#include <stdio.h>` och ersätta ANTAL_FORDON med 10 efter `#define ANTAL_FORDON 10`. Kompileringen skapar assemblerkod för en viss typ av maskin, normalt den man kompilerar på, från C-koden. Assembleringen skapar objektkod, som är maskinkod plus diverse information till länkaren, och länkningen sätter ihop objektkoden.

Preprocessing, kompilering och assemblering kallas ofta tillsammans bara för kompilering. Ibland inkluderas även länkningen i ordet kompilering; man kompilerar ett program.

Processen kan med -c, -E eller -S avbrytas tidigare än länkningen och resulterar då inte i en programfil utan i mellanlagrade filer av respektive typ (eller output på stdout för -E), och/eller påbörjas senare än preprocessingen genom att mata gcc med annat än källkodsfiler (*.c). Man skulle exempelvis kunna köra `gcc -S fordon.c`, redigera assemblerfilen fordon.s som skapas, sen bygga programmet med `gcc main.c meny.c fordon.s`. Om någon eller några inputfiler av någon anledning inte har rätt file extension, anger man typen av fil med -x.

Det vanligaste är att skapa objektfiler (*.o) av allting, så att man efter ändrigar i en av källkodsfilerna inte behöver kompilera om de andra. Kompileringen är det som tar tid, inte länkingen.

Kod:
gcc -c main.c meny.c fordon.c # skapar main.o, meny.o och fordon.o
gcc -o garage main.o meny.o fordon.o
./garage
...
# redigera main.c
gcc -c main.c # skriver över main.o
gcc -o garage main.o meny.o fordon.o # samma som förut

Allt kan skötas automatiskt med en enkel makefil, där man anger vilka andra filer en fil har beroende av och hur den ska byggas om från dem om det behövs, som make avgör genom att jämföra ändringsdatumen. Döp filen till "Makefile" för att slippa ge namnet med -f.

https://www.bing.com/search?q=make+tutorial
Citera
2018-09-17, 21:53
  #12
Medlem
Citat:
Ursprungligen postat av Ranndall
Jag vet inte hur man ska skriva i terminalen för att kompilera båda .c filerna.

Du anger helt enkelt flera fil-argument (c-filer) till kompilatorn:
gcc fil1.c fil2.c fil3.c (osv.)
(byt ut "gcc" mot "clang" om du kör clang)

Lite förenklat kan man säga att kompilatorn kompilerar varje källkodsfil var för sig utan att ta hänsyn till någon av de andra källkodsfilerna. Det betyder att fil1.c inte har någon aning om vad som finns i fil2.c (och vice versa). Om du exempelvis har en funktion i fil2.c som du vill kunna anropa i fil1.c brukar man skriva en header-fil som deklarerar vad som finns i fil2.c och sedan inkluderar man denna header-fil inuti fil1.c.

Låt oss skapa ett exempelprogram som består av två källkodsfiler, foo.c och bar.c:

foo.c:
Kod:
int add(int a, int b) {
	return a + b;
}

bar.c:
Kod:
#include <stdio.h>

int main(void) {
	printf("%d\n", add(4, 5));
	return 0;
}

I bar.c (i main-funktionen) anropar vi alltså funktionen "add" som finns definierad i filen foo.c.
Låt oss försöka kompilera ovanstående program som alltså består av två filer, foo.c och bar.c:
Kod:
$ gcc foo.c bar.c
bar.c:4:17: WARNING: Implicit declaration of function "add"

Ajdå! Kompilatorn varnar att bar.c inte vet vad "add" är för funktion. Vi behöver berätta för bar.c
vad "add" är för funktion. Dvs: Vad funktionen heter, hur många parametrar och vilken datatyp respektive parameter har och vilken retur-datatyp den har). Detta gör vi med en funktionsdeklaration, dessa skrivs normalt i en header-fil (om funktionen behöver anropas från en annan fil, annars kan man skriva den direkt i c-filen). Header-filen som tillhör en .c-fil döps normalt till samma namn som c-filen men med filändelsen .h istället för .c, detta är dock bara en konvention, du kan döpa h-filen till vad du vill.
Låt oss skapa header-filen foo.h (i samma mapp där bar.c och foo.c redan ligger) med en funktionsdeklaration för funktionen "add":

foo.h:
Kod:
int add(int a, int b);
Observera att en funktionsdeklaration ser ut som en funktionsdefinition med funktionskroppen utelämnad, man sätter också ett semikolon direkt efter parameterlistan.

Vi kan nu inkludera header-filen (foo.h) inuti bar.c så bar.c vet vad "add" är för funktion.
Vi gör detta genom att lägga till #include "foo.h" i början av bar.c:

bar.c: (ny)
Kod:
#include "foo.h"
#include <stdio.h>

int main(void) {
	printf("%d\n", add(4, 5));
	return 0;
}

Låt oss nu kompilera programmet en gång till:
Kod:
$ gcc foo.c bar.c
$ ./a.out
9
Observera att vi anropar kompilatorn precis som innan, man ska alltså inte ange .h-filen på kommandoraden till kompilatorn, den inkluderas ju av bar.c.
Vi ser att programmet kompileras utan problem.
Och när vi kör programmet (a.out) skrivs också talet 9 ut som förväntat.
----------------

Din fil "filhantering.c" ser lite konstig ut. Borde den inte innehålla två funktioner, en för att läsa fordon från fil och en funktion för att skriva fordon till fil? Nu ligger all kod i en enda funktion som heter "read_fordon"...

Sen kommer du behöva bryta ut en del definitioner och deklarationer till en extra header-fil eftersom filhantering.c behöver veta vad tillexempel "ANTAL_MAX_FORDON" och "f" är för något. Och filhantering.c kommer själv behöva en tillhörande header-fil (filhantering.h) så andra källkodsfiler kan anropa dess funktioner. Och du behöver såklart inkludera en del header-filer från standardbiblioteket i filhantering.c så den kan hitta "FILE", "memset()" och så vidare... Lycka till!

(Senaste koden du postat är uppdelad i tre källkodsfiler (filhantering.c, header.c och main.c), jag tror att du börjar snurra till det för dig själv nu. Börja med att dela upp koden i två källkodsfiler: filhantering.c och resten av koden i main.c (med tillhörande header-filer), sen när du fått detta att fungera kan du bryta upp koden i ytterliggare källkodsfiler om du tycker det skulle behövas.)
Citera
  • 1
  • 2

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Det är enkelt att registrera ett nytt konto

Bli medlem

Logga in

Har du redan ett konto? Logga in här

Logga in