PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit kleinem C Programm



hunter
05-11-2003, 17:02
In der Uni hat gerade die Vorlesung für die Programmiersprache C begonnen. Dabei taucht ein kleines Beispiel auf, das Wörter, Zeilen und Zeichen einer .c Datei zählen soll. Habe das Programm auch schön ordentlich geschrieben, analysiert und (wie ich meine) verstanden.


#include <stdio.h>

main()
{

int temp,zeichen,woerter,zeilen,status;
cnum status {OUT, IN};
FILE *fd;

fd = fopen ("countchar3.c","r");
status = OUT;
zeichen = woerter = zeilen = 0;

while ((temp=getc(fd))!=EOF)
{
++zeichen;

if (temp == '\n')
{
++zeilen;
}

if (temp == ' ' || temp == '\n' || temp == '\t')
{
status = OUT;
}
else if (status == OUT)
{
status = IN;
++woerter;
}
}

printf ("Zeichen=%d\tWörter=%d\tZeilen=%d\t",zeichen,woerter,zeilen);

}

gcc -o countchar3 countchar3.c

countchar3.c: In function `main':
countchar3.c:7: `cnum' undeclared (first use in this function)
countchar3.c:7: (Each undeclared identifier is reported only once
countchar3.c:7: for each function it appears in.)
countchar3.c:7: parse error before "status"
countchar3.c:11: `OUT' undeclared (first use in this function)
countchar3.c:29: `IN' undeclared (first use in this function)

Er kennt den Typ cnum nicht. Offenbar soll das ein Typ sein, der entweder IN oder OUT ist. Aber das nimmt der Compiler so nicht an.

Zudem frage ich mich warum der status vorher auch schon als Integer deklariert wird.

wraith
05-11-2003, 17:06
enum nicht cnum ;).

Weiterhin ist implicit int deprecated,also deklarriere main als int main.

hunter
05-11-2003, 17:36
Danke. Da war die Schrift mal wieder so klein und unleserlich, das ich da doch glatt ein c entziffert habe.

./countchar3
Zeichen=506 Wörter=73 Zeilen=38


Zwei Fragen hätte ich nun:

1. Wiso wird temp erst als int und dann als enum deklariert ? Könnte das ein Fehler sein, oder hat das einen bestimmten Grund ?

2. Ok. Also "int main" und am Ende dann "return 0". Kannst du mir erklären, warum man das so machen muss bzw. soll ?

wraith
05-11-2003, 17:54
Original geschrieben von hunter

1. Wiso wird temp erst als int und dann als enum deklariert ? Könnte das ein Fehler sein, oder hat das einen bestimmten Grund ?

Also das ist vom Autor sehr ungeschickt gemacht,gerade weil Anfänger das auch verstehen sollen.
Gut,status wurde als int deklarriert und das bleibt status auch bis zum Ende.
Mit enum status {OUT,IN}; wird ein neuer Datentyp deklarriert der den Namen enum status hat (das ist hier entscheidend der Name ist enum status).
Dieser kann zwei Werte annehmen,OUT == 0,und IN == 1.
In der Zeile status = OUT; wird also der int Variablen status eine 0 zugewiesen.

Besser wäre ein namenloser Enum gewesen


enum {OUT,IN};

Um das noch etwas zu verkomplizieren ;)
enum status ist ein Datentyp,jetzt kann man davon eine Instanz erzeugen,nennen wir sie status


enum status {OUT,IN};
enum status status = OUT;

Jetzt sieht man schön,das enum status und status zwei völlig verschiedene Namen sind.
Das wäre auch die logische Variante gewesen status gleich als enum status zu deklarrieren und nicht als int.


2. Ok. Also "int main" und am Ende dann "return 0". Kannst du mir erklären, warum man das so machen muss bzw. soll ?
Der Standard schreibt es so vor.
Implementierungen können auch andere Signaturen für main anbieten,aber nur int main(),und int main(int,char**) sind nötig.

hunter
05-11-2003, 18:16
Hmm. Ich bin in der Tat nun ein kleines bischen verwirrt.

Also status soll ja wirklich nur zwei Zustände annehmen um eben festzuhalten ob man sich gerade bei einem Wort befindet oder zwischen zwei Wörtern.

int status weg zu lassen und nur enum status zu schreiben gibt eine Fehlermeldung. In sofern gibt das schon Sinn, "int status; enum status {OUT, IN};" zu schreiben um festzuhalten, das man sich auf die Variable status bezieht. Aber es klappt auch wenn man nur "enum {OUT, IN};" schreibt.

Also könnte man nun OUT und IN jeder Variable zuweisen, oder ? Aber wiso dann eine Instanz status erzeugen ? :confused: :confused:


Also "int main" braucht man später mal, weil man diese main Anweisung dann auch von anderen Anweisungen aus aufrufen könnte, was man zur Zeit nicht braucht, es didaktisch aber sinnvoll ist ?


Hier noch ein kleines Programm was nicht will:


/* Berechnet 2^i und (-3)^i wobei i von 0 bis 9 läuft */

#include <stdio.h>

int funktion (int m, int n);

int main()
{

int i;

for (i=0; i<10; ++i)
{
printf ("i=%d\t2^i=%d\t(-3)^i=%d\n", i, funktion (2,i), funktion (-3,i));
}

return 0;

}


int funktion (int basis, int n)
{

int p=0, i;

for (i=1; i<=n; ++i)
{
p = p * basis;
}

return p;

}
Da kommen nur Nullen raus. Siehst du vieleicht was hier falsch ist, ich komm zur Zeit irgendwie nicht dahinter ?

wraith
05-11-2003, 18:27
Original geschrieben von hunter

Also status soll ja wirklich nur zwei Zustände annehmen

Ja,darum wäre es besser gewesen,gleich status als enum status zu deklarrieren und nicht als int.


int status weg zu lassen und nur enum status zu schreiben gibt eine Fehlermeldung.

Wenn du int status rausnimmst,mußt du dafür das rein packen.


enum status {OUT,IN};//Der Datentyp
enum status status = OUT;//Dein status Variable.



Also könnte man nun OUT und IN jeder Variable zuweisen, oder ? Aber wiso dann eine Instanz status erzeugen ? :confused: :confused:

IN und OUT sind einfach zwei int Konstanten.
Man hätte sie auch einfach als Makros definieren können.


#define OUT 0
#define IN 1

die enum Variante ist aber besser.
So und irgendeine Variable soll ja zur Laufzeit wechselweise entweder OUT oder IN enthalten.
Also mußt du eine Variable haben,die int Werte speichern kann,daher wurde int status deklarriert.
Aber man kann (wie bereits gesagt) auch ein Variable vom Typ enum status deklarrieren (anstatt int status).Da sieht jeder gleich,"Aha,dieses Vairable soll nur die Werte OUT und IN haben können".


Also "int main" braucht man später mal, weil man diese main Anweisung dann auch von anderen Anweisungen aus aufrufen könnte, was man zur Zeit nicht braucht, es didaktisch aber sinnvoll ist ?

Nein,es ist egal,ob man das Programm von einem anderen Programm ausführt,und dann den Rückgabewert braucht.
Am Ende deines Programms steht (wird vom Compiler generiert):
exit(main());
also der Returnwert von main wird an exit übergeben.



Da kommen nur Nullen raus. Siehst du vieleicht was hier falsch ist, ich komm zur Zeit irgendwie nicht dahinter ?
Du setzt in funktion p auf 0,und multiplizierst immer irgendwas anderes dran,0 mal irgendwas bleibt aber 0.

hunter
05-11-2003, 18:50
Erst mal danke für deine Erklärungen. So langsam steig ich da durch. Mein Problem ist halt, das ich das mehr oder weniger allein aus dem Script lernen muss, da ich die beiden ersten Vorlesungen nicht besuchen konnte.

Zum Programm. Stimmt. p wird mit 1 initialisiert und nicht mit 0. Dann funktioniert es.