Присвоение строк массивам символов
Я немного удивлен следующим.
Пример 1:
char s[100] = "abcd"; // declare and initialize - WORKS
Пример 2:
char s[100]; // declare
s = "hello"; // initalize - DOESN'T WORK ('lvalue required' error)
Мне интересно, почему второй подход не работает. Кажется естественным, что он должен (он работает с другими типами данных)? Может ли кто-нибудь объяснить мне логику этого?
Ответы
Ответ 1
При инициализации массива C позволяет вам заполнить его значениями. Так
char s[100] = "abcd";
в основном так же, как
int s[3] = { 1, 2, 3 };
но это не позволяет вам выполнять присваивание, так как s
является массивом, а не свободным указателем. Значение
s = "abcd"
это присвоить s
значение указателя abcd
но вы не можете изменить s
так как ничто не будет указывать на массив.
Это может работать и работает, если s
является char*
- указателем, который может указывать на что угодно.
Если вы хотите скопировать строку, просто используйте strcpy
.
Ответ 2
В Си нет такой вещи, как "строка". В Си строки - это одномерный массив char
, заканчивающийся нулевым символом \0
. Поскольку вы не можете назначать массивы в C, вы также не можете назначать строки. Литерал "привет" является синтаксическим сахаром для const char x[] = {'h','e','l','l','o','\0'};
Правильный путь будет:
char s[100];
strncpy(s, "hello", 100);
или еще лучше:
#define STRMAX 100
char s[STRMAX];
size_t len;
len = strncpy(s, "hello", STRMAX);
Ответ 3
Инициализация и назначение - это две различные операции, которые используют один и тот же оператор ( "=" ) здесь.
Ответ 4
1 char s[100];
2 s = "hello";
В приведенном примере s фактически инициализируется в строке 1, а не в строке 2. Даже если вы не присвоили ему значение явно в этот момент, компилятор сделал. На строке 2 вы выполняете операцию присваивания, и вы не можете назначить один массив символов другому массиву символов, подобных этому. Вам нужно будет использовать strcpy() или какой-то цикл для назначения каждого элемента массива.
Ответ 5
Чтобы расширить на ответ Sparr
Инициализация и назначение - это две различные операции, которые используют один и тот же оператор ( "=" ) здесь.
Подумайте об этом так:
Предположим, что есть 2 функции, называемые InitializeObject
и AssignObject
. Когда компилятор видит thing = value
, он просматривает контекст и вызывает один InitializeObject
, если вы создаете новый thing
. Если вы этого не сделаете, вместо этого он называет AssignObject
.
Обычно это нормально, поскольку InitializeObject
и AssignObject
обычно ведут себя одинаково. За исключением случаев использования массивов char (и нескольких других случаев краев), в этом случае они ведут себя по-разному. Зачем это делать? Хорошо, что целая другая статья связана с стеком против кучи и т.д. И т.д.
PS: В стороне, думая об этом таким образом, также поможет понять конструкторы копирования и другие подобные вещи, если вы когда-нибудь захотите в С++
Ответ 6
Обратите внимание, что вы все еще можете сделать:
s[0] = 'h';
s[1] = 'e';
s[2] = 'l';
s[3] = 'l';
s[4] = 'o';
s[5] = '\0';
Ответ 7
Я знаю, что на этот вопрос уже дан ответ, но я хотел бы поделиться ответом, который я дал кому-то, кто задал очень похожий вопрос в группе C/C++ в Facebook.
Массивы не имеют функций оператора присваивания *. Это означает, что вы не можете просто присвоить массив символов строковому литералу. Зачем? Потому что сам массив не имеет оператора присваивания. (* Это константный указатель, который нельзя изменить.)
массивы - это просто область смежной выделенной памяти, а имя массива фактически является указателем на первый элемент массива. (Цитата из https://www.quora.com/Can-we-copy-an-array-using-an-assignment-operator)
Чтобы скопировать строковый литерал (такой как "Hello world"
или "abcd"
) в ваш массив char, вы должны вручную скопировать все элементы char строкового литерала в массив.
char s[100];
Это инициализирует пустой массив длиной 100.
Теперь, чтобы скопировать строковый литерал в этот массив, используйте strcpy
strcpy(s, "abcd");
Это скопирует содержимое строкового литерала "abcd"
и скопирует его в массив s[100]
.
Вот отличный пример того, что он делает:
int i = 0; //start at 0
do {
s[i] = ("Hello World")[i]; //assign s[i] to the string literal index i
} while(s[i++]); //continue the loop until the last char is null
Очевидно, вы должны использовать strcpy
вместо этого пользовательского строкового литерального копира, но это хороший пример, который объясняет, как работает strcpy
.
Надеюсь это поможет!
Ответ 8
Вы можете использовать это:
yylval.sval=strdup("VHDL + Volcal trance...");
Где
yylval - char *. strdup от выполнения задания.
Ответ 9
Я бы использовал
char *s = "abcd";