Zeichenkeete casten
-
Sicher eine dumme Frage, aber ich raffe es gerade nicht. Folgender Konstrukt liefert mir eine Warnung "Zeichenkette mit mehreren Konstanten":
long l; ... if (l=='BLA!') { ... }
Es funktioniert korrekt weil der in "l" eingelesene Wert eigentlich eine lesbare Zeichenkette ist, nur wie muss ich den String 'BLA!" korrekt casten damit diese Meldung nicht mehr kommt UND ich die Zeichenkette trotzdem noch leserlich im code stehen habe?
-
machs doch irgendwie so:
[cpp]
char str[]="hallo karlheinz";if(strcmp(str, "hallo karlheinz") == 0)
{
//sind gleich
}
else //sind nicht gleichhoffe gehülfen zu haben konnten, danke.
-
Nein, das will ich eben nicht da es viel zu aufwändig ist (Geschwindigkeitsproblem). Der vergleich mit einem long-Wert der in ASCII-Darstellung eben ein Text ist muss ja auch irgend wie gehen ohne dass ich diese Meldung bekomme.
-
Geschwindigkeitsproblem? Bei den heutigen Rechnern?
Das Problem ist: Du kannst für long nur eine Zahl eingeben, keine Schriftzeichen. Schriftzeichen müssen in einem char-Array (char dingens[] = "Bla") gespeichert werden.
Nachträglich kann man die Werte im Char nach long convertieren (mit (long)dingens)" oder so ähnlich), so daß die ASCII-Werte als Zahlen verstanden werden.
-
solang dein string genau 4 zeichen hat, passt er in ein 32bit-integer.
dazu liesst du einfach ein integer an der adresse des strings aus:char* idstr1="BLA!"; // entweder als string - wegen \0 aber 5 byte gross char idstr2[4]={'B','L','A','!'}; // oder als 4 chars... int id1= *((int*)idstr1); int id2= *((int*)idstr2); int id3= (int)'BLA!'; // ... oder direkt als int, dann ist endianess zu beachten if (id1==id2) // ...
-
Elektronix schrieb:
Geschwindigkeitsproblem? Bei den heutigen Rechnern?
Wer hat denn was über die verwendete Hardware gesagt?
Das Problem ist: Du kannst für long nur eine Zahl eingeben, keine Schriftzeichen. Schriftzeichen müssen in einem char-Array (char dingens[] = "Bla") gespeichert werden.
Falsch, so wie ich es oben gezeigt habe funktioniert es ganz problemlos, der "String" wird als long behandelt und korrekt verglichen - es kommt halt nur die Warnung, dass hier etwas nicht ganz korrekt sein könnte.
Nachträglich kann man die Werte im Char nach long convertieren (mit (long)dingens)" oder so ähnlich), so daß die ASCII-Werte als Zahlen verstanden werden.
Und genau das geht oben eben nicht, ein (long)'BLA!" führt zu exakt der selben Warnung wie bereits geschrieben.
-
Benutzer schrieb:
Falsch, so wie ich es oben gezeigt habe funktioniert es ganz problemlos, der "String" wird als long behandelt und korrekt verglichen
Ja klar, der Datentyp heisst ja auch long weil besonders lange Strings hineinpassen
-
LordJaxom schrieb:
Ja klar, der Datentyp heisst ja auch long weil besonders lange Strings hineinpassen
Sorry, aber wenn du keine Ahnung hast solltest du es bleiben lassen: Auf Hardwareebene ist alles nur eine Zahl. Einen String kann ich auch als Zahl darstellen (schon mal was von ASCII gehört?) und bestimmte Zahlen stellen auf Basis dieser ASCII-Konvertierung wieder lesbare Zeichen dar.
Mit anderen Worten: Der 4stellige String 'BLA!' lässt sich auch als 32-Bit-Zahl darstellen, nichts anderes mache ich oben, nur dass ich mit dieser Notation den lesbaren Text erhalte statt irgend ein kryptisches 0xYYYYYYYY zu verwenden (wobei Y in diesem Beispiel für je eine Hex-Stelle steht, bevor hier wieder ein Schlaumeier vorbeikommt...).
Die Methode mit dem Vergleich long=='BLA!' ist übrigens vollständig portabel, sie Funktioniert mit VC++, mit dem BCB und mit dem gcc.
-
...was ist jetzt nochmal das problem?
MSVC warnt da nichts:
if (l=='BLA!')
was nicht unbedingt heisst, dass es da nichts zu warnen gaebe...
-
Ganz einfach: der korrekt arbeitende Vergleich
long l; ... if (l=='BLA!')
liefert eine Warnung, die an sich nur unschön, funktional aber kein Problem ist. Meine Frage war, durch welchen Cast ich die wegbekomme, sprich ich muss dem Compiler beibringen dass er 'BLA!' in sein ASCII-Zahlenäquivalent umwandelt bzw. es als solches ansieht.
if (l==(long)'BLA!')
funktioniert nicht.
-
Ach ja, die Warnung kommt nur beim GCC, BCB und MSVC++ übergehe ndie Stelle schweigend.
-
gcc macht's richtig.
die warnung bedeutet 'du wolltest doch bestimmt ein char-array haben, oder?'
damit das warning verschwindet, musste den code umschreiben:long l = *(long*)"123";
das ist wenigstens einigermassen portabel, ein 'l = 'BLA' dagegen nicht...
-
Danke net, das sieht gut aus, ich werde es mal probieren.
Ich dachte ja schon, auf den "schneller als Zeichenweise geht es nicht"-Schwachsinn kommt gar nichts mehr (hallo? seit wann ist ein 32-Bit-Vergleich langsamer als ein Zeichen-für-Zeichen-Gemurkse?).
-
Benutzer schrieb:
Danke net, das sieht gut aus, ich werde es mal probieren.
...aber beachte dass auf 'ner little-endian pc-kiste '1234' nicht (long)"1234", sondern alles rückwärts ist
-
Auf C-Ebene sind "XYZW" und longs eben grundverschiedene Dinge,
die nicht direkt vergleichbat sind.Du mußt schon bitweise mit maskieren und shiften arbeiten, um einen
String mit einem long zu vergleichen.
-
Benutzer schrieb:
Es funktioniert korrekt weil der in "l" eingelesene Wert eigentlich eine lesbare Zeichenkette ist, nur wie muss ich den String 'BLA!" korrekt casten damit diese Meldung nicht mehr kommt UND ich die Zeichenkette trotzdem noch leserlich im code stehen habe?
Erstmal solltest du Typ int verwenden, denn diesem entspricht eine solche "multi-character constant". Abschalten kannst du diese Warnung beim GCC mit -Wno-multichar.
Trotzdem, du solltest beachten, dass solche Konstanten implementationsspezifisch sind, und dadurch Probleme entstehen können, zB weil ein int nicht gross genug ist, oder die Vorzeichen von char und int unterschiedlich sind. Little- und big-endian kann ebenfalls zum Problem werden.
-
Zorg-- schrieb:
wenn man plattformübergreifend einen 32-Bit-Datentyp haben möchte nimmt man eben long oder unsigned long, die sind überall 32 Bit.
mindestens, ne?
wenn'se zu gross sind kann's aber auch zu komischen bugs führen.
besser man nimmt selbstgemachte typen. etwa so:#ifdef PROCESSOR_A typedef unsigned short UINT16; #elif PROCESSOR_B typedef unsigned int UINT16; ...
das kennt ihr bestimmt...
-
strcmp ist doch bei den meisten libraries schon auf diese weise optimiert.