2010-02-16 2 views
2
char sXSongBuffer[20][30]; 
sXSongBuffer = {"Thriller", "Don't Stop Till You Get Enough", "Billy Jean"}; 

Почему это возвращает ошибку expected expression before ‘{’ token? Поэтому я хочу, чтобы инициализировать мой массив, как это так, что я могу изменить его содержание, как это позже:Почему я не могу инициализировать массив cstrings, как это?

sXSongBuffer = {"New Song", "More Music From Me"}; 

ответ

6

Вы не можете назначать массивы в C. C позволяет использовать alizing массивы со значениями, которые являются константами времени компиляции. Если вы хотите позже изменить значения или установить значения, которые не являются константами времени компиляции, вы должны назначить конкретный индекс массива вручную.

Итак, ваше назначение sXSongBuffer отвергается в С. Кроме того, поскольку sXSongBuffer[0]sXSongBuffer[19] в массивы тоже, вы не можете даже сказать: sXSongBuffer[0] = "New Song";

В зависимости от того, что вы хотите, это может работать для вас:

/* declare sXSongBuffer as an array of pointers */ 
char *sXSongBuffer[30] = { 
    "Thriller", 
    "Don't Stop Till You Get Enough", 
    "Billy Jean", 
    NULL /* set the rest of the elements to NULL */ 
}; 
size_t i; 
/* and then later in your code */ 
sXSongBuffer[0] = "New Song"; 
sXSongBuffer[1] = "More Music From Me"; 
for (i=2; i < sizeof sXSongBuffer; ++i) 
    sXSongBuffer[i] = NULL; 

Но вышеизложенное работает только в том случае, если вы знаете все свои строки во время компиляции. Если нет, вам нужно будет решить, хотите ли вы «большие» массивы, или если вам нужна динамическая память для строк и/или количество строк. В обоих случаях вам понадобится использовать эквивалент strcpy() для копирования строк.

Редактировать: Для того, чтобы ответить на комментарий:

Вы объявляя массив из 30 символьных указателей с первые три элемента, указывающие на буферы размер строки, то есть положительный эффект, на который указывает sXSongBuffer[0] не будет содержать ничью, превышающую "Thriller", и если он делает sXSongBuffer[0] = malloc(32); Он получит небольшой кусочек памяти. Кроме того, ему понадобится память malloc для каждого из остальных слотов в массиве. Он должен либо использовать 2d char массивы, как в OP + назначенный init, или malloc каждый буфер во время выполнения и копировать в значениях. Ему также нужно запомнить free любую память, которую он malloc s.

sXSongBuffer в char *sXSongBuffer[30]; представляет собой массив размером 30, причем каждый элемент будучи char *, указатель на char. Когда я это сделаю:

char *sXSongBuffer[30]; 

каждый из этих 30 указателей неинициализирован.Когда я это сделаю:

char *sXSongBuffer[30] = { "Thriller", ... }; 

Я установил указатели в разные точки только для чтения. Нет ничего, что мешало бы мне затем «переназначить» указатели где-то в другом месте. Это как если бы я был:

char *data = "Hello"; 
printf("%s\n", data); 
data = "Hello, world"; 
printf("%s\n", data); 

В приведенном выше фрагменте кода, я назначу data к "Hello" первым, а затем изменить его, чтобы указать на более длинной строки позже. Код, который у меня был выше в моем ответе, сделал не более, чем переназначение sXSongBuffer[i] на что-то еще позже, а так как sXSongBuffer[i] - это указатель, назначение в порядке. В частности, sXSongBuffer[0] является char * и может указывать на любое допустимое местоположение, в котором есть char.

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

+0

Вы объявляете массив из 30 указателей с тремя первыми элементами, указывающими на буферизацию размера строк, то есть бафф, на который указывает 'sXSongBuffer [0]', не будет содержать строку больше, чем «Thriller», и если он делает 'sXSongBuffer [0] = malloc (32);' Он получит небольшой лук-пойнт памяти. Кроме того, он должен будет хранить память для каждого из остальных слотов в массиве. Он должен либо использовать 2d char массивы, как в OP + назначенный init, либо malloc каждый буфер во время выполнения и копировать в значениях. Он также должен помнить, чтобы освободить любую память, которую он mallocs. –

+0

@Robert: см. Мое редактирование. –

0

C не имеет общего назначения литералов массива. Синтаксис списка {} работает только при инициализации, т. Е. При назначении значения в том же самом заявлении, который объявляет переменную.

0

Вы не можете просто написать

char sXSongBuffer[20][30]; 
sXSongBuffer = {"Thriller", "Don't Stop Till You Get Enough", "Billy Jean"}; 

Вы должны либо инициализировать массив сразу (но это будет containt всего 3 статей):

char * sXSongBuffer[]= {"Thriller", "Don't Stop Till You Get Enough", "Billy Jean"}; 

Или использовать либо stnrcpy по каждому пункту:

char sXSongBuffer[20][30]; 
strncpy(sXSongBuffer[0],"Thriller",29); 
strncpy(sXSongBuffer[1],"Don't Stop Till You Get Enough",29); 
strncpy(sXSongBuffer[2],"Billy Jean",29); 
+0

Он может использовать назначенный инициализатор, чтобы получить эффект, что он хочет. –

0

Посмотрите на Designated Initializers.

#include <stdio.h> 

int main (void) { 

    char a[6][6] = { [2] = "foo", [4] = "bar" }; 

    for (int i=0; i<6; ++i) 
     printf("%d == %s\n", i, a[i]); 

    return 0; 
} 

Это c99-функция. Компиляция с:

gcc -W -std=c99 2dInit.c -o 2dInit 

Воспроизводит:

0 == 
1 == 
2 == foo 
3 == 
4 == bar 
5 == 

В вашем случае, если вы хотите сделать:

char sXSongBuffer[20][30] = { 
    [0] = "Thriller", 
    [1] = "Don't Stop Till You Get Enough", 
    [2] = "Billy Jean" 
}; 
Смежные вопросы