Как инициализировать массив символов из строки - PullRequest
15 голосов
/ 08 июня 2009

Я хочу сделать следующее

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

Но я не хочу писать эти символы отдельно. Я хочу что-то вроде

#define S "ABCD"

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

Но это не скомпилируется (gcc говорит, что элемент инициализатора не является константой).

Я попытался заменить строку #define на

const char S[] = "ABCD";

Но это, похоже, не помогает.

Как я могу сделать это (или что-то подобное), которое позволит мне написать «ABCD» как обычную «строку», а не как четыре отдельных символа?

P.S. Кажется, что люди не правильно читают вопрос ...

Я не могу получить следующий код для компиляции:

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

Ответы [ 11 ]

18 голосов
/ 08 июня 2009

Вы не можете - в C. В C инициализация глобальных и локальных статических переменных разработана так, что компилятор может статически помещать значения в исполняемый файл. Он не может обрабатывать неконстантные выражения как инициализаторы. И только в C99 вы можете использовать непостоянное выражение в агрегатных инициализаторах - не так в C89!

В вашем случае, поскольку ваш массив - это массив, содержащий символы, каждый элемент должен быть выражением арифметической константы. Посмотрите, что это говорит о тех

Арифметическое константное выражение должно иметь арифметический тип и должно иметь только операнды, которые являются целочисленными константами, плавающими константами, константами перечисления, символом константы и размер выражений.

Конечно, это не удовлетворяет ваш инициализатор, который использует операнд типа указателя. Конечно, другой способ - инициализировать ваш массив с использованием строкового литерала, как это также объясняется

Все выражения в инициализаторе для объекта со статической продолжительностью хранения должны быть константными выражениями или строковыми литералами.

Все цитаты взяты из проекта комитета C99 TC3. Итак, чтобы сделать вывод, что вы хотите сделать - используя неконстантное выражение - нельзя сделать с C. У вас есть несколько вариантов:

  • Пишите свои вещи несколько раз - один раз в обратном порядке, а другой раз не в обратном порядке.
  • Изменить язык - C ++ может сделать все это.
  • Если вы действительно хотите сделать это, используйте массив char const* вместо

Вот что я имею в виду под последним вариантом

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] };

Это отлично работает, так как выражение константы адреса используется для инициализации указателей

Константа адреса - это нулевой указатель, указатель на l-значение, обозначающее объект статической длительности хранения, или указатель на указатель функции; он должен быть создан явно с использованием унарного оператора & или целочисленной константы, приведенной к типу указателя, или неявно с помощью выражения массива или типа функции. Массив-индекс [] и членский доступ. и -> операторы, унарные операторы адреса и косвенности * и приведение указателей могут использоваться при создании адресной константы, но при использовании этих операторов значение объекта не должно быть доступно.

Возможно, вам повезет с настройкой параметров компилятора - еще одна цитата:

Реализация может принимать другие формы константных выражений.

5 голосов
/ 08 июня 2009

Просто

const char S[] = "ABCD";

должно работать.

Какой у тебя компилятор?

3 голосов
/ 31 октября 2012

Другой вариант - использовать sprintf.

Например,

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

Удачи.

0 голосов
/ 08 июня 2009

Это один из случаев, когда скрипт для генерации соответствующего кода может помочь.

0 голосов
/ 08 июня 2009

Проблема компиляции возникает только для меня (gcc 4.3, ubuntu 8.10), если три переменные являются глобальными. Проблема в том, что C не работает как скриптовые языки, поэтому вы не можете считать само собой разумеющимся, что инициализация u и t происходит после одной из s. Вот почему вы получаете ошибку компиляции. Теперь вы не можете инициализировать t и y так, как вы это делали раньше, поэтому вам понадобится символ *. Код, который выполняет работу, следующий:

#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 голосов
/ 08 июня 2009

Я не уверен, в чем ваша проблема, но, кажется, следующее работает хорошо:

#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>

Редактировать 9 июня 2009 г.

Если вам нужен глобальный доступ, вам может понадобиться что-то ужасное:

#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 голосов
/ 08 июня 2009

Странная ошибка.

Можете ли вы проверить это?

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 голосов
/ 08 июня 2009

Вот неясное решение: определить макрос-функцию:

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

char x[] = { Z(0), Z(1), Z(2) };
0 голосов
/ 08 июня 2009
const char S[] = "ABCD";

Это должно работать. Я использую только эту запись, и она прекрасно работает для меня. Я не знаю, как вы используете.

0 голосов
/ 08 июня 2009

Возможно, ваш массив символов должен быть постоянным. Поскольку вы инициализируете свой массив символами из константной строки, ваш массив должен быть постоянным. Попробуйте это:

#define S "ABCD"
const char a[] = { S[0], S[1], S[2], S[3] };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...