deadtronic
Anmeldungsdatum: 18. Februar 2010
Beiträge: 762
|
Folgender Code:
char* one = getLine(...);
char* two = getLine(...);
rtrn.push_back( list_of(one)(two) );
std::cout << rtrn[pos_rtrn][0] << std::endl;
Gibt nichts aus. An getLine liegt es nicht, ein cout one/two gibt den gewollten Inhalt aus, nur der Vektor rtrn ist leer. Kompilier- und Laufzeitfehler gibt es keine. pos_rtrn ist ein Integer zum Zählen in einer Schleife, allerdings gibt zB ein rtrn[0][0] auch nichts aus. Jemand eine Idee, woran es sonst noch liegen könnte?
Die notwendigen Boost-Libs für list_of sind auch included. Danke & Gruß deadtronic
|
cn
Anmeldungsdatum: 6. Juni 2005
Beiträge: 356
Wohnort: Oberösterreich
|
Kannst du einen Verweis zur Doku von list_of angeben?
Weiters wäre es hilfreich, wenn du das gesamte Programm (also auch den Inhalt von getLine und alle Variablendeklarationen) bekanntgibst.
|
deadtronic
(Themenstarter)
Anmeldungsdatum: 18. Februar 2010
Beiträge: 762
|
cn schrieb: Kannst du einen Verweis zur Doku von list_of angeben?
http://beta.boost.org/doc/libs/1_34_1/libs/assign/doc/index.html#list_of Weiters wäre es hilfreich, wenn du das gesamte Programm (also auch den Inhalt von getLine und alle Variablendeklarationen) bekanntgibst.
Mittlerweile, nach einigen änderungen, klappt das obige, teilweise kann ich jetzt den Inhalt des Arrays ausgeben, teilweise bekomme ich allerdings einen Laufzeitfehler (auch in der Schleife unten):
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check
Aborted Hier mal der Code etwas ausführlicher der Reihe nach:
Scan scanAutostarts;
std::vector< std::vector<std::string> > entrys = boost::assign::list_of(0)(0);
entrys = scanAutostarts.doScan();
int size = (int)entrys.size();
//printf("Total Elements: %d\n", index);
std::cout << "1_0:" << entrys.at(2).at(0);
for(long index = 0; index < size; index++)
{
rl->pushBack(refListStore, liststore, true,
entrys.at(index).at(1),
entrys.at(index).at(2)); // <-------------- Fehler
}
In den obigen aufrufen von entrys liegt auch das Problem. Hier der Restliche Code, der verwendet wird, möglicherweise ist da auch etwas falsch, allerdings habe ich getLine() getestet, es gibt nur valide Strings aus.
std::vector< std::vector<std::string> > Scan::doScan()
{
std::vector< std::vector<std::string> > rtrn = boost::assign::list_of(0)(0);
DIR *hdir;
struct dirent *entry;
char* directory = (char*) malloc (256);
strcpy(directory, getenv("HOME"));
strcat(directory, "/.config/autostart/");
char type[] = ".desktop";
hdir = opendir(directory);
int pos_rtrn = 0;
do
{
entry = readdir(hdir);
if (entry)
{
if (strstr(entry->d_name, type) != NULL)
{
std::string one = getLine("\'/^Name=/!d\'", entry->d_name, directory);
std::string two = getLine("\'/^Exec=/!d\'", entry->d_name, directory);
rtrn.push_back ( list_of (one)(two) );
std::cout << "scan.cc";
pos_rtrn++;
}
}
} while (entry);
closedir(hdir);
return rtrn;
}
char* Scan::getLine(const char regEx[256], char* file, char* dir)
{
char* cmd = (char*) calloc(1024, sizeof(cmd));
strcat(cmd, "/bin/sed -e ");
strcat(cmd, regEx);
strcat(cmd, " ");
strcat(cmd, dir);
strcat(cmd, file);
char* rtrn = (char*) calloc(4096, sizeof(cmd));
char* buffer = (char*) calloc(4096, sizeof(cmd));
FILE *sed = popen(cmd, "r" );
while ( fgets( buffer, sizeof buffer, sed ) != NULL )
{
strcat(rtrn, buffer);
}
pclose( sed );
return rtrn;
} Bei list_of bin ich mir nicht ganz so sicher ob das so funktioniert wie ich das vorhabe (also dem vector 2 Werte multidimensional zuweisen), aber ich habe das mal in irgendeinem Forum gefunden, vielleicht liegt es auch daran. Beispielsweise: std::cout<< entrys.at(2).at(0); gibt aber das gewünschte aus, während es mit (3)(0) den obigen Fehler ausgibt.
|
cn
Anmeldungsdatum: 6. Juni 2005
Beiträge: 356
Wohnort: Oberösterreich
|
Ich bitte das als objektive und konstruktive Kritik aufzufassen: Das Programm ist relativ unübersichtlich geschrieben, was z.B. die Variablennamen betrifft. Auch erschließt sich mir nicht, weshalb du statt new und delete mit calloc arbeitest bzw. überhaupt dynamisch Speicher anforderst. Was mir auffällt, unabhängig von dem vector-Fehler:
| rl->pushBack(refListStore, liststore, true,
entrys.at(index).at(1),
entrys.at(index).at(2)); // <-------------- Fehler
|
Sollten 1 und 2 nicht eher 0 und 1 sein? Aber ich konnte nicht die Zeile finden, in der rl deklariert ist.
|
Hello_World
Anmeldungsdatum: 13. Juni 2006
Beiträge: 3620
|
Das Starten eines externen Prozesses wie sed aus einem C++-Programm heraus ist meist eine schlechte Idee, Du schreibst hier kein Shell-Script. Für reguläre Ausdrücke in C++ kann man z. B. std::tr1::regex verwenden. Und char* verwendet man in C++ nicht, verwende stattdessen eine String-Klasse wie std::string (ja, ich weiß, dass popen nunmal einen FILE* liefert, aus dem man nicht ohne weiteres einen std::string lesen kann. Aber da das Starten eines Prozesses hier unnötig ist, brauchst Du auch popen nicht mehr (welches ohnehin eine bekloppte Funktion ist, aber ich schweife ab)). Die Probleme, zu denen malloc & Co. führen, sieht man auch in Deinem Programm, da Du den mit calloc allokierten Speicher nirgends freigibst, von den sinnlosen hart codierten Puffergrößen ganz zu schweigen. Ferner ist std::vector< std::vector<std::string> > entrys = boost::assign::list_of(0)(0) absurd, std::vector<std::vector<std::string> > entries(2) tut das gleiche, nur in einfach.
|
deadtronic
(Themenstarter)
Anmeldungsdatum: 18. Februar 2010
Beiträge: 762
|
cn schrieb: Ich bitte das als objektive und konstruktive Kritik aufzufassen:
Klar, ich bin froh über alles was ihr mir dazu sagt, ich beschäftige mich noch nicht allzu lang mit C++. 😉 Das Programm ist relativ unübersichtlich geschrieben, was z.B. die Variablennamen betrifft. Auch erschließt sich mir nicht, weshalb du statt new und delete mit calloc arbeitest bzw. überhaupt dynamisch Speicher anforderst.
also char* bla = new char[int];? Sso wie es aussieht werde ich diese wohl sowieso nicht mehr brauchen. Sollten 1 und 2 nicht eher 0 und 1 sein?
Stimmt, ich hatte es zeitweise zum testen umgeändert und vergessen es wieder zurückzusetzen. Trotzdem hat das ganze nichts damit zu tun.
Aber ich konnte nicht die Zeile finden, in der rl deklariert ist.
Die ist dort auch nicht enthalten, das ist diese Funktion:
void pushBack(Glib::RefPtr<Gtk::ListStore> &refListStore, ModelColumns &liststore, bool aktiv, std::string name, std::string command); Hello World schrieb: Das Starten eines externen Prozesses wie sed aus einem C++-Programm heraus ist meist eine schlechte Idee, Du schreibst hier kein Shell-Script. Für reguläre Ausdrücke in C++ kann man z. B. std::tr1::regex verwenden.
Hmm, ich hatte vor diesem Schritt ausführlich das Internet durchsucht, und überall stand es gibt keine regulären ausdrücke in C++. Wenn das so ist, werde ich die tr1-regex verwenden - ich habe die jetzige Lösung auch nie für besonders gut gehalten. Und char* verwendet man in C++ nicht, verwende stattdessen eine String-Klasse wie std::string (ja, ich weiß, dass popen nunmal einen FILE* liefert, aus dem man nicht ohne weiteres einen std::string lesen kann. Aber da das Starten eines Prozesses hier unnötig ist, brauchst Du auch popen nicht mehr (welches ohnehin eine bekloppte Funktion ist, aber ich schweife ab)). Die Probleme, zu denen malloc & Co. führen, sieht man auch in Deinem Programm, da Du den mit calloc allokierten Speicher nirgends freigibst, von den sinnlosen hart codierten Puffergrößen ganz zu schweigen.
Werde ich auch berücksichtigen ☺ Ferner ist std::vector< std::vector<std::string> > entrys = boost::assign::list_of(0)(0) absurd, std::vector<std::vector<std::string> > entries(2) tut das gleiche, nur in einfach.
Und das auch. Danke für die vielen Tipps. Ich werde jetzt das alles mal einbauen, auf tr1::regex umstellen und melde mich dann nochmal, wenn alles funktioniert oder immer noch nicht tut.
|
deadtronic
(Themenstarter)
Anmeldungsdatum: 18. Februar 2010
Beiträge: 762
|
/usr/include/c++/4.4/c++0x_warning.h:31: error: #error This file requires compiler and library support for the upcoming ISO C++ standard, C++0x. This support is currently experimental, and must be enabled with the -std=c++0x or -std=gnu++0x compiler options. Macht es Sinn, ein experimentelles Feature zu benutzen? Ich denke zwar nicht, dass ich damit Probleme bekommen würde, aber eigentlich wird einem von sowas ja stark abgeraten. Oder wäre es besser, die regex von boost zu verwenden?
|
cn
Anmeldungsdatum: 6. Juni 2005
Beiträge: 356
Wohnort: Oberösterreich
|
deadtronic schrieb: Macht es Sinn, ein experimentelles Feature zu benutzen? Ich denke zwar nicht, dass ich damit Probleme bekommen würde, aber eigentlich wird einem von sowas ja stark abgeraten. Oder wäre es besser, die regex von boost zu verwenden?
Nachdem ohnehin zu erwarten ist, dass es im Standard vorhanden sein wird, kannst du es durchaus bereits verwenden falls es nicht herumzickt. Aber generell ist es auch nicht falsch, an "alten" Bibliotheken festzuhalten, die bereits etabliert sind, wenn diese ebenfalls bereits zufriedenstellend funktionieren (BOOST...). Das hat den Vorteil, dass man eben nicht etwas "Experimentelles" verwendet, das ja brandneu und vermutlich noch nicht lange getestet ist.
|
Hello_World
Anmeldungsdatum: 13. Juni 2006
Beiträge: 3620
|
Nimm #include <tr1/regex> statt #include <regex> , dann bekommst Du die Meldung nicht mehr. Oder Du benutzt Boost. //edit: vergiss tr1, die libstdc++ implementiert das tr1-regex-Zeug davon noch nicht (http://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html). Aber es spricht ja auch nichts gegen Boost.
|
deadtronic
(Themenstarter)
Anmeldungsdatum: 18. Februar 2010
Beiträge: 762
|
Habe mich vorerst für Boost entschieden, allerdings komme ich damit nicht so wunderbar klar. Hier wird das ganze so gemacht:
std::string s, sre;
boost::regex re;
//...
re.assign(sre, boost::regex_constants::icase); Bei mir so:
boost::regex rx;
rx.assign(regEx); // regEx: std::string, wird beim Funktionsaufruf übergeben Aber so richtig will das nicht.
scan.o: In function `boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::assign(char const*, char const*, unsigned int)':
scan.cc:(.text._ZN5boost11basic_regexIcNS_12regex_traitsIcNS_16cpp_regex_traitsIcEEEEE6assignEPKcS7_j[boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::assign(char const*, char const*, unsigned int)]+0x2e): undefined reference to `boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::do_assign(char const*, char const*, unsigned int)' Warum funktioniert das bei denen, aber bei mir nicht? 🙄 Die Doku zu Boost.Regex befindet sich hier, falls das hilft.
|
Hello_World
Anmeldungsdatum: 13. Juni 2006
Beiträge: 3620
|
Du musst gegen die Boost Regex-Bibliothek linken, das sollte mit dem Schalter -lboost_regex gehen (das -dev -Paket der Boost Regex-Bibliothek muss dafür installiert sein).
|
deadtronic
(Themenstarter)
Anmeldungsdatum: 18. Februar 2010
Beiträge: 762
|
Ok hatte mich schon gewundert. Funktioniert jetzt bestens, danke ☺
|
deadtronic
(Themenstarter)
Anmeldungsdatum: 18. Februar 2010
Beiträge: 762
|
So funktionierts mittlerweile
std::vector< std::vector<std::string> > entrys(100, std::vector<std::string>(0));
while (iwas)
{
std::string name = getLine("^Name=.*$", entry->d_name, directory);
std::string exec = getLine("^Exec=.*$", entry->d_name, directory);
entrys[pos][0] = name;
entrys[pos][1] = exec;
pos++;
}
Kleines Problem ist aber, dass wenn ich den Vector jetzt wieder per Schleife auslese, bekomme ich sämtliche 100x Eintrage, wovon fast alle leer sind. Ich brauche die Größe aber dynamisch. Probiert habe ich es mit resize innerhalb obiger Schleife.
std::vector< std::vector<std::string> > entrys(1, std::vector<std::string>(0));
int pos = 1;
// while...
pos++
entrys.resize ( pos );
Das führt aber zu nicht besonders viel.
*** glibc detected *** ./program: free(): invalid pointer: 0x0000000001653bb8 ***
Was mache ich falsch? Danke schonmal, danach hätte ich das endlich geschafft ☺
|
Hello_World
Anmeldungsdatum: 13. Juni 2006
Beiträge: 3620
|
deadtronic schrieb: Was mache ich falsch?
Du stellst keinen Test Case bereit. Erstelle ein Programm, das alle der folgenden Punkte erfüllt:
Es wird vom Compiler genau so akzeptiert Es ist so kurz wie möglich Es demonstriert den Fehler
Mit den von Dir geposteten Codefetzen kann man nichts anfangen.
|
deadtronic
(Themenstarter)
Anmeldungsdatum: 18. Februar 2010
Beiträge: 762
|
Hello World schrieb: Mit den von Dir geposteten Codefetzen kann man nichts anfangen.
Ok, eigentlich hatte ich nur so wenig gepostet, weil ich oben schon fast alles gepostet hatte und niemanden verwirren wollte. Die annahme, dass das ausreichend ist, ist wohl falsch. Egal, mittlerweile habe ich das selber gelöst. Ich wollte ja den multidimensionalen Vektor entrys vergrößern. Das Problem dabei war, dass ich nur die erste Dimension vergrößert habe und die zweite vergessen hatte, sodass es natürlich einen Fehler beim Versuch gab, darauf zuzugreifen. Richtig wäre das so gewesen:
std::vector< std::vector<std::string> > entrys(10, std::vector<std::string>(2));
entrys.resize ( pos + 1 );
entrys[pos].resize ( 2 );
Oder wen es interessiert, hier die komplette Funktion. Damit hat sich das ursprüngliche Problem erledigt. Danke für eure Geduld und verzeihung, dass ich mich vielleicht etwas unvollständig ausdrücke, aber ich wusste einfach selber nicht was ich will und was du dafür für Infos brauchtst, bin eher von einem simplen Problem ausgegangen.
|