Stringlisten und Review
-
Hallo Forum,
ich versuche gerade etwas mit Stringlisten zu machen. Hier im konkretem Fall möchte ich alle MAC Adressen auslesen. BSP im Inet (VB6 Code): http://www.office-loesung.de/ftopic1521_0_0_asc.php
Ich habe 3 Fragen:
1. Die MACs bekomme ich in einen C++ String gelesen. Bloß wenn ich den Pointer auf den String in die Liste schreibe und ihn später wieder raushole steht an der Stelle etwas anderes. (Der Speicher wurde mit new angefordert und nicht wieder freigegeben.)2. Beim kompilieren kommen diese Warnungen:
warning C4786: 'std::reverse_bidirectional_iterator<std::list<std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > *> >::iterator,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::basic_string<char,std::char_traits<char>,std::allocator<char> > * &,std::basic_string<char,std::char_traits<char>,std::allocator<char> > * *,int>' : identifier was truncated to '255' characters in the debug informationBei einem Doppelklick lande ich im LIST Header vom VS6.0. Was soll mir das sagen?
3. Allgemein gefragt: Ist das guter (durchschnittlicher) C++ Code oder schleppe ich sonst noch irgendwo C Zeugs mit rum?
Um den Source zum Laufen zu bringen einfach diesen Source in einen Header mit Namen aaaa.h auslagern. Den Source darunter in ein KonsolenProjekt kopieren und die main() überschrieben. Man benötigt das Microsoft SDK und die IPHlpApi.lib.
// Diese Klasse liesst bestimmte Computer Daten ein und stellt sie der Applikation // zur Verfügung. Die Daten werden im Konstruktor eingesammelt und stehen dann // als PublicMember zur Verfügung. Die Daten die eingesammelt werden sind: // -- Liste der Mac Addressen. #ifndef _ComputerData_ #define _ComputerData_ #include <windows.h> #include <sstream> #include <list> #include <IPHlpApi.h> // Ermittlung der Mac Adresse. using namespace std; // Fehler die intern auftreten können: enum ErrorConst { NoMacAddress }; class ComputerData { public: list<string *> m_oMacAddresses; ComputerData(); ~ComputerData(); private: FillMacAddress() throw(ErrorConst); }; #endif // _ComputerData_#include "stdafx.h" #include <iostream> #include "aaaa.h" // Füllt alle MAC Addressen (maximal 100) in eine Liste: ComputerData::FillMacAddress() throw(ErrorConst) { ostringstream ss; char *AdapterInfo; DWORD dwBufLen=0, result=0; char *cMac=0; string *sTemp; // Mac Adressen per Api holen: dwBufLen = sizeof(AdapterInfo)/sizeof(IP_ADAPTER_INFO); result = GetAdaptersInfo(0, &dwBufLen); AdapterInfo = new char[dwBufLen]; result = GetAdaptersInfo((IP_ADAPTER_INFO *)AdapterInfo, &dwBufLen); PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *)AdapterInfo; // Fehler werfen wenn keine gefunden: if (!pAdapterInfo) throw NoMacAddress; // Schreibe jede Mac in die Liste: do { cMac = new char[18]; // Schreibe die MAC mit Bidnestrichen formatiert in ein char[]: sprintf(cMac, "%02x-%02x-%02x-%02x-%02x-%02x", (pAdapterInfo->Address)[0], (pAdapterInfo->Address)[1], (pAdapterInfo->Address)[2], (pAdapterInfo->Address)[3], (pAdapterInfo->Address)[4], (pAdapterInfo->Address)[5] ); // Konvertiere die MAC von char[] nach string und schreibe den String in die Liste: ss << cMac; delete[] cMac; sTemp = new string(); *sTemp = ss.str(); m_oMacAddresses.push_back(sTemp); // sTemp ist ein Pointer auf einen String mit gültiger MAC. ss.str(""); } while (pAdapterInfo=pAdapterInfo->Next); } // Hole die Daten per Funktionsaufruf im Konstruktor: ComputerData::ComputerData() { try { FillMacAddress(); } catch (ErrorConst e) { switch (e) { case NoMacAddress: cout << "MacAddress could no be read." << endl; break; default: cout << "Unknown error." << endl; } } catch (...) { cout << "Unknown error." << endl; } } // Den Speicher der Stringliste wieder freigeben: ComputerData::~ComputerData() { if (m_oMacAddresses.size()) { for(list<string*>::iterator pos=m_oMacAddresses.begin(); pos!=m_oMacAddresses.end(); pos++) { delete *pos; } } } int main(int argc, char* argv[]) { ComputerData *oData; oData = new ComputerData(); for(list<string*>::iterator pos=oData->m_oMacAddresses.begin(); pos!=oData->m_oMacAddresses.end(); pos++) { cout << *pos << endl; // Hier steht nicht die MAC! } delete oData; return 0; }
-
pos ist der Iterator.
*pos ist der Zeiger auf den String.
**pos ist der String.Warum speicherst du überhaupt Zeiger?
-
@1: Lass am besten das ganze Zeiger-Gegurke weg - string's sind kompakt genug, um sie auch auf dem Stack anzulegen und zu verwalten.
@2: Die Warnung kannst du i.a. ignorieren (oder per #pragma gleich abschalten).
@3: Der Code ist grauenhaft
(besonders das oben erwähnte Zeiger-Gegurke)PS: Und eventuell solltest du dir mal ansehen, was sizeof kann (und was nicht).
-
Erstmal vielen Dank für die Tips

Ich habe jetzt SizeOf() antfernt und eine Stringliste ohne Pointer gemacht:
list<string> m_oMacAddresses;Wie lösche ich jetzt den String?
Nach dem was MFK gesagt hat muß bei jetziger Listendefinition *pos der String sein. Warum geht dann "delete *pos;" nicht?
ComputerData::~ComputerData() { if (m_oMacAddresses.size()) { for(list<string>::iterator pos=m_oMacAddresses.begin(); pos!=m_oMacAddresses.end(); pos++) { delete *pos; } } }Fehlermeldung:
cannot convert from 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' to ''
Gibt es keine praktikable alternative zu sprintf() in iostream?
Was wäre noch Verbesserungswürdig? Die beiden alten C Casts werfe ich schon selber heraus wenn ich die richtigen Datentypen zu IP_ADAPTER_INFO gefunden habe.
-
Die Listenelemente kannst du ganz einfach per erase() löschen (aber an der Stelle ist das nicht einmal nötig, die liste räumt schon selber auf, wenn sie vernichtet wird).
Und als Alternative zu sprintf() kannst du die Stream-Ausgabe per << verwenden:
-
C++ Anfänger 2 schrieb:
...Wie lösche ich jetzt den String?...
*** ambiguity error***

"string löschen" = "Einen String aus der Liste entfernen"
"string löschen" = "Stringobjekt destruieren"
"string löschen" = "Inhalt auf fachlich leeren String setzen"Ersteres: s. CStoll.
Zweiteres: Gar nicht - brauchst Du auch nicht.
Drittes: = ""; (wenn Du's wirklich brauchen solltest)Gruß,
Simon2.
-
Zu der Liste habe ich noch ein paar Fragen.
//Sie ist jetzt so angelegt: list<string> m_oMacAddresses; // aaa zeigt auf ein mit new angeforderten string. m_oMacAddresses.push_back(*aaa); // Den einzigen String holen: list<string>::iterator pos = m_oMacAddresses.begin(); // *pos ist also der String ,also pos die Adresse des Strings. cout << *pos << endl; // Aus der Liste entfernen: m_oMacAddresses.remove(*pos); // Warum geht "temp = pos;" nicht? pos ist doch nur ein Pointer auf den String? (Siehe cout) string *temp = &(*pos); // Das geht, aber warum kann ich "delete pos" auch nicht machen wenn es ein Pointer auf den String ist? delete temp;
-
Hi,
mach es Dir doch noch einfacher:
//Sie ist jetzt so angelegt: list<string> m_oMacAddresses; string aaa = "Simon2"; // aaa ist der string. list legt selbst eine Kopie an. m_oMacAddresses.push_back(aaa); // Den einzigen String holen: list<string>::iterator pos = m_oMacAddresses.begin(); // pos verweist auf den String und mit *pos bekomme ich Zugriff auf den String cout << *pos << endl; // Alle gleichlautenden Strings aus der Liste entfernen - führt auch dazu, dass diese Stringobjekte selbst freigegeben werden: m_oMacAddresses.remove(*pos);und pos ist kein "Pointer auf einen String", sondern ein Iterator !
Sieht man schon am Typen: list<string>::iterator
Für bestimmte Situationen funktioniert zwar ein Pointer wie ein Iterator, aber das heißt noch nicht, dass sie immer identisch seien (und in diesem Fall eben auch nicht).Übrigens list::remove() entfernt ALLE passenden Strings aus dem Container !! Das können durchaus mehr als einer sein !
Willst Du nur den einen entfernen, hilft erase():list<string> m_oMacAddresses; string aaa = "Simon2"; m_oMacAddresses.push_back(aaa); m_oMacAddresses.push_back(aaa); // nochmal einen einfügen list<string>::iterator pos = m_oMacAddresses.begin(); cout << *pos << endl; m_oMacAddresses.erase(*pos);Hier ist nur das erste "Simon2" aus der Liste entfernt (und gelöscht) worden...
Gruß,
Simon2.
-
Puh ist das ungewohnt. Ich hatte vor 4-5 Jahren im Grundstudium mal 1 Semester lang C++ aber das waren wohl wirklich nur die Basics. Ich werde mir erstmal ein Buch aus einer Bücherei holen wo die STL erklärt wird. Und wie ich jetzt lese ist es auch gar nicht die STL wie mir während des Studiums beigebracht worden ist...
http://de.wikipedia.org/wiki/C++-Standardbibliothekwurde aber im Laufe der Standardisierung durch den Einfluss einer bei Hewlett-Packard entwickelten Bibliothek namens Standard Template Library (STL) stark überarbeitet. Heute wird fälschlicherweise die C++-Standardbibliothek im Volksmund immer noch STL genannt, obwohl
Vielen Dank Simon, CStoll und MFK
