Unsichtbarer Fehler
-
...und verwende kein "using ...;" im globalen Namensraum eines Headers.
-
Kleiner Tipp: Du könntest die
ReadInt,ReadDoubleundReadStringMethoden kürzer schreiben, wenn du einfach die entsprechenden Funktionen aus dem<cctype>-Header verwenden würdest.
http://www.cplusplus.com/reference/clibrary/cctype/
-
Danke für eure Lösungen und Hilfen. Hab jetzt auch <cctype> verwendet, sehr nützlich :). Aber es erkennt die Funktionen find, length und substr nicht. Die Fehlermeldung ist (für mich zumindest
) kurios. Ich würde mal tippen er hat wieder irgendwelche Probleme mit dem namespace oder meiner Dateiausleseklasse. Aber ich werde nicht schlau, wo genau er die Funktionen sucht und wo sie zu finden sein sollten. Also hier nochmal nur die gekürzte "ConfigLaden.cpp":#include <string> #include <fstream> #include <iostream> #include <cctype> #include "ConfigLaden.h" //using namespace std; ConfigLoad::ConfigLoad(char* file) { Puffer = new char[1000]; //Datei öffnen pKonfiguration = new std::ifstream (file); //Fehlerkontrolle if (!pKonfiguration -> good()) { delete pKonfiguration; std::cout << " konnte nicht geöffnet werden."; } } void ConfigLoad::ReadNextLine() { if (!pKonfiguration -> eof()) { pKonfiguration -> getline(Puffer, 1000); } } bool ConfigLoad::FoundString(char* search) const { bool found = false; size_t position = 1000; //Suchen position = Puffer.find(search); if (position != 1000) { found = true; } return found; } size_t ConfigLoad::StringPos(char* search) const { size_t found = 0; //Suchen found = Puffer.find(search); found += search.length(); return found; } int ConfigLoad::ReadInt(size_t nPosition) const { int Integer = 0; char* ZwischenPuffer = new char[1000]; char* IntPuffer = new char[1000]; bool Zahl = false; //ZwischenPuffer füllen ZwischenPuffer = Puffer.substr (nPosition); //Ab dem ersten nicht-Zahlzeichen abschneiden for (size_t i = 0; i < ZwischenPuffer.length(); i++) { Zahl = false; if(isdigit(ZwischenPuffer[i])) { Zahl = true; } //Wenn Zahl zu Ende, zusammenkopieren if(!Zahl) { IntPuffer = ZwischenPuffer.substr (0, (i - 1)); i = ZwischenPuffer.length(); //Schleife beenden } } //In int umwandeln Integer = atoi(IntPuffer); return Integer; } double ConfigLoad::ReadDouble(size_t nPosition) const { double Double = 0.0; char* ZwischenPuffer = new char[1000]; char* DoublePuffer = new char[1000]; bool Zahl = false; //ZwischenPuffer füllen ZwischenPuffer = Puffer.substr (nPosition); //Ab dem ersten nicht-Zahlzeichen abschneiden for (size_t i = 0; i < ZwischenPuffer.length(); i++) { Zahl = false; if (isdigit(ZwischenPuffer[i])) { Zahl = true; } if (ZwischenPuffer[i] == ".") { Zahl = true; } //Wenn Zahl zu Ende, zusammenkopieren if(!Zahl) { DoublePuffer = ZwischenPuffer.substr (0, (i - 1)); i = ZwischenPuffer.length(); //Schleife beenden } } //In int umwandeln Double = atof(DoublePuffer); return Double; } char* ConfigLoad::ReadString(size_t nPosition) const { char* ZwischenPuffer = new char[1000]; char* EndPuffer = new char[1000]; bool Leerzeichen = false; //ZischenPuffer füllen ZwischenPuffer = Puffer.substr (nPosition); //Ab dem ersten nicht-Zeichen abschneiden for (size_t i = 0; i < ZwischenPuffer.length(); i++) { Leerzeichen = false; if (isspace(ZwischenPuffer[i])) { Leerzeichen = true; } //Wenn Zahl zu Ende, zusammenkopieren if(Leerzeichen) { EndPuffer = ZwischenPuffer.substr (0, (i - 1)); i = ZwischenPuffer.length(); //Schleife beenden } } return EndPuffer; }Und die Fehlermeldungen:
ConfigLaden.cpp||In member function `bool ConfigLoad::FoundString(char*) const':| ConfigLaden.cpp|39|error: request for member `find' in `((const ConfigLoad*)this)->ConfigLoad::Puffer', which is of non-class type `char* const'| ConfigLaden.cpp||In member function `size_t ConfigLoad::StringPos(char*) const':| ConfigLaden.cpp|53|error: request for member `find' in `((const ConfigLoad*)this)->ConfigLoad::Puffer', which is of non-class type `char* const'| ConfigLaden.cpp|54|error: request for member `length' in `search', which is of non-class type `char*'| ConfigLaden.cpp||In member function `int ConfigLoad::ReadInt(size_t) const':| ConfigLaden.cpp|67|error: request for member `substr' in `((const ConfigLoad*)this)->ConfigLoad::Puffer', which is of non-class type `char* const'| ConfigLaden.cpp|70|error: request for member `length' in `ZwischenPuffer', which is of non-class type `char*'| ConfigLaden.cpp|82|error: request for member `substr' in `ZwischenPuffer', which is of non-class type `char*'| ConfigLaden.cpp|83|error: request for member `length' in `ZwischenPuffer', which is of non-class type `char*'| ConfigLaden.cpp||In member function `double ConfigLoad::ReadDouble(size_t) const':| ConfigLaden.cpp|100|error: request for member `substr' in `((const ConfigLoad*)this)->ConfigLoad::Puffer', which is of non-class type `char* const'| ConfigLaden.cpp|103|error: request for member `length' in `ZwischenPuffer', which is of non-class type `char*'| ConfigLaden.cpp|120|error: request for member `substr' in `ZwischenPuffer', which is of non-class type `char*'| ConfigLaden.cpp|121|error: request for member `length' in `ZwischenPuffer', which is of non-class type `char*'| ConfigLaden.cpp||In member function `char* ConfigLoad::ReadString(size_t) const':| ConfigLaden.cpp|137|error: request for member `substr' in `((const ConfigLoad*)this)->ConfigLoad::Puffer', which is of non-class type `char* const'| ConfigLaden.cpp|140|error: request for member `length' in `ZwischenPuffer', which is of non-class type `char*'| ConfigLaden.cpp|152|error: request for member `substr' in `ZwischenPuffer', which is of non-class type `char*'| ConfigLaden.cpp|153|error: request for member `length' in `ZwischenPuffer', which is of non-class type `char*'| ||=== Build finished: 16 errors, 0 warnings ===|Ich werd da echt nicht schlau draus.
-
Solltest du aber ...
error: request for member `find' in `((const ConfigLoad*)this)->ConfigLoad::Puffer', which is of non-class type `char* const'
ist doche eindeutig.
Du behandelst nen const char* wie ein Objekt... Der "Puffer" sollte vllt ein std::string sein?!?
-
Ich hatte den Puffer erst als String, aber C++ lässt nicht zu, dass ich den Filestream in einen String auslese:
C:\Eigene Dateien\C++\Projekte\Dateientest\ConfigLaden.cpp||In member function `void ConfigLoad::ReadNextLine()':| ConfigLaden.cpp|31|error: no matching function for call to `std::basic_ifstream<char, std::char_traits<char> >::getline(std::string&, int)'| C:\Programme\CodeBlocks\MinGW\bin\..\lib\gcc\mingw32\3.4.5\..\..\..\..\include\c++\3.4.5\bits\istream.tcc|582|note: candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::getline(_CharT*, std::streamsize, _CharT) [with _CharT = char, _Traits = std::char_traits<char>]| C:\Programme\CodeBlocks\MinGW\bin\..\lib\gcc\mingw32\3.4.5\..\..\..\..\include\c++\3.4.5\istream|399|note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::getline(_CharT*, std::streamsize) [with _CharT = char, _Traits = std::char_traits<char>]|Gibt es einen Weg, ein char-Array in einen String umzuwandeln?
Die anderen Puffer sind immer noch char-Arrays und mit einem einfachen "=", wie hier:
ZwischenPuffer = Puffer.substr (nPosition);will er die Umwandlung nicht machen:
C:\Eigene Dateien\C++\Projekte\Dateientest\ConfigLaden.cpp|69|error: cannot convert `std::basic_string<char, std::char_traits<char>, std::allocator<char> >' to `char*' in assignment|
-
Little Programmer schrieb:
Gibt es einen Weg, ein char-Array in einen String umzuwandeln?
Die anderen Puffer sind immer noch char-Arrays und mit einem einfachen "=", wie hier:
ZwischenPuffer = Puffer.substr (nPosition);will er die Umwandlung nicht machen:
C:\Eigene Dateien\C++\Projekte\Dateientest\ConfigLaden.cpp|69|error: cannot convert `std::basic_string<char, std::char_traits<char>, std::allocator<char> >' to `char*' in assignment|Mannmannmann... Wieso denn char* umwandeln in string?!? Verwende einen std::string! char*::find gibt es einfach nicht, da bracuht man sich nicht wundern.
Und genau so liest du aus nem std::istream in einen std::string:
http://www.cplusplus.com/reference/string/getline/Solltest echt noch etwas in deinem C++-Buch schmökern, bevor du dich an solch "komplexe" Programme ransetzt
-
Einem ehemaligen Java-Programmierer und jetzigen C++-Programmierer (wie mir) fällt sofort auf, dass Du versuchst, in C++ Java zu programmieren. Das ist eine ganz schlechte Idee. Folgende Macken hat dein Programm:
- Viel zu viele
news undnew[]s - Viel zu viele Zeiger
- Zuviel
char* - Speicher- und Resource-Lecks
- Ein impliziter Konstruktor, der ein expliziter sein sollte
- Misachtung der Dreierregel
- Puffer ist vom Typ char* und besitzt keine Elementfunktionen (wie zB "find")
Dir ist scheinbar das RAII-Konzept noch nicht bekannt. Unbedingt nachholen!
In C++ kapselt man die Verwaltung einer einzelnen Resource in der Regel in einem dedizierten Objekt (zB std::stringoderstd::ifstream).Objekte, die "logisch" gesehen Mitglieder eines anderen Objektes sind, sollten es auch "praktisch" sein, sofern möglich -- also direkte Objekt-Mitglieder, statt nur über private Zeiger erreichbar.
class foo { ... std::ifstream dings; // <-- muss kein Zeiger sein ... };Es gibt natürlich ausnahmen (Polymorphie, Compiler-Firewall). In Deinem Fall ist aber ein Zeiger auf ein ifstream Objekt unnötig. Du erzeugst dieses Objekt direkt im Konstruktor selbst. Es kann genauso gut ein "echtes" Objekt-Element sein.
BTW: Konstruktoren dürfen auch Exceptions schmeißen.
Tipp: Schnapp Dir ein gutes Buch zum Thema C++. Du kannst Dir damit viel Zeit und Ärger ersparen. Du tappst im Moment im Dunkeln. Ein Buch kann hier sehr erhellend sein und Dir den Weg leuchten -- mal metaphorisch gesprochen.
Gruß,
SP
- Viel zu viele
-
Ich hab die Exceptions mit Absicht hier raus geworfen. Das ist eigentlich Teil einer anderen Anwendung, in der es aber noch eine Weile dauert, bis sie eine Ausgabe hat. Ich nehme hier mit Absicht nur die Standardausgabe um die Funktionen erst einmal zu testen. Dann schreib ichs wieder um. Java hab ich noch nie geschrieben. Ich hatte auch erst ausschließlich strings anstatt char*, aber dann hat der Compiler nur noch gemeckert. Deshalb hatte ichs dann umgeändert.
@OMGler, ich benutze die getline-Funktion exakt so wie in der Referenz beschrieben und trotzdem bekomme ich die schon geposteten Fehlermeldungen. Der Fehler liegt irgendwo anders.
Ich schreib jetzt alles zum zweiten Mal zurück in String und mach den Filestreamzeiger zu nem Filestream.
Die "ConfigLaden.cpp" geht jetzt so:
#include <string> #include <fstream> #include <iostream> #include <cctype> #include "ConfigLaden.h" //using namespace std; ConfigLoad::ConfigLoad(std::string file) { //Puffer = new char[1000]; Puffer = ""; //Datei öffnen std::ifstream Konfiguration(file); //Fehlerkontrolle if (!Konfiguration -> good()) { Konfiguration.close(); std::cout << "Konnte nicht geoeffnet werden."; } } void ConfigLoad::ReadNextLine() { if (!Konfiguration.eof()) { Konfiguration.getline(Puffer, 1000); } } bool ConfigLoad::FoundString(std::string search) const { bool found = false; size_t position = 1000; //Suchen position = Puffer.find(search); if (position != 1000) { found = true; } return found; } size_t ConfigLoad::StringPos(std::string search) const { size_t found = 0; //Suchen found = Puffer.find(search); found += search.length(); return found; } int ConfigLoad::ReadInt(size_t nPosition) const { int Integer = 0; std::string ZwischenPuffer; std::string IntPuffer; bool Zahl = false; //ZwischenPuffer füllen ZwischenPuffer = Puffer.substr (nPosition); //Ab dem ersten nicht-Zahlzeichen abschneiden for (size_t i = 0; i < ZwischenPuffer.length(); i++) { Zahl = false; if(isdigit(ZwischenPuffer[i])) { Zahl = true; } //Wenn Zahl zu Ende, zusammenkopieren if(!Zahl) { IntPuffer = ZwischenPuffer.substr (0, (i - 1)); i = ZwischenPuffer.length(); //Schleife beenden } } //In int umwandeln Integer = atoi(IntPuffer); return Integer; } double ConfigLoad::ReadDouble(size_t nPosition) const { double Double = 0.0; std::string ZwischenPuffer; std::string DoublePuffer; bool Zahl = false; //ZwischenPuffer füllen ZwischenPuffer = Puffer.substr (nPosition); //Ab dem ersten nicht-Zahlzeichen abschneiden for (size_t i = 0; i < ZwischenPuffer.length(); i++) { Zahl = false; if (isdigit(ZwischenPuffer[i])) { Zahl = true; } if (ZwischenPuffer[i] == '.') { Zahl = true; } //Wenn Zahl zu Ende, zusammenkopieren if(!Zahl) { DoublePuffer = ZwischenPuffer.substr (0, (i - 1)); i = ZwischenPuffer.length(); //Schleife beenden } } //In int umwandeln Double = atof(DoublePuffer); return Double; } std::string ConfigLoad::ReadString(size_t nPosition) const { std::string ZwischenPuffer; std::string EndPuffer; bool Leerzeichen = false; //ZischenPuffer füllen ZwischenPuffer = Puffer.substr (nPosition); //Ab dem ersten nicht-Zeichen abschneiden for (size_t i = 0; i < ZwischenPuffer.length(); i++) { Leerzeichen = false; if (isspace(ZwischenPuffer[i])) { Leerzeichen = true; } //Wenn Zahl zu Ende, zusammenkopieren if(Leerzeichen) { EndPuffer = ZwischenPuffer.substr (0, (i - 1)); i = ZwischenPuffer.length(); //Schleife beenden } } return EndPuffer; }Die Fehlermeldungen: Der Compiler sucht basic_ifstream anstatt ifstream und die atoi und atof Funktionen funktionieren mit Strings nicht.
ConfigLaden.cpp||In constructor `ConfigLoad::ConfigLoad(std::string)':| ConfigLaden.cpp|17|error: `ifstream' was not declared in this scope| ConfigLaden.cpp|17|error: expected `;' before "Konfiguration"| ConfigLaden.cpp|20|error: base operand of `->' has non-pointer type `std::ifstream'| ConfigLaden.cpp|17|warning: unused variable 'ifstream'| ConfigLaden.cpp||In member function `void ConfigLoad::ReadNextLine()':| ConfigLaden.cpp|31|error: no matching function for call to `std::basic_ifstream<char, std::char_traits<char> >::getline(std::string&, int)'| istream.tcc|582|note: candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::getline(_CharT*, std::streamsize, _CharT) [with _CharT = char, _Traits = std::char_traits<char>]| istream|399|note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::getline(_CharT*, std::streamsize) [with _CharT = char, _Traits = std::char_traits<char>]| ConfigLaden.cpp||In member function `int ConfigLoad::ReadInt(size_t) const':| ConfigLaden.cpp|89|error: cannot convert `std::string' to `const char*' for argument `1' to `int atoi(const char*)'| ConfigLaden.cpp||In member function `double ConfigLoad::ReadDouble(size_t) const':| ConfigLaden.cpp|127|error: cannot convert `std::string' to `const char*' for argument `1' to `double atof(const char*)'| ||=== Build finished: 6 errors, 1 warnings ===|
-
#ifndef MYCONFIGLOADER_H #define MYCONFIGLOADER_H #include <fstream> #include <string> class ConfigLoad { public: ConfigLoad(const std::string& filename); bool ReadNextLine(); bool FoundString(const std::string& search) const; std::string::size_type StringPos(const std::string& search) const; int ReadInt(std::string::size_type nPosition) const; double ReadDouble(std::string::size_type nPosition) const; std::string ReadString(std::string::size_type nPosition) const; private: std::string puffer; std::ifstream konfiguration; }; #endif // MYCONFIGLOADER_H#include <iostream> #include <fstream> #include <sstream> #include <string> #include <cctype> #include "configloader.h" ConfigLoad::ConfigLoad(const std::string& filename): konfiguration(filename.c_str()) { if(!konfiguration) std::cerr << "Konnte nicht geoeffnet werden.\n"; } bool ConfigLoad::ReadNextLine() { if(std::getline(konfiguration, puffer)) return true; return false; } bool ConfigLoad::FoundString(const std::string& search) const { return puffer.find(search) != std::string::npos; } std::string::size_type ConfigLoad::StringPos(const std::string& search) const { return puffer.find(search); } int ConfigLoad::ReadInt(std::string::size_type nPosition) const { int ret_int(0); for(std::string::size_type beg(nPosition), end(puffer.size()); beg < end; ++beg) { if(!isdigit(puffer[beg]) || beg + 1 == end) { std::istringstream iss(puffer.substr(nPosition, beg + 1)); iss >> ret_int; break; } } return ret_int; } double ConfigLoad::ReadDouble(std::string::size_type nPosition) const { double ret_double(0.0); for(std::string::size_type beg(nPosition), end(puffer.size()); beg < end; ++beg) { if((!isdigit(puffer[beg]) && puffer[beg] != '.') || beg + 1 == end) { std::istringstream iss(puffer.substr(nPosition, beg + 1)); iss >> ret_double; break; } } return ret_double; } std::string ConfigLoad::ReadString(std::string::size_type nPosition) const { std::ostringstream oss; for(std::string::size_type beg(nPosition), end(puffer.size()); beg < end; ++beg) { if(isspace(puffer[beg]) || beg + 1 == end) { oss.str(puffer.substr(nPosition, beg + 1)); break; } } return oss.str(); }#include "configloader.h" #include <iostream> int main() { ConfigLoad config("test.txt"); while(config.ReadNextLine()) { if(config.FoundString("Hallo")) std::cout << "Begruessung in dieser Zeile vorhanden." << std::endl; else std::cout << "Keine Begruessung vorhanden." << std::endl; std::cout << "Lese int an Position 0: " << config.ReadInt(0) << std::endl; std::cout << "Lese double an Position 0: " << config.ReadDouble(0) << std::endl; std::cout << "Lese Wort an Position 0: " << config.ReadString(0) << std::endl; } }test.txt
test test Hallo test 87 noch ein Hallo test kein test 92.4
-
Little Programmer schrieb:
@OMGler, ich benutze die getline-Funktion exakt so wie in der Referenz beschrieben und trotzdem bekomme ich die schon geposteten Fehlermeldungen. Der Fehler liegt irgendwo anders.
Du benutzt die eben genau nicht so wie in dem von mir geposteten Link.
Um dir das Rumsuchen zu ersparen, hier exakt das Beispiel, wie es im Link unten steht:// getline with strings #include <iostream> #include <string> using namespace std; int main () { string str; cout << "Please enter full name: "; getline (cin,str); cout << "Thank you, " << str << ".\n"; }Und anstatt zu jammern, solltest du echt mal die Meldungen lesen und versuchen zu verstehen (ist nicht sooo schwer).
Um das mal anzustoßen:error: `ifstream' was not declared in this scope|Er kennt ifstream nicht. Was macht man da?
error: expected `;' before "Konfiguration"Folgefehler...
ConfigLaden.cpp|20|error: base operand of `->' has non-pointer type `std::ifstream'|operator-> geht nur mit Pointern, und dein ifstream-Objekt ist ein non-pointer. Was macht man da?
Und nun:
error: no matching function for call to `std::basic_ifstream<char, std::char_traits<char> >::getline(std::string&, int)'| istream.tcc|582|note: candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::getline(_CharT*, std::streamsize, _CharT) [with _CharT = char, _Traits = std::char_traits<char>]|Das sagt mir, dass du getline nicht so verwendest wie du es vorgibst...
Ich hör mit den Fehlern hier mal auf, du hast echt nur ifstream* durch ifstream ersetzt, genauso wie die Deaklaration von Puffer in std::string umgemünzt, aber im Code nichts verändert. Hol das nach...
-
Soweit verstanden, dass ifstream nicht erkannt wurde und der nächste Fehler ein Folgefehler ist, habe ich die Fehlermeldungen ja auch. Meine Frage war ja das Warum. Das mit dem -> hatte ich übersehen.
@Krise, danke für's korrigieren.
Ich werd das jetzt ein paar Mal durchlesen. Sehr lehrreich. 
-
null problemo