PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C] Strukturarray sortieren & ausgeben


Gast
2006-02-04, 00:11:40
Ich sitze grade an einem Problem bei C.
Ich hab mir ein Struktur-Array erzeugt, kann dieses mit Daten füllen und will es dann unsortiert und sortiert in eine Datei schreiben.
Dafür hab ich die Funktion "file_write", der ich das Array übergeben kann.
Es funktioniert auch beim unsortierten Array.
Aber wenn ich das Array durch die Funktion "sortiere" schieße, bleibt die Datei leer. Weiß hier vielleicht jemand was ich falsch gemacht haben könnte?
Und vielleicht weiß auch jemand, wie ich in der main-Funktion vek[i].name mit einer leeren Zeichenkette füllen kann.
Besten Dank schonmal fürs schauen!
Anbei das Listing:

#include <stdio.h>
#include <string.h>

struct daten{
long mitnr; //zwischen 1000 und 50000
char name[30];
int anstell; //zwischen 1998 und 2050
};

int trigger=0; //Pseudo-Bool zum Abbruch bei Eingabe mitnr=0
int anz=0; //Anzahl der real gefuellten Struktur-Vektor-Elemente

int eingabe(struct daten neu[], int i)
{
int an;
long mit;

printf("\nMitarbeiternummer:");
scanf("%d",&mit);


if(mit != 0)
{
if(mit>=1000 && mit<=50000)
{
neu[i].mitnr=mit;

printf("Name:");
fflush(stdin);
fgets(neu[i].name,30,stdin);

printf("Anstellungsjahr:");
scanf("%d",&an);
if(an>=1998 && an <=2050)
neu[i].anstell=an;
else
printf("\nFalscher Datenbereich");
}
else
printf("\nFalscher Datenbereich");
}
else
{
anz=i; //Wert bis wohin der Vektor in Datei geschrieben werden soll
trigger=1; //Bool-Wert um RestVektor mit 0 zu füllen
}
}

void file_write(struct daten dat[], char *str)
{
FILE *fp;
int i;

fp=fopen(str,"w+b");
if(fp == NULL)
printf("Datei konnte nicht erstellt werden");
else
{
for(i=0;i<anz;i++)
{
fprintf(fp , "%ld %s \t %d\n" , dat[i].mitnr,dat[i].name,dat[i].anstell);
}
}
}

void sortiere(struct daten sort[])
{
int i;
FILE *fp;
struct daten *temp;

temp=(struct daten *)malloc(sizeof(struct daten *));
if(temp == NULL)
{
printf("Kein Speicher reservierbar\n");
return;
}
else
{
//Bubble-Sort
while(anz--)
{
for(i=1; i<=anz; i++)
{
if(sort[i-1].mitnr > sort[i].mitnr)//linkes Element > rechtes Element
{
*temp=sort[i]; //rechtes Element sichern
sort[i]=sort[i-1]; //tausche Elemente
sort[i-1]=*temp; //rechts Element auf linkes setzen
}
}
}
}
file_write(sort,"sort.txt"); //Sortierten Struktur-Vektor ausgeben
}

void main()
{
struct daten vek[40];
int i;

for(i=0; i<40;i++)
{
if(trigger != 1) //solange mitnr!=0 normale Dateneingabe
eingabe(vek,i);
else
{
//printf("Vektor %d wird mit 0 initialisiert\n",i);
vek[i].anstell=0;
vek[i].mitnr=0;
//vek[i].name='\0';
}
}
file_write(vek,"unsort.txt");
sortiere(vek);
}

Trap
2006-02-04, 00:15:08
while(anz--) ist keine gute Idee...

Warum benutzt du nicht einfach qsort()?

Gast
2006-02-04, 00:28:50
while(anz--) ist keine gute Idee...
Warum? Damit gewährleiste ich, dass sauber getauscht wird. Habs bei einem normalen int-Vektor schonmal getestet und läuft einwandfrei

Warum benutzt du nicht einfach qsort()?
Ich wollte es gern selbst implementieren, mir gehts eher ums algorithmische Verständnis. Vorgefertigte Algorithmen kann (und werde) ich sicherlich noch häufig genug nutzen :)

Trap
2006-02-04, 00:36:27
Ok, nach ein Holzhammer-Hinweis:

Was macht anz--?
Was bedeutet anz in deinem Programm?
Welche Funktionen hängen davon ab, dass in anz ein bestimmter Wert steht?

Gast
2006-02-04, 01:03:05
Ok, hat sich erledigt.
Wollte grad noch posten wozu (anz--) gut ist, da wurde mir plötzlich die Unsinnigkeit dieser Operation klar und ich habe eine neue Variable dafür definiert. Jetzt funktioniert die Sortierung. Ist manchmal gut, dass jemand anderem zu erklären :)

anz ist übrigens nur dazu da, sich zu merken wie weit in den Vektor geschrieben wurde, damit keine leeren Datenfelder in die Dateien geschrieben werden.

Eine Sache hätte ich noch:
vek[i].name='\0'; -> das mag der Compiler nicht, hab auch Varianten wie ="" oder =' ' probiert.

Trap
2006-02-04, 01:08:01
Hab ewig keine string-sachen mit char[] mehr gemacht, vek[i].name[0]=0; müsste aber gehen.

GloomY
2006-02-04, 18:00:29
Hab ewig keine string-sachen mit char[] mehr gemacht, vek[i].name[0]=0; müsste aber gehen.Entweder das oder:vek[i]->name = '\0';

Neomi
2006-02-04, 18:10:48
Mal ein paar Anmerkungen zu deiner Sortierungs-Funktion...

1. Du allokierst Speicher für eine temporäre Variable, der nicht mehr freigegeben wird. Das ist ein Speicherleck.

2. Du allokierst nur genug Platz, um einen Pointer zu speichern, nicht für die ganze Struktur. Statt sizeof (struct daten *) solltest du sizeof (struct daten) verwenden. In der jetzigen Form schreibst du bei der Zuweisung in Speicherbereiche, die nicht dafür vorgesehen sind, sowas kann böse enden.

3. Da du eh nur eine einzelne Temp-Variable brauchst, solltest du die gleich auf dem Stack anlegen und die Sache mit dem Pointer sein lassen. Ein simples struct daten temp; ist da wesentlich besser.

4. Da du die Variable anz beim Schreiben der Daten noch brauchst, solltest du sie nicht vorher schon bis -1 runterzählen. Da ist klar, daß nichts mehr geschrieben werden kann. Versuche es stattdessen mit int anz2 = anz; und while (anz2--) lokal in der Funktion. Damit wäre immerhin die Anzahl gerettet und würde die Sortierung überstehen.

Edit: hab übersehen, daß 4. schon längst erledigt ist.

Neomi
2006-02-04, 18:17:14
Entweder das oder:vek[i]->name = '\0';

Nein, da der Pointer "vek" schon über den []-Operator dereferenziert wird. Da bleibt nur:

vek [i].name [0] = '\0';

oder:

*(vek [i].name) = '\0';

Xmas
2006-02-04, 19:54:18
Nein, da der Pointer "vek" schon über den []-Operator dereferenziert wird.
Dazu kommt dass name als Array deklariert ist, man aber nur Arrayelementen etwas zuweisen kann.

Gast
2006-02-04, 23:17:25
Mal ein paar Anmerkungen zu deiner Sortierungs-Funktion...

1. Du allokierst Speicher für eine temporäre Variable, der nicht mehr freigegeben wird. Das ist ein Speicherleck.

2. Du allokierst nur genug Platz, um einen Pointer zu speichern, nicht für die ganze Struktur. Statt sizeof (struct daten *) solltest du sizeof (struct daten) verwenden. In der jetzigen Form schreibst du bei der Zuweisung in Speicherbereiche, die nicht dafür vorgesehen sind, sowas kann böse enden.

3. Da du eh nur eine einzelne Temp-Variable brauchst, solltest du die gleich auf dem Stack anlegen und die Sache mit dem Pointer sein lassen. Ein simples struct daten temp; ist da wesentlich besser.

Vielen Dank für die Hinweise, ich habe sie beherzigt. Es stimmt, bisher behandle ich dynamischen Speicher etwas stiefmütterlich. In C++ ist das dank des Destruktors auch wesentlich angenehmer :D.

Vielen Dank auch an alle anderen, die sich über meine Probleme den Kopf zerbrochen haben - da kann ich nur sagen: super Community!