У меня возникли проблемы с заменой строки в массиве строк в C.
В принципе, у меня есть:
char * words[3];
Теперь предположим, что там есть строки «кошка», «собака», «птица».
Теперь у меня есть символьное слово [], содержащее слово «мышь», и я хочу заменить в массиве «собака» на «мышь».
Я пробовал использовать strcpy(words[2], word);, но это не работает должным образом, и я предполагаю, что это потому, что длина мыши больше, чем у собаки. Итак, мне интересно, как бы вы выполнили эту задачу в этой ситуации.
Заранее благодарю за любую помощь
Проблема в том, что char * words[3]; объявляет не массив строк, а массив указателей. Массив из трех строк будет выглядеть примерно так: char words[3][100];, где каждая строка имеет максимальную длину 99 символов (плюс обязательный терминатор nul). Что вы хотите: массив строк или массив указателей?
Я думаю, вы имели в виду strcpy(words[1], word);? Вы можете назначить words[1] = word; (words[1] — это всего лишь указатель), но убедитесь, что вы не используете words[1] после окончания срока действия word.
Вам следует дополнить этот вопрос кодом, показывающим, как вы присваиваете начальные значения words, поскольку это позволит раскрыть информацию о ситуации. Похоже, вы только учитесь обработке строк в C, и вам предстоит обсудить множество вопросов: различия между копированием строк и копированием указателей на них, обеспечение достаточного места для строки и многое другое. Кроме того, никогда не описывайте проблему просто как «это работает не так, как ожидалось». Всегда описывайте, что произошло на самом деле и чего вы ожидали.



Следующий код показывает один из способов сделать это. Обратите внимание, что мы предоставляем достаточно места (10 символов) для будущей «мыши» strcpy(). Это важный момент, поскольку исходное объявление:
char * words[3];
... место выделяется только для трех указателей типа char. Вы не можете безопасно использовать strcpy() для этих указателей, даже если они инициализированы строками в объявлении.
#include <stdio.h>
#include <string.h>
/* A multi-dimensional array with enough space for 3 strings
of 9 characters each -- plus the terminating NUL ('\0') for
each string. (3x10) We can safely strcpy() "mouse" to an
array like this.*/
char words[3][10] = {"cat", "dog", "bird"};
char word[] = "mouse";
int main()
{
int iii;
for(iii = 0; iii < 3; iii++)
printf("%s\n", words[iii]);
strcpy(words[2], word);
printf("\n");
for(iii = 0; iii < 3; iii++)
printf("%s\n", words[iii]);
return 0;
}
Выход:
cat
dog
bird
cat
dog
mouse
Работоспособный код здесь
Код без объяснений не является хорошим ответом, и этот код меняет определение вопроса words, не обсуждая последствия.
Привет @Eric Postpischil! Ты пропустил мой комментарий? На этот раз я решил, что лучше включить мое объяснение в виде комментария, чтобы его можно было разместить рядом с определением массива... спасибо
Краткого комментария недостаточно для обсуждения последствий изменения, которые включают проблемы времени жизни, различия между копированием содержимого строки и копированием указателя на строку и многое другое. Это не очень хороший ответ. Честно говоря, это отчасти потому, что это не очень хороший вопрос; это оставляет слишком много вещей открытыми. Но в этом случае от хорошего ответа зависит решение множества проблем, которые студент будет изучать на этом этапе.
@Eric Postpischil - большое спасибо, что нашли время научить меня этому. Отмеченный. Спасибо еще раз.
@user3386109 user3386109 - спасибо за редактирование, которое поможет лучше соответствовать моему комментарию в качестве объяснения. Буду иметь в виду для будущих постов. Спасибо еще раз.
#include <stdio.h>
int main(void) {
char* words[3] = {"cat", "dog", "bird"};
printf("The Initial List\n");
for(int i=0; i<3; ++i)
{
printf("%d : %s\n", i, words[i]);
}
// Replace the middle entry
char* replacement = "mouse";
words[1] = replacement;
printf("The Final List\n");
for(int i=0; i<3; ++i)
{
printf("%d : %s\n", i, words[i]);
}
return 0;
}
Success #stdin #stdout 0.01s 5464KB
The Initial List
0 : cat
1 : dog
2 : bird
The Final List
0 : cat
1 : mouse
2 : bird
Код без объяснения не является хорошим ответом. По этому вопросу следует обсудить вопросы времени жизни и строковых литералов в сравнении с выделенным пространством.
Вы правы: увеличить размер строки невозможно, поскольку каждый указатель в массиве указывает на константную строку. Вот как вы можете визуализировать структуру памяти:
Вы можете объявить свой массив таким образом, чтобы обеспечить достаточно места для каждой строки, т.е.
char words[3][256] = {"cat", "dog", "bird"};
Фактически, поскольку это константы, массив должен быть объявлен как const, и вам следует избегать изменения этих строк в реальной программе.
Если бы массив был объявлен так, как вы показываете, char words[3][256], то его объявление const, как вы предлагаете, сделало бы невозможным выполнить то, что требует вопрос, заменив одну из строк.
А именно: «вам следует избегать изменения этих строк в реальной программе».
Да, вы говорите ОП избегать изменения строк, но это не меняет того факта, что использование const не даст решения их запроса. Они попросили помочь заменить струну, но использование const делает это невозможным. Массив не следует объявлять const, поскольку его содержимое не должно быть постоянным. (Кроме того, их инициализация строковыми литералами не делает их константами.)
Этот код:
char * words[3];
words[0] = "cat";
words[1] = "dog";
words[2] = "bird";
... примерно эквивалентно:
// Internal memory you can't see:
char _string1[] = {'c','a','t','\0'} // Address 0x001234
char _string2[] = {'d','o','g','\0'} // Address 0x001238
char _string3[] = {'b','i','r','d','\0'} // Address 0x001242
// Your program memory:
char * words[3];
words[0] = (char *)0x001234;
words[1] = (char *)0x001238;
words[2] = (char *)0x001242;
Важно то, что char * s — это не то же самое, что char s[], поэтому попытка скопировать «мышь» по адресу 0x001238 не даст того, что вы хотите.
Учитывая char word[] = "mouse";, word имеет адрес, поэтому вы можете назначить его, как в word[1] = word;, и это будет работать. Конечно, если вы измените word[0] = 'h'; на «дом», тогда word[1] тоже будет «дом».
Если для вас это не проблема, то ничего страшного, иначе вам нужно, чтобы words был массивом символов, а не массивом указателей, и убедитесь, что символов достаточно для хранения всех нужных вам слов. Поскольку большинство слов будут короче, многие символы останутся неиспользованными, но обычно это не является большой проблемой.
В противном случае вам придется использовать malloc(), free(), strdup() и так далее для управления памятью, а это усложняется, поэтому лучше избегать этого, если только вам это действительно не нужно.
как инициализировать массив слов?