Elemente in Pointer zu Array verändern



  • Hallo,

    ich mache seit diesem Semester ne C++-Vorlesung und hab daher noch nicht wirklich viel Ahnung... Nun haben wir die Aufgabe bekommen, ein bild zu invertieren, in vier verschiedenen Arten, das Bild an die Funktion zu übergeben: als Vektor, Pointer zum Vektor, Referenz zum Vektor, Array.
    Das mit dem normalen Vektor klappt schon, bloß mit den Pointer nicht.
    Ich kann weder die Elemente bearbeiten, noch in eine Datei schreiben.
    Dabei bekomme ich die Fehler:
    Zeile 24: error: no match for 'operator-' in '255 - * *(image2 + ((unsigned int)(nI * 4u)))'
    Zeile 25: error: no matching function for call to 'std::basic_ofstream<char>::put(std::vector<char>&)'

    und wenn ich die Funktion aufrufe auch noch:
    Zeile 55: error: cannot convert 'std::vector<char>' to 'std::vector<char>' for argument '1' to 'void img2(std::vector<char>, char*, unsigned int)'

    Hier der Code:

    #include <fstream>
    #include <string.h>
    #include <vector>
    #include <iostream>
    #include <stdio.h>
    
    using namespace std;
    
    vector<char> img1(vector<char> image2)
    	{
    		for (unsigned int nI = 54; nI < image2.size(); nI++)
    		{
    			image2.at(nI) = 255 - image2.at(nI);
    		}
    		return image2;
    	};
    
    void img2(vector<char> *image2, char *sFile, unsigned int iSize)
    	{
    				ofstream Inv;
    				Inv.open(sFile, std::ios::out | std::ios::binary);
    				for (unsigned int nI = 0; nI < image2.size(); nI++)
    				{
    					*image2[nI] = 255 - *image2[nI];
    					Inv.put(*image2[nI]);
    				}
    	};
    
    int main(int argc, char ** argv) {
    
    	ifstream image3;
    	image3.open(argv[1], std::ios::in | std::ios::binary);
    	vector<char> vImg;
    	image3.seekg (0, ios::end);
    	int length = image3.tellg();
    	image3.seekg (0, ios::beg);
    	for (int nI = 0; nI < length; nI++)
    	{
    		vImg.push_back(image3.get());
    	}
    if (strcmp(argv[3], "using_vector") == 0)
    {
    vImg = img1(vImg);
    ofstream Inv;
    Inv.open(argv[2], std::ios::out | std::ios::binary);
    for (unsigned int nI = 0; nI < vImg.size(); nI++)
    {
    	Inv.put(vImg.at(nI));
    }
    }
    
    if (strcmp(argv[3], "using_pointer") == 0)
    	{
    		vector<char> *vImgP = &vImg;
    		img2(*vImgP, argv[2], vImg.size());
    	};
    return 0;
    }
    

    Jemand ne Ahnung was ich da falsch mache? Hab echt schon ewig gesucht, alles mögliche probiert und finde den Fehler einfach nicht...
    Die anzahl der Elemente kann ich auch nich über den Pointer erkennen, oder? Bisher klappt das nur, wenn ich die Anzahl mit .size() vom array nehme und mit in die funktion übergebe...

    Vielen Dank



  • Die Operatorpriorität verhält sich anders als von dir erwartet. Schreib

    (*image2)[nI]
    

    oder verwende gleich Referenzen als Parameter:

    vector<char>& image2
    

    Übrigens: Ersetze die C-Header <string.h> und <stdio.h> durch deren C++-Äquivalente <cstring> und <cstdio> , dann sind die Bezeichner auch im Namensraum std .



  • Das Problem ist, dass die hier einen vector mit ins Spiel bringst, obwohl du nur einen Zeiger haben willst. Mach aus den vector<char> * nur einen char* und das sollte soweit erstmal klappen. In den beiden oberen Zeilen solltest du dir auch noch mal ansehen, wie man über einen Zeiger auf die Elemente zugreifen kann. Vielleicht ist es hilfreich sich dazu einmal C-Felder anzusehen, wie diese benutzt werden.
    Was mir aber unschön in deinem Code aufgefallen ist, dass du einmal die Daten in der Funktion in die Datei schreibst und einmal außerhalb. Mach das völlig unabhängig von der Auswahl, ob Zeiger oder vector und du musst den Code nur einmal schreiben. Und du du solltest auch eine rudimentäre Fehlerbehandlung mit rein machen. Schauen, ob die Datei geöffnet werden konnte und ob überhaupt genügend Argumente an die Anwendung übergeben wurden.



  • Vielen Dank, so klappt das schonmal mit den Elementen, hab da echt nix zu gefunden wie man darauf zugreift...
    Aber wo soll ich vector<char>* durch char* ersetzen? Die Aufgabe ist ja, dass ich nen Zeiger zum Vektor benutzen soll... Durch das ersetzen bekomme ich nur noch mehr Fehler... Der letzte Fehler bei dem funktionsaufruf ist immernoch da, wieso geht das da so nicht?

    Die Fehlerüberprüfung usw wollte ich am Ende machen, wenn erstmal alles läuft...
    Und dazu dass ich einmal in der Funktion und einmal ausserhalb der Funktion geschrieben wird... Irgendwie steht das so iner Aufgabe, bin dadurch auch verwirrt 😕

    The four functions differ only in the way, the image is passed to them. Use
    the following different ways of passing the image:
     Pass the image as std::vector<char> to the function, invert it and return it back to the main.
     Pass the image as reference of std::vector<char> to the function and invert it.
     Pass the image as pointer to std::vector<char> to the function and invert it.
     Pass the image as character array to the function and invert it.

    Beim ersten soll ich das ane main zurück geben, bei den anderen nicht und die unterscheiden sich trotzdem nur in der Parameterübergabe 😕



  • Ah okay!
    Der erste Fall dürfte soweit stimmen. Zum zweiten Fall, schaust du dir den Alternativvorschlag von Nexus mal an und für den dritten seine erste Lösung. Der letzte Fall bezieht sich dann auf die von mir genannte Zeiger auf char Lösung. Die Größe benötigst du nur bei der letzten Version, bei den drei anderen wird sie über das vector-Objekt mit übergeben.

    Die Fehlerüberprüfung usw wollte ich am Ende machen, wenn erstmal alles läuft...

    Nachlässigkeit ist der Anfang vom Ende. Gewöhne dir lieber an gleich die Fehlerbehandlung zu machen, wenn du Pech hast musst du sonst deinen Code nochmal überdenken. Und wenn er eigentlich läuft ist das extrem blöd. Das gleiche gilt für Kommentare, immer sofort schreiben, wenn du noch genau weißt was du dort getrieben hast.



  • ok, stimmt schon, nächstes mal mach ich das gleich dabei...

    jetzt hab ich erstmal die sachen ausprobiert, compiliert er auch, aber läuft nicht. (Image.exe funktioniert nicht mehr-Meldung)
    Bei der Methode mit Pointer und chat stürzt reagiert das Programm nicht und bei der Referenz-Methode kommt nicht das invertierte Bild 😕

    Sieht da jemand vll den Fehler? Ich verste nicht wirklich, wieso der das nicht so macht....

    /*
     * image.cpp
     *
     *  Created on: 25.11.2010
     *      Author: Björn
     */
    #include <fstream>
    #include <string.h>
    #include <vector>
    #include <iostream>
    #include <stdio.h>
    
    using namespace std;
    
    vector<char> img1(vector<char> image2)
    	{
    		for (unsigned int nI = 54; nI < image2.size(); nI++)
    		{
    			image2.at(nI) = 255 - image2.at(nI);
    		}
    		return image2;
    	};
    
    void img2(vector<char> *image2, char *sFile)
    	{
    				ofstream Inv;
    				Inv.open(sFile, std::ios::out | std::ios::binary);
    				for (unsigned int nI = 54; nI < (*image2).size(); nI++)
    				{
    					(*image2)[nI] = 255 - (*image2)[nI];
    					Inv.put((*image2)[nI]);
    				}
    				Inv.close();
    	};
    
    void img3(vector<char> &image2, char *sFile)
    	{
    		ofstream Inv;
    		Inv.open(sFile, std::ios::out | std::ios::binary);
    		for (unsigned int nI = 54; nI < image2.size(); nI++)
    		{
    			image2[nI] = 255 - image2[nI];
    			Inv.put(image2[nI]);
    		}
    		Inv.close();
    	}
    
    void img4(char image2[], char *sFile, int length)
    	{
    		ofstream Inv;
    		Inv.open(sFile, std::ios::out | std::ios::binary);
    		for (int nI = 54; nI < length; nI++)
    				{
    					image2[nI] = 255 - image2[nI];
    					Inv.put(image2[nI]);
    				}
    		Inv.close();
    	}
    
    /* 	vector img3(sIn, sOut)
    	{
    
    	};
    
    	vector img4(sIn, sOut)
    	{
    
    	};
    */
    int main(int argc, char ** argv) {
    
    	ifstream image3;
    	image3.open(argv[1], std::ios::in | std::ios::binary);
    	vector<char> vImg;
    	image3.seekg (0, ios::end);
    	int length = image3.tellg();
    	image3.seekg (0, ios::beg);
    	for (int nI = 0; nI < length; nI++)
    	{
    		vImg.push_back(image3.get());
    	}
    	image3.close();
    if (strcmp(argv[3], "using_vector") == 0)
    {
    vImg = img1(vImg);
    ofstream Inv;
    Inv.open(argv[2], std::ios::out | std::ios::binary);
    for (unsigned int nI = 0; nI < vImg.size(); nI++)
    {
    	Inv.put(vImg.at(nI));
    }
    Inv.close();
    }
    
    if (strcmp(argv[3], "using_pointer") == 0)
    	{
    		vector<char> *vImgP = NULL;
    		*vImgP = vImg;
    		img2(vImgP, argv[2]);
    	};
    
    if (strcmp(argv[3], "using_reference") == 0)
    	{
    		img3(vImg, argv[2]);
    	}
    
    if (strcmp(argv[3], "using_char") == 0)
    	{
    		char cImg[length];
    		for (int nI = 0; nI < length; nI++)
    			{
    				cImg[nI] = vImg[nI];
    			}
    		img4(cImg, argv[2], length);
    	}
    /*		if (sChoice == 'reference')
    				{
    
    				};
    		if (sChoice == 'pointer')
    				{
    
    				};
    		if (sChoice == 'character')
    				{
    
    				};
    */
    return 0;
    }
    


  • In Zeile 98 weist du Zeiger das Objekt und nicht die Objektadresse zu. Eigentlich müsste der Compiler an der Stelle meckern.
    In Zeile 109 legst du ein Feld auf dem Stack an. Wenn dieses zu groß wird, was bei einem Bild leicht der Fall sein kann, machst du dir deinen Stack kaputt und den daneben liegenden Speicher. Lege das Array einfach mit new an, damit umgehst du dieses Problem.
    Andere Fehler/Probleme kann ich auf Anhieb nicht sehen, außer dass deine Einrückung ihrem Namen nicht gerecht wird.



  • Ahh, ok, jetzt weiß ich wofür new gut ist 😃
    Das klappt so, Bild ist zwar nicht anzeigbar, aber das liegt daran, dass ich erst ab 54 zähl, den Header also nicht veränder, aber die neue Datei auch ohne header schreibe 🙄
    Das änder ich mal wenn das andere klappt

    Zu dem Pointer:
    Müsste Zeile 93 dann so lauten?

    *vImgP = &vImg;
    

    Dann meckert der Compiler aber...



  • Björn87 schrieb:

    *vImgP = &vImg;
    

    Dann meckert der Compiler aber...

    Ja, was sagt er denn?

    Der Stern dient nur in der Deklaration dazu zu zeigen, dass es sich um einen Zeiger handelt. Später dereferenzierst du damit das Objekt an der hinterlegten Adresse.

    vector<char> *vImgP = NULL;  // Zeiger auf Anfangswert NULL setzen, ist richtig
    *vImgP = vImg;               // hier derefernzierst du NULL und kopierst das Objekt vImg auf das Objekt an Adresse NULL
    

    Krachen dürfte es schon bei der Dereferenzierung.

    vector<char> *vImgP = NULL;
    vImgP = &vImg;
    


  • Ok, hab ich auch grad probiert, so gehts jetzt

    Ziemlich kompliziert mit den Pointern und so, wenn man das noch nie gemacht hat...

    Dann nur noch die Headersache, Fehlerüberprüfung und kommentieren
    Das mit dem Einrücken kommt von Copy6Paste bei Eclipse, muss ich wohl auch nochmal richtig machen 😉

    Vielen Dank für die Hilfe, so langsam fang ich an das zu verstehn 😉



  • Einrücken in Eclipse: Textblock markieren, Strg + i


Log in to reply