Kleines Problem mit FILE Pointern



  • wird durch das ++i der Index auch schon hochgezählt? ja oder?
    Danke für den Code 😃



  • mazeli schrieb:

    wird durch das ++i der Index auch schon hochgezählt? ja oder?

    Geneauso ist es.



  • hmm also das programm scheint so nicht zu funktionieren, zumindest gibt er mir nur die erste zahl richtig aus und dann nur noch irgendwelche werte



  • meine Variante:

    #include <stdio.h> 
    #include <stdlib.h> 
    
    #define pfad "D:\\Studium\\Informatik 2\\Labor\\Aufgabe 3.1\\qsort.txt"
    int main() 
    { 
        FILE* fp;   
        int tmp, temp;
        int* array;     
    
        if ((fp = fopen(pfad,"r+b")) == NULL) 
            return EXIT_FAILURE; 
        for (tmp = 0; fscanf(fp, "%d", &temp) != EOF; tmp++); 
        fclose(fp);
    
        array = (int*) malloc(tmp*sizeof(int));
    
        if ((fp = fopen(pfad,"r+b")) == NULL) 
            return EXIT_FAILURE; 
        for (tmp = 0; fscanf(fp, "%d", &array[tmp]) != EOF; tmp++) 
            printf("Wert: %d\n", array[tmp]); 
    
        fclose(fp);
        free(array); 
        array = NULL; 
        return EXIT_SUCCESS; 
    }
    

    🕶



  • Joar Danke, die tut 😃

    aber möchte gern wissen was bei der obigen der Fehler ist



  • habs debuggt und korrigiert - jetzt läufts

    #include <stdio.h> 
    #include <stdlib.h> 
    
    int main(void) 
    { 
        FILE *fp = NULL; 
        int *array = NULL, i = 1, j = 0; 
        if((fp = fopen("D:\\Studium\\Informatik 2\\Labor\\Aufgabe 3.1\\qsort.txt","r+b")) == NULL) 
            return EXIT_FAILURE; 
        do 
        { 
            if(array == NULL) 
            { 
                if((array = (int *)malloc(sizeof(int))) == NULL) 
                    return EXIT_FAILURE; 
            } 
            else 
            { 
                if((array = (int *)realloc(array, ++i * sizeof(int))) == NULL) 
                    return EXIT_FAILURE; 
            } 
        } 
        while((fscanf(fp, "%d", &array[i-1])) != EOF); 
        fclose(fp); 
        fp = NULL; 
        for(j = 0; j < i-1; j++) 
            printf("Wert: %d\n", array[j]); 
        free(array); 
        array = NULL; 
        return EXIT_SUCCESS; 
    }
    

    🕶 🕶



  • Vielen Dank euch allen für die Hilfe

    hier der fertige Code mit Qsort.

    #include <stdio.h>
    #include <stdlib.h>
    #include "compare.h"
    
    int main(void)
    {
    	FILE *fp = NULL;
    	int anz = 0, i = 1, y = 0;
    	int *arr = NULL;
    	if((fp = fopen("D:\\Studium\\Informatik 2\\Labor\\Aufgabe 3.1\\qsort.txt","r+b")) == NULL)
    		return EXIT_FAILURE;
    
    	do
    	{
    		if(arr == NULL)
    		{
    			if((arr = (int *)malloc(sizeof(int))) == NULL)
    			return EXIT_FAILURE;
    		}
    		else
    		{
    			if((arr = (int *)realloc(arr, ++i * sizeof(int))) == NULL)
    				return EXIT_FAILURE;
    		}
    	}while((fscanf(fp, "%d", &arr[i - 1])) != EOF);
    	fclose(fp);
    	fp = NULL;
    	printf("\nEingelesene unsortierte Werte: \n\n");
    	for(y = 0; y < i-1; y++)
    		printf("%d ", arr[y]);
    
    	printf("\n\nEingelesene sortierte Werte: \n\n");
    
    	qsort(arr, i-1, sizeof(int), compare_int);
    
    	for(y = 0; y < i-1; y++)
    		printf("%d ", arr[y]);
    
    	free(arr);
    	return EXIT_SUCCESS;
    }
    
    #include "compare.h"
    
    int compare_int(const void *ptr1, const void *ptr2)
    {
    	int ret, z1, z2;
    
    	z1 = *(int *) ptr1;	/* Cast auf Integer */
    	z2 = *(int *) ptr2;
    
    	if (z1 < z2)
    		ret = -1;
    	else if(z1 == z2)
    		ret = 0;
    	else
    		ret = 1;
    	return ret;
    }
    
    extern int compare_int(const void *, const void *);
    


  • Den Returnwert in der Vergleichsfunktion kannst du im Falle von Integern auch etwas kürzer schreiben:

    return (z1 - z2);
    

    Damit sparst du dir die Vergleiche. Für den allgemeineren Fall (z.B. Strukturen sortieren) gilt das natürlich nicht.



  • joar stimmt, aber in der Aufgabe war es so vorgegeben.

    Naja hab jetzt grad en anderes problem.

    Wollte das selbe Programm jetzt mit nem Modul erweitern welches ein dynamisch erzeugtes INT Array mit zufallswerten füllt und sortieren lässt (Modul ist vorhanden un funktioniert)

    jetzt wollte ich natürlich mein altes Programm nicht löschen und deshalb die alte Funktion mit der Datei in ein extra Modul packen, so als übung nebenbei. Natürlich klappt es nicht 😃

    in der Funktion create_file kann ich das eingelesene Array ausgeben, aber in der main selbst stürtzt er beim printf ab.

    Denke mal das ich was mit den Arrays/Pointer was falschgemacht habe.
    Habe das Thema Pointer wohl immer noch net richtig im Griff...

    achso noch ne kleine Frage: Ich suche ein schönes Buch zum Thema c / c++, so ne art referenz wo alle funktionen schön beschrieben sind, und natürlich wo auch noch normale Erklärungen hat, halt ein gutes Buch zum Nachschlagen aber auch neue Themen lernen.

    Bissle Farbe sollte auch vorhanden sein, einfach nur schwarzweiß text ist bei mir irgendwie wirkungslos 😃

    Könnt ihr da was empfehlen?

    bzw hier mal der Code:

    Inhalt der main.c:

    #include <stdio.h>
    #include <stdlib.h>
    #include "compare.h"
    #include "file.h"
    #include "array.h"
    
    int main(void)
    {
    
    	int anz = 0, i = 0, y = 0;
    	int *arrr = NULL;
    
    	i = create_file(&arrr);
    
    	printf("\nEingelesene unsortierte Werte: \n\n");
    	for(y = 0; y < i-1; y++)
    		printf("%d ", arrr[y]);
    
    	printf("\n\nEingelesene sortierte Werte: \n\n");
    
    	qsort(arrr, i-1, sizeof(int), compare_int);
    
    	for(y = 0; y < i-1; y++)
    		printf("%d ", arrr[y]);
    
    	//free(arrr);
    	return EXIT_SUCCESS;
    }
    

    Inhalt der file.c

    #include "file.h"
    #include <stdlib.h>
    #include <stdio.h>
    
    int create_file(int *Aptr)
    {
    	int *arr = NULL; //(int *) calloc(sizeof(int), max);
    	int *tmp = arr;
    	int i = 0, y = 0;
    	FILE *fp = NULL;
    
    	if((fp = fopen("D:\\Studium\\Informatik 2\\Labor\\Aufgabe 3.1\\qsort.txt","r+b")) == NULL)
    		return EXIT_FAILURE;
    
    	do
    	{
    		if(arr == NULL)
    		{
    			if((arr = (int *)malloc(sizeof(int))) == NULL)
    				return EXIT_FAILURE;
    		}
    		else
    		{
    			if((arr = (int *)realloc(arr, ++i * sizeof(int))) == NULL)
    				return EXIT_FAILURE;
    		}
    	}while((fscanf(fp, "%d", &arr[i - 1])) != EOF);
    
    	/*printf("\nEingelesene unsortierte Werte: \n\n");
    	for(y = 0; y < i-1; y++)
    		printf("%d ", arr[y]);*/
    	*Aptr = tmp;
    
    	fclose(fp);
    	fp = NULL;
    
    	return i;
    
    }
    

    Inhalt der file.h

    int create_file(int *);
    

    inhalt der compare.c

    #include "compare.h"
    
    int compare_int(const void *ptr1, const void *ptr2)
    {
    	int ret, z1, z2;
    
    	z1 = *(int *) ptr1;	/* Cast auf Integer */
    	z2 = *(int *) ptr2;
    
    	if (z1 < z2)
    		ret = -1;
    	else if(z1 == z2)
    		ret = 0;
    	else
    		ret = 1;
    	return ret;
    }
    

    compare.h

    extern int compare_int(const void *, const void *);
    

    Also er stürzt beim ersten printf in der main ab.

    Nehme an weil im Array nix steht.



  • Ja, C übergibt Parameter als Kopie, das heißt eine Zuweisung in der Funktion wirkt sich nicht auf das Hauptprogramm aus. Da brauchst du schon Zeiger auf Zeiger:

    int create(int** Aptr)
    {
      int* tmp=NULL;
      ...
      *Aptr = tmp;
    }
    
    ...
    int* array;
    create(&array);
    

    (ein weiterer Fehler: Du arbeitest in der Funktion die ganze Zeit mit arr und gibst am Ende tmp zurück - der steht aber nach der ersten Zuweisung weiterhin auf NULL)

    PS: Übrigens kann realloc() auch einen NULL-Zeiger übergeben bekommen, also ist die Fallunterscheidung "if(arr==NULL)" unnötig.



  • hmm klingt schon logisch,

    aber wieso funktioniert das dann hier?

    array.c

    #include <stdlib.h>
    #include <stdio.h>
    #include "array.h"
    #include <time.h>
    
    void scanArray(unsigned int max, int *Aptr, int *anz)
    {
    	int i = 0;
    	int *tmp_arr = (int *) calloc(sizeof(int), max);
    	int *tmp = tmp_arr;
    
    	printf("\nBitte Werte eingeben: ");
    
    	while(i < max)
    	{
    		*anz = scanf("%i", tmp_arr);
    
    		if(*anz != 1)
    			break;
    		if(*anz >= max)
    			break;
    		i++;
    		(*anz)++;
    		tmp_arr++;
    	}
    	*Aptr = tmp;
    	free(tmp_arr);
    }
    
    void fillArray(unsigned int max, int *Aptr, int *anz)
    {
    	int *tmp_arr = (int *) calloc(sizeof(int), max);
    	int *tmp;
    	int i = 0;
    
    	tmp = tmp_arr;
    
    	srand(time(NULL));
    
    	*anz = rand()%max;
    
    	for(i = 0; i < *anz; i++)
    	{
    		tmp_arr[i] = rand()%max;
    	}
    	*Aptr = tmp;
    }
    
    void printArray(unsigned int max, int *Aptr, int *anz)
    {
    	int z = 0;
    
    	printf("\nEingelesene Werte: \n\n");
    
    	for(z = 0; z < max; z++)
    	{
    		if(z % 8 == 0)
    			printf("\n");
    		printf("%6i", Aptr[z]);
    	}
    
    }
    

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "array.h"
    #include "average.h"
    
    #define MAX 10
    
    int main(void)
    {
    	int *arr;
    	int n = 0;
    	double x = 0;
    
    	//scanArray(MAX, &arr, &n);
    	fillArray(MAX, &arr, &n);
    	printArray(MAX, arr, &n);
    	//x = average(MAX, arr, &n);
    	//printf("\n\nMittelwert: %lf", x);
    	return EXIT_SUCCESS;
    }
    

    hier übergebe ich ja auch eine Kopie an die Funktion, kann aber dann in einer anderen funktion das array mit dem Inhalt ausgeben

    gnaa das zeigt mir eindeutig das ich Zeiger immer noch nicht verstanden habe 😞



  • Hast du jetzt nur beim Abtippen einen Stern vergessen oder übergibst du wirklich einen int** (&arr) als int* (APtr)? Wenn ja, sollte dich eigentlich dein Compiler darauf aufmerksam machen.

    Ansonsten beachte mal die Reihenfolge der Zuweisungen:

    tmp = arr;
    arr = malloc(...);
    ...
    *Aptr = tmp;
    
    //vs
    
    arr = malloc(...);
    tmp = arr;
    ...
    *Aptr = tmp;
    

    (wobei die Variable tmp sowieso überflüssig ist - da du innerhalb der Funktion mit 'arr' arbeitest, reicht auch ein "*Aptr = arr;" am Ende aus)



  • ne hab nix vergessen, ist genauso wie es dort steht...und funktioniert ja auch



  • OK, dann langsam: Du hast im Hauptprogramm einen int* namens arr und übergibst deiner Funktion dessen Adresse (das wäre ein int**). Die Funktion nimmt jedoch ein int* (und rechnet dann seltsamerweise damit so, als ob es ein int** wäre) - da hängt es dann von deinem Glück und dem Compiler ab, ob das funktioniert.



  • hmm ich raff das net mit pointern, ich übergeben die Adresse meines Array oder?
    wenn ich jetzt nur (arr) und nicht (&arr) übergeben hätte, dann würde ich ja einen Pointer auf das erste Element übergeben oder?

    Hmm also das Programm an sich ist falsch aber funktioniert seltsamerweiße?

    ps: Kannst en gutes C Buch empfehlen?



  • Du verwendest einen int*, um damit ein dynamisches Array anzulegen und zu verwalten (ja, das ist ein Zeiger auf das erste Element). Und da du den Zeiger in deinem Hauptprogramm verändern willst, mußt du ihn als "Referenz" übergeben - deshalb brauchst du einen "Pointer auf int*" (=int**).



  • hmm und in meinem Code lege ich sozusagen nur ne Kopie an und übergebe dieser die Adresse meines Arrays, demnach dürfte es gar nicht funktionieren...hmm


Anmelden zum Antworten