Hallo,
ich habe folgendes Problem. Ich Möchte eine Namensliste mit C sortieren
können und entscheiden ob sie nur als Bildschirmausgabe oder auch als
Textdatei angezeitg werden soll. Es sollen 5 verschiedene
Sortiervarianten möglich sein. Nun habe ich das Problem, dass er mir
nicht mal eine Zeile ordentlich ausgibt. Er schreib mir nur ein wirrwa.
Meine C-Kenntnisse sind leider sehr begrenzt. Ich habe die main.c uund
die Liste mit angehangen. Ich lasse gerade nur eine Zeile darstellen, da
die Formatierung dort schon nicht stimmt.
Wäre schön, wenn jemand eine schnelle Lösung hat, da ich nur noch bis
Donnerstag Zeit habe.
Lg Florian
Ach mir fiel gerade auf, dass ich in der int Bildschirmausgabe() die
falsche Datei zum öffnen hatte. Natürlich soll dort die geschriebene
Datei ARBZEIT.txt geöffnet werden.
drehst du erst mal um.
Du brauchst zuallererst mal eine Struktur, die die EINE Person speichern
kann. HIer ist sie
1
structperson
2
{
3
charPersonalNr[5];
4
charName[41];
5
charDatum[11];
6
charTag[6];
7
charMonat[7];
8
charJahr[8];
9
};
Und dann erzeugst du dir davon ein Array, welches 25 Personen speichern
kann
1
structpersonPersonen[25];
Weiters.
Das hier
1
voideinlesen()
2
{
3
structstrPersonal;
4
5
...
6
}
und das hier
1
voidsortierabfrage(void)
2
{
3
structstrPersonal;
4
5
....
6
}
sind NICHT dieselben Variablen, auch wenn sie gleich heißen. Das sind
zwei voneinander unabhängige Variablen, die nur zufällig den gleichen
Namen tragen. Mehr aber auch nicht. Funktionslokale Variablen werden
erzeugt, wenn eine Funktion betreten wird und sie werden zerstört, wenn
die Funktion verlassen wird.
WEnn du globale Variablen haben willst, die in allen Funktionen bekannt
sind, dann musst du die ausserhalb der Funktionen definieren.
Und zu guter letzt halte dich an die einfache Regel, dass eine Funktion
nur das tun soll, was ihr Name besagt.
Eine Funktion heißt einlesen, weil ihr Job darin besteht, die Daten aus
dem File einzulesen. Eine Funktion heißt ausgeben, weil ihr Job darin
besteht, die Daten aus dem Array auszugeben. Die Verteilung der Aufgaben
geschieht in main(). Dort ist die Schaltzentrale, die den Benutzer
fragt, was er tun möchte und entsprechend die Funktionen aufruft. Es ist
aber nicht der Job einer Funktion namens 'einlesen' diese Aufgabe
durchzuführen.
Des weiteren ist es eine extrem gute Idee, wenn du dir neben dem Array,
welches die eigentlichen Daten hält, noch eine zusätzliche Variable
einführst, welche dir sagt, wieviele der Arrayeinträge überhaupt gültig
sind. Schliesslich sagt ja kein Mensch, dass in dem Textfile immer 25
Personen beschrieben sein müssen
1
structpersonPersonal[25];
2
intAzahlPersonen=0;
Beim Einlesen zählst du diese Anzahl entsprechend mit, so dass dir diese
Anzahl dann bei der Sortierung bzw. der Ausgabe zur Verfügung steht.
Noch ein paar Tipps:
Aktiviere für den C-Compiler die Ausgabe von Warnungen. Einige dieser
Warnungen weisen auf schwerwiegende Fehler hin.
Wenn das Programm ohne Warnmeldungen kompiliert wird, dann starte das
Programm und achte auf die Fehlermeldungen, die es ausgibt. Bei mir
erscheint bspw. beim Öffnen von "workload.txt" folgende Meldung
"Datei konnte NICHT geoeffnet werden.\n"
obwohl die Datei existiert. Woran das wohl liegen könnte? Lies dir noch
einmal die Dokumentation von fopen durch.
Wenn das Programm keine Fehlermeldungen mehr ausgibt, die Ausgabe aber
immer noch fehlerhaft ist, gehe das Programm im Debugger Schritt für
Schritt durch und überprüfe die jeweils berechneten Variablen auf ihre
Richtigkeit. Wenn eine Variable einen unsinnigen Inhalt hat, weißt du
sofort, wo du suchen musst. Falls du keinen Debugger installiert hast
oder ihn nicht bedienen kannst, kannst du das Programm auch mit
printf-Ausgaben wichtiger Zwischenergebnisse spicken.
Lies dir auch die Dokumentation von strncpy noch einmal durch. Es
sieht nicht so aus, als ob du diese Funktion im Detail verstanden
hättest.
Vielen Dank für die schnellen Antworten.
Ich habe die Änderungen mal versucht, aber dann kommt die Fehlermeldung,
das Personal nicht zugeordnet werden kann. Nun weiß ich nicht, wie ich
das umsetzen muss.
Ja, mir fehlt es noch ein wenig an Grundlagen. Teilweise fehlen mir
leider die Zusammenhänge.
Florian P. schrieb:> Vielen Dank für die schnellen Antworten.> Ich habe die Änderungen mal versucht, aber dann kommt die Fehlermeldung,> das Personal nicht zugeordnet werden kann. Nun weiß ich nicht, wie ich> das umsetzen muss.>> Ja, mir fehlt es noch ein wenig an Grundlagen. Teilweise fehlen mir> leider die Zusammenhänge.
Das ist ziemlich schlecht, wenn dir das in dieser Phase auffällt.
Mit einer derartigen Aufgabenstellung solltest du eigentlich mit deinem
Wissen schon viel weiter sein.
compilieren, eventuelle Tippfehler von mir beseitigen und dann erst mal
testen. Wenn das dann funktioniert, dann baust du in eingeben deine
Dateibehandlung ein. Wieder: testen.
Wenn das dann einwandfrei funktioniert, dann machst du einen weiteren
Menüpunkt dazu, der auf eine Datei ausgibt.
Wieder: testen.
Und wenn das dann auch noch funktioniert, dann kommt das sortieren dazu.
Ein Sortierkriterium nach dem anderen mit jeweils einem eigenen
Menüpunkt, wobei jedes, nachdem es fertig implementiert wurde, getestet
wird.
Aber nicht alles auf einmal.
Auch wenn es noch nicht soweit ist, trotzdem gleich mal ein PS:
man kann Strukturobjekte als ganzes zuweisen!
Du darfst also schreiben
1
structpersontmp;
2
3
....
4
5
tmp=Personal[i];
6
Personal[i]=Personal[i+1];
7
Personal[i+1]=tmp;
8
...
um 2 Array Einträge miteinander zu vertauschen. Da werden dann komplette
"struct person" Objekte zugewiesen, also alle Member, egal wieviele das
auch sind.
Genau deshalb ist es sinnvoll, dass EINE Struktur auch nur EINE Person
beschreibt. Denn mit EINEM struct person Objekt hast du alles beisammen,
was EINE Person in deiner Datenbank ausmacht und die kannst du als EINE
Einheit betrachten, wenn das in der jeweiligen Teilaufgabenstellung
zweckmässig ist.
Ich danke schon mal für die Geduld mit mir. Nun gibt er den Fahler aus,
"request for member "PersonalNr" in something not a structure or union".
Der Fehler ist mein Hauptproblem und war auch der Grund, warum ich die
struct str Personal; hinter die int...(); gelegt habe. Aber das hatte ja
bekanntlich auch nicht geklappt, da er ja so nichts schreiben kann.
deine grundsätzliche Programmstruktur ist "falsch".
schau mal in KHB's Beitrag von 01.07.2013 21:53 nach, wo er das "main()"
platziert hat, wo du es hast, und was das bedeuten könnte.....
Florian.p schrieb:> aber es funktioniert trotzdem nicht.
das ist ja mal eine detaillierte Fehlerbeschreibung.
Daraufhin kann man einen genau so detaillierte Fehlerbehebungs-Ratschlag
geben:
"Du mußt das Programm so korrigieren, daß der Fehler nicht mehr
auftritt".
PS: Bitte Sourcecode als Anhang posten, dann klappst auch mit dem
Syntax-markieren (siehe deinen ersten Beitrag)
Kann es sein, Das es an Windows liegt, dass er so eine Fehlermeldung aus
gibt. Es besteht weiterhin folender Fehler : "request for member
"PersonalNr" in something not a structure or union" bei folgendem
Programm.
> Kann es sein, Das es an Windows liegt, dass er so eine Fehlermeldung aus gibt.
Nein.
Das liegt schon an deinen Fähigkeiten, bzw. eigentlich
Nicht-Fähigkeiten.
> strncpy(Personal.PersonalNr[i],puffer+0,4); //einlesen der Daten
Vergleich mal mit den strcpy wie ich sie geschrieben habe!
Was ist jetzt das Array?
Ist Personal das Array? Ja!
Daher musst du erst mal sagen, welchen von den 25 Einträgen in Personal
du haben willst.
Also zb den mit der Nummer i
1
Personal[i]
da Personal ein komplettes Array aus lauter 'struct person' Objekten
ist, ist Personal[i] einer davon - nämlich der i-te. Ein komplettes
'struct person' Objekt. Und so ein Object hat einen Member. Zb den
Member PersonalNr. Um also den zu erreichen lautet die Schreibweise
daher
1
Personal[i].PersonalNr
Einfach von links nach rechts durchgehen und jeweils überlegen was jetzt
was ist - welcher Datentyp da jeweils dahinter steckt. Es ist von der
Schreibweise her völlig logisch. Vom Groben, durch jeweilige Auswahlen,
zum immer feineren, bis man beim Member landet, den man haben will,
ausgehend von der kompletten Datenbank.
Ich hab es extra das Programm so weit vollständig geschrieben, dass du
dir dort bei Syntaxfragen auch die SChreibweisen ansehen kannst. Aber
Code studieren und mit dem abgleichen, was du eigentlich vor Wochen
schon hättest lernen sollen, das musst du schon selber!
Wenn sich der Aufbau der Daten verändert hat, dann wird sich wohl auch
der entsprechende Code dafür verändern und an die geänderten
Gegebenheiten anpassen müssen!
Und das hier
1
Personal.PersonalNr[i][41]=0;
solltest du dir auch noch mal genauer ansehen! Das es
1
Personal[i].PersonalNr[41]=0;
heissen muss sollte ja jetzt klar sein. Aber: Ist deine eine PersonalNr
überhaupt mindestens 42 Zeichen lang? Mal sehen
1
structperson
2
{
3
charPersonalNr[5];
Nö. Ist sie nicht. Eine PersonalNr besteht aus 5(!) Zeichen und nicht
aus 42.
PersonalNr[0]
PersonalNr[1]
PersonalNr[2]
PersonalNr[3]
PersonalNr[4]
also die mit den Indexnummern 0 bis 4. Zähl nach. Sind genau 5 Stück.
(Ich kann schon erraten, was du eigentlich wolltest, aber auch dann hast
du da immer noch einen Fehler, für den ich dir hiermit mit dem
'Nachzählen' der Array-Elemente einen Hinweis gegegben habe)
printf("Moechten Sie die unsortierte Liste angezeigt bekommen?\n (1) fuer Ja und (2) fuer Nein:\n\n");
2
scanf("%d",&Liste);
3
4
if(Liste==1)
wozu brauchst du das schon wieder in 'eingeben'. Kein Mensch braucht das
dort. WEnn sich der Benutzer die unsortierte Liste ansehen will, dann
macht er das im main mit dem Menüpunkt 2 (ausgeben), gleich nachdem er
die Daten vom File einlesen gelassen hat. Du brauchst das hier nicht.
Kümmere dich lieber darum, dass deine AnzahlPersonen Variable den
richtigen Wert hat, anstatt dass du da 100-tausend Texte an allen Ecken
und Enden ausgibst. Ein gutes Programm ist eines das funktioniert und
nicht eines, das beim Beenden "Auf Wiedersehen" hinschreibt.
Ich hatte nur 15 Vorlesungsstunden und dann die aufgabe bekommen. Das
alles in einem recht engen Zeitfenster, deswegen bin ich auch so
wissenslos. Mit der Eingabe der Dateien funktiniert es jetzt one
Probleme. Danke dafür. Ich muss jetzt aber wreiter nerven. Nun hab ich
das Problem, das er wieder den oben genannten Fehler "request for member
"PersonalNr" bei der Drehfunktion angibt.
1
voidsortierabfrage(void)
2
{
3
4
inta;
5
inth,j,i;
6
intDrehen;
7
charBuffer[121];
8
9
printf("\n\n\n\Sie haben die Moeglichkeit zwischen folgenden Sortiervarianten,\n die mit den dazugehoerigen Zahlen auszuwaehlen sind \n\n");
10
printf("(1) Fuer das Sortieren der Personalnummer aufsteigen \n");
11
printf("(2) Fuer das Sortieren nach Name, Vorname aufsteigend \n");
12
printf("(3) Fuer das Sortieren nach dem Buchungstag \n");
13
printf("(4) Fuer das Sortieren der Monatsarbeitszeit \n");
14
printf("(5) Fuer das Sortieren der Jahresarbeitszeit \n\n Bitte bestaetigen Sie Ihre Eingaben mit Enter\nEingabe:");
Florian P. schrieb:> Ich hatte nur 15 Vorlesungsstunden und dann die aufgabe bekommen. Das> alles in einem recht engen Zeitfenster, deswegen bin ich auch so> wissenslos.
???
Das ist ja fast ein Semester.
Hast du auch ein C Buch? Welches und hast du das auch ordentlich
durchgearbeitet?
Sorry aber an der Uni sollte man in der Lage sein und auch damit rechnen
sich was selbst beizubringen.
Florian P. schrieb:> Ich hatte nur 15 Vorlesungsstunden und dann die aufgabe bekommen. Das> alles in einem recht engen Zeitfenster, deswegen bin ich auch so> wissenslos.
Beeindruckt mich ehrlich gesagt überhaupt nicht.
Auf einer Uni oder einer FH wird vorausgesetzt, dass man sich selbst in
seiner Freizeit weiterbringt. Dazu gibt es Bücher, dazu muss man in
Eigenregie üben.
Gerade in einer Programmiersprachenvorlesung ist das dümmste was man tun
kann, sich in eine Vorlesung zu setzen und sich einfach nur berieseln
lassen. Programmieren lernen bedeutet in erster Linie: üben, üben, üben.
Und wenn man denkt, man beherrscht die Sache, dann werden noch mal 20
Übungsstunden draufgelegt um sich selbst zu kontrollieren, ob man die
Sache verstanden hat. Und dann gehts weiter zum nächsten Thema in der
Vorlesung und die ganze Überei beginnt wieder von vorne.
Sorry. So ist das nun mal. Das ist bei dir heute auch nicht anders als
bei uns vor 30 Jahren. Ok, einen kleinen UNterschied gibt es. Wir
mussten unsere Übungs-Programme noch auf dem Uni-Großrechner entwickeln
und hatten dazu genau 1 (in Worten: einen(!)) Compiler-Lauf pro Tag
(eigentlich: pro Nacht) und 14 Tage Zeit für jeweils 3 Übungsprogramme.
Junge hatten wir die Syntax schnell gelernt um nur ja nicht 3 oder 4
Compiler-Läufe (und damit 3 oder 4 Tage) wegen dummer Syntax-Fehler zu
verlieren.
Florian P. schrieb:> Ich hatte nur 15 Vorlesungsstunden und dann die aufgabe bekommen. Das> alles in einem recht engen Zeitfenster, deswegen bin ich auch so> wissenslos. Mit der Eingabe der Dateien funktiniert es jetzt one> Probleme. Danke dafür. Ich muss jetzt aber wreiter nerven. Nun hab ich> das Problem, das er wieder den oben genannten Fehler "request for member> "PersonalNr" bei der Drehfunktion angibt.
Na dann sieh dir die Zeile an, die dir der Compiler markiert und
korrigiere den Fehler.
> Ich wollte erstmal nur einen Block drehen lassen, damit es Schritt für> Schritt geht.
Das was du da hast ist zwar nicht ganz falsch, aber eigentlich
ziemlicher Unsinn.
Ich habe so viele Stunden in lesen und verstehen investiert und habe
Probleme. Hätte ich diese nicht, hätte ich mich nicht hier an euch
gewendet. Ich bin kein Programmierer und werde auch keiner. Ihr könnt
euch überlegen ob ihr mir weiter helft oder nicht. Die Ansätze waren
bisher super und ich bin darüber auch dankbar.
Karl Heinz Buchegger schrieb:> Das was du da hast ist zwar nicht ganz falsch, aber eigentlich> ziemlicher Unsinn.
Neben vielen anderen Dingen, lass uns mal das hier ansehen
1
strcpy(Buffer,Personal[i].PersonalNr[j-1]);
was ist Personal[i].PersonalNr[j-1]
Personal ist das komplette Array. Also alle Daten
Personal[i] ist ein einzelnes Array Element, also 1 struct person Objekt
Personal[i]. der Punkt besagt: Member davon nehmen. Da Personal[i] ein
struct person Objekt ist geht das auch.
Personal[i.PersonalNr aha, also der PersonalNr Member des struct person
Objektes. Was ist das wieder? Das ist ein char Array, also viele Zeichen
die einen String ergeben.
Personal[i].PersonalNr[j] ist daher ein einzelnes Zeichen, ein einzelner
char.
Und mit diesem einen char, willst du einen strcpy machen?
strcpy arbeitet auf Strings und nicht auf einzelnen Charactern!
Tut mir leid. Aber das (Arbeiten mit Strings) das sind Dinge, die müssen
zum jetzigen Zeitpunkt sitzen! Da darf es keinerlei Probleme mehr geben.
Ich weiß schon, dass String-Verarbeitung in C die erste große Hürde ist.
Aber über die müsstest du schon seit langem drüber sein!
Florian.p schrieb:> Ich habe so viele Stunden in lesen und verstehen investiert
Selber Programme schreiben!
Üben!
Üben!
Üben!
Selber Programme schreiben!
Üben!
Üben!
Üben!
Du kannst den Radfahrern bei der Tour de France stundenlang zusehen und
ihren Tritt beobachten und studieren. Davon wirst du als Nichtradfahrer
nicht plötzlich radfahren können!
Es gibt nur einen Weg um Schwimmen zu lernen. Ins Becken zu springen und
es selbst zu tun. Anderen zuzusehen und sich Dinge abschauen ist gut und
auch wichtig, keine Frage. Aber du musst selber ins Becken!
Und hier ist es genau das gleiche.
> gewendet. Ich bin kein Programmierer und werde auch keiner. Ihr könnt> euch überlegen ob ihr mir weiter helft oder nicht.
Die Frage, die sich mir stellt, lautet:
Wie sinnvoll ist es, dass du einen Abschluss in einem Fach bekommst,
welches du nicht mal ansatzweise kannst! Von beherrschen kann da noch
keine Rede sein. Wo endet die Hilfestellung und wo beginnt schlicht und
ergreifend der Betrug durch Vortäuschen einer selbst erbrachten
Leistung?
Eigentlich wurde dir schon alles erklärt was du jetzt noch brauchst!
Das die Kollegen soviel Geduld mit dir aufbringen ist schon sehr
erstaunlich!
OK, ich versuche dir auch ein bisschen uzu helfen:
1.) Sieh dir mal den Vergleich an! Was vergleichst du eigentlich? Welche
Indiezes musst du benutzen? Welche benutzt du?
2.) das Umkopieren der Felder wurde dir schon ganz weit oben erklärt. Du
kannst die ganze struct auf eimal umkopieren!!!!
Viel Spaß
Dirk