2009-06-08 14 views
14

ich folgendeWie initialisieren char-Array aus einem String

char a[] = { 'A', 'B', 'C', 'D'}; 

tun will Aber ich will diese Zeichen nicht separat schreiben. Ich möchte etwas wie

#define S "ABCD" 

char a[] = { S[0], S[1], S[2], S[3] }; 

Aber das wird nicht kompilieren (gcc sagt 'Initialisierungselement ist nicht konstant').

Ich versuchte, die #define Linie mit

const char S[] = "ABCD"; 

ersetzt aber das scheint nicht zu helfen.

Wie kann ich dies (oder etwas Ähnliches) machen, das mich die "ABCD" als normale "Zeichenfolge" schreiben lässt und nicht als vier separate Zeichen?

P.S. Es scheint, dass die Menschen nicht lesen, die Frage richtig ...

ich nicht der folgende Code bekommen kann zu kompilieren:

const char S[] = "ABCD"; 
char t[] = { S[0], S[1], S[2], S[3] }; 
char u[] = { S[3], S[2], S[1], S[0] }; 
+4

warum nicht einfach char a [] = "ABCD"; –

+0

Es sollte auf jeden Fall funktionieren. Wie hast du kompiliert? Welche Optionen gibst du an gcc weiter? – qrdl

+1

Bitte erläutern Sie, warum eine Char-Zeichenfolge kopiert/einer anderen Char-Zeichenfolge zugewiesen werden soll, indem eine individuelle Zeichenzuweisung verwendet wird. – nik

Antwort

18

Sie können nicht - in C. In C Initialisierung von globalen und lokalen statischen Variablen sind so ausgelegt, dass der Compiler die Werte statisch in den ausführbaren setzen können. Es kann nicht-konstante Ausdrücke als Initialisierer behandeln. Und nur in C99 können Sie nicht-konstanten Ausdruck in Aggregat-Initialisierer verwenden - nicht so in C89!

In Ihrem Fall, da Ihr Array ein Array mit Zeichen ist, muss jedes Element eine arithmetische Konstante Ausdruck sein. Schauen Sie, was sagt es über jene

Einen arithmetischen Konstante Ausdruck arithmetischen Typen haben darf und die nur Operanden, die ganzzahlige Konstanten sind, potenzialfreie Konstanten, Enumerationskonstanten, Charakter Konstanten und sizeof Ausdrücke.

Sicherlich ist dies nicht von Ihrem initializer erfüllt, die einen Operanden von Zeigertyp verwendet. Die andere Möglichkeit besteht darin, Ihr Array mit einem String-Literal zu initialisieren, wie es auch erläutert

Alle Ausdrücke in einem Initialisierer für ein Objekt mit statischer Speicherdauer müssen Konstantenausdrücke oder Zeichenfolgenliterale sein.

Alle Zitate sind aus dem C99 TC3 Ausschussentwurf entnommen. So zu schließen, was Sie tun wollen - mit nicht konstanten Ausdruck - nicht mit C durchgeführt werden kann Sie haben mehrere Möglichkeiten:

  • Schreiben Sie mehrere Male Sachen - einmal umgekehrt, und das andere Mal nicht rückgängig gemacht.
  • Ändern Sie die Sprache - C++ kann das alles tun.
  • Wenn Sie wirklich das Zeug tun wollen, ein Array von char const* anstelle

Hier ist, was ich durch die letzte Option bedeuten

char const c[] = "ABCD"; 
char const *f[] = { &c[0], &c[1], &c[2], &c[3] }; 
char const *g[] = { &c[3], &c[2], &c[1], &c[0] }; 

Das funktioniert gut, als Adresse konstant Ausdruck wird verwendet, um die Zeiger zu initialisieren

Eine Adreßkonstante ist ein Nullzeiger, ein Zeiger auf einen lvalue, der a bezeichnet n Objekt der statischen Speicherdauer oder ein Zeiger auf einen Funktionsbezeichner; Es wird explizit mit dem unären &-Operator oder einer Integer-Konstanten, die in den Zeigertyp umgewandelt wird, oder implizit durch die Verwendung eines Ausdrucks des Array- oder Funktionstyps erstellt. Das Array-Index [] und Member-Zugriff. und -> Operatoren, die Adresse & und Indirection * unäre Operatoren, und Pointercasts können bei der Erzeugung einer Adreßkonstanten verwendet werden, aber der Wert eines Objekts darf nicht durch Verwendung dieser Operatoren erreicht werden.

können Sie Glück haben Ihre Compiler-Optionen zwicken - ein weiteres Zitat:

Eine Implementierung andere Formen der konstanten Ausdrücke annehmen.

+1

+1 große Erklärung und Workaround. –

3

einfach

const char S[] = "ABCD"; 

funktionieren sollte.

Was ist Ihr Compiler?

+0

Beachten Sie, dass dadurch ein Array mit fünf Elementen initialisiert wird. Es gibt auch das \ 0 am Ende. Wenn Sie es nicht wollen, machen Sie es zu einem const char S [sizeof ("ABCD") - 1] = "ABCD" – laalto

+0

Ja, nur die Größe auf 4 wird der Compiler das \ 0 weglassen. Die Wahl hängt davon ab, was Sie eigentlich tun möchten. –

+0

Haben Sie das versucht? Ich habe es mit - ARM ADS 1.2 und gcc (für x86) versucht, und das Ergebnis ist das gleiche: beide Compiler beschweren sich, dass die Eingabe ** nicht ** const ist. –

0

Dies kompiliert gut auf GCC-Version 4.3.3 (Ubuntu 4.3.3-5ubuntu4).

const char s[] = "cheese"; 

int main() 
{ 
    return 0; 
} 
+0

Duh :-) Aber bitte fügen Sie eine Zeile char t [] = {s [0], s [1]}; weil das ist was ich versuche zu tun! –

+0

Arnaud: Also ist dein Problem mit dieser Linie. Warum willst du das machen? Was genau willst du erreichen? –

+1

Ich möchte zwei Char-Arrays haben, mit dem gleichen Inhalt, aber in einer anderen Reihenfolge. Und diese Reihenfolge ist zur Kompilierzeit bekannt, also möchte ich zur Laufzeit kein Shuffling machen! –

-1

Vielleicht muss Ihr Zeichenarray konstant sein. Da Sie Ihr Array mit Zeichen aus einer konstanten Zeichenfolge initialisieren, muss Ihr Array konstant sein. Versuchen Sie folgendes:

#define S "ABCD" 
const char a[] = { S[0], S[1], S[2], S[3] }; 
+0

Danke, aber nein. Ich habe das versucht und den gleichen Fehler bekommen, was logisch ist, weil der Compiler beklagt, dass meine 'Initialisierungselemente' nicht const sind! –

+0

Hm, aber "ABCD" [0] sollte ein const Zeichen zurückgeben, oder? –

+0

Es sollte, deshalb verstehe ich nicht, dass es nicht funktioniert :-) –

0
const char S[] = "ABCD"; 

Diese funktionieren sollte. Ich benutze nur diese Notation und es funktioniert perfekt für mich. Ich weiß nicht, wie du es benutzt.

+0

Anscheinend habe ich meine Frage nicht klar formuliert. Versuchen Sie die folgenden ** zwei ** Zeilen zu kompilieren: const char S [] = "ABCD"; Zeichen t [] = {S [0], S [1]}; –

+0

und was die Notwendigkeit dafür war, char s [] = "ABCD" allein wird nicht für Sie arbeiten? Was ist die genaue Anforderung? –

0

ist hier unklar Lösung: definieren Makrofunktion:

#define Z(x) \ 
     (x==0 ? 'A' : \ 
     (x==1 ? 'B' : \ 
     (x==2 ? 'C' : '\0'))) 

char x[] = { Z(0), Z(1), Z(2) }; 
+0

Verschieben Sie sie außerhalb der Hauptfunktion. Sie werden nicht als globale Variablen funktionieren. –

+0

Es ist genau wie Mehrdad sagt: Mein Problem tritt nicht innerhalb einer Funktion, aber wenn diese Variablen global sind (oder statisch, aber nicht Teil einer Funktion) –

+0

@Mehrdad, @Arnaud: Ok, ich verstehe. Ich habe jetzt die Lösung in eine andere geändert. –

0

Weird-Fehler.

Können Sie das testen?

const char* const S = "ABCD"; 
char t[] = { S[0], S[1], S[2], S[3] }; 
char u[] = { S[3], S[2], S[1], S[0] }; 
+0

Versuchte das schon. Funktioniert auch nicht. –

0

Ich bin nicht sicher, was dein Problem ist, aber das scheint folgende OK zu arbeiten:

#include <stdio.h> 

int main() 
{ 
    const char s0[] = "ABCD"; 
    const char s1[] = { s0[3], s0[2], s0[1], s0[0], 0 }; 

    puts(s0); 
    puts(s1); 
    return 0; 
} 


Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86 
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved. 
cl /Od /D "WIN32" /D "_CONSOLE" /Gm /EHsc /RTC1 /MLd /W3 /c /ZI /TC 
    .\Tmp.c 
Tmp.c 
Linking... 

Build Time 0:02 


C:\Tmp>tmp.exe 
ABCD 
DCBA 

C:\Tmp> 

bearbeiten 9. Juni 2009

Wenn Sie den globalen Zugriff benötigen, müssen Sie möglicherweise etwas hässlich wie folgt:

#include <stdio.h> 

const char *GetString(int bMunged) 
{ 
    static char s0[5] = "ABCD"; 
    static char s1[5]; 

    if (bMunged) { 
     if (!s1[0]) { 
      s1[0] = s0[3]; 
      s1[1] = s0[2]; 
      s1[2] = s0[1]; 
      s1[3] = s0[0]; 
      s1[4] = 0; 
     } 
     return s1; 
    } else { 
     return s0; 
    } 
} 

#define S0 GetString(0) 
#define S1 GetString(1) 

int main() 
{ 
    puts(S0); 
    puts(S1); 
    return 0; 
} 
+0

Es wird nicht funktionieren, wenn s1 global sein wird. –

+0

Diese Antwort wurde bereits versucht :-) Das Problem ist, dass das Array global sein sollte! –

0

Das Kompilierungsproblem tritt nur für mich auf (gcc 4.3, ubuntu 8.10) wenn die drei va rariables sind global.Das Problem ist, dass C nicht wie eine Skriptsprache funktioniert. Sie können also nicht davon ausgehen, dass die Initialisierung von u und t nach der Eins von s erfolgt. Deshalb erhalten Sie einen Kompilierungsfehler. Nun können Sie T und Y nicht wie zuvor initialisieren, deshalb brauchen Sie ein Char *. Der Code, der die Arbeit tun, ist die folgende:

#include <stdio.h> 
#include <stdlib.h> 

#define STR "ABCD" 

const char s[] = STR; 
char* t; 
char* u; 

void init(){ 
    t = malloc(sizeof(STR)-1); 
    t[0] = s[0]; 
    t[1] = s[1]; 
    t[2] = s[2]; 
    t[3] = s[3]; 


    u = malloc(sizeof(STR)-1); 
    u[0] = s[3]; 
    u[1] = s[2]; 
    u[2] = s[1]; 
    u[3] = s[0]; 
} 

int main(void) { 
    init(); 
    puts(t); 
    puts(u); 

    return EXIT_SUCCESS; 
} 
0

Das ist einer der Fälle, in denen ein Skript zum Generieren des entsprechenden Codes hilfreich sein könnte.

2

Eine andere Möglichkeit ist die Verwendung von sprintf.

Zum Beispiel

char buffer[50]; 
sprintf(buffer, "My String"); 

Viel Glück.

Verwandte Themen