Замена строки в массиве строк в C

У меня возникли проблемы с заменой строки в массиве строк в C.

В принципе, у меня есть:

char * words[3];

Теперь предположим, что там есть строки «кошка», «собака», «птица».

Теперь у меня есть символьное слово [], содержащее слово «мышь», и я хочу заменить в массиве «собака» на «мышь».

Я пробовал использовать strcpy(words[2], word);, но это не работает должным образом, и я предполагаю, что это потому, что длина мыши больше, чем у собаки. Итак, мне интересно, как бы вы выполнили эту задачу в этой ситуации.

Заранее благодарю за любую помощь

как инициализировать массив слов?

Iłya Bursov 06.10.2023 18:26

Проблема в том, что char * words[3]; объявляет не массив строк, а массив указателей. Массив из трех строк будет выглядеть примерно так: char words[3][100];, где каждая строка имеет максимальную длину 99 символов (плюс обязательный терминатор nul). Что вы хотите: массив строк или массив указателей?

Adrian Mole 06.10.2023 18:31

Я думаю, вы имели в виду strcpy(words[1], word);? Вы можете назначить words[1] = word; (words[1] — это всего лишь указатель), но убедитесь, что вы не используете words[1] после окончания срока действия word.

Ian Abbott 06.10.2023 18:44

Вам следует дополнить этот вопрос кодом, показывающим, как вы присваиваете начальные значения words, поскольку это позволит раскрыть информацию о ситуации. Похоже, вы только учитесь обработке строк в C, и вам предстоит обсудить множество вопросов: различия между копированием строк и копированием указателей на них, обеспечение достаточного места для строки и многое другое. Кроме того, никогда не описывайте проблему просто как «это работает не так, как ожидалось». Всегда описывайте, что произошло на самом деле и чего вы ожидали.

Eric Postpischil 06.10.2023 19:39
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
3
4
129
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Следующий код показывает один из способов сделать это. Обратите внимание, что мы предоставляем достаточно места (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

Работоспособный код здесь

Kz2023 06.10.2023 18:36

Код без объяснений не является хорошим ответом, и этот код меняет определение вопроса words, не обсуждая последствия.

Eric Postpischil 06.10.2023 18:47

Привет @Eric Postpischil! Ты пропустил мой комментарий? На этот раз я решил, что лучше включить мое объяснение в виде комментария, чтобы его можно было разместить рядом с определением массива... спасибо

Kz2023 06.10.2023 18:49

Краткого комментария недостаточно для обсуждения последствий изменения, которые включают проблемы времени жизни, различия между копированием содержимого строки и копированием указателя на строку и многое другое. Это не очень хороший ответ. Честно говоря, это отчасти потому, что это не очень хороший вопрос; это оставляет слишком много вещей открытыми. Но в этом случае от хорошего ответа зависит решение множества проблем, которые студент будет изучать на этом этапе.

Eric Postpischil 06.10.2023 18:55

@Eric Postpischil - большое спасибо, что нашли время научить меня этому. Отмеченный. Спасибо еще раз.

Kz2023 06.10.2023 18:57

@user3386109 user3386109 - спасибо за редактирование, которое поможет лучше соответствовать моему комментарию в качестве объяснения. Буду иметь в виду для будущих постов. Спасибо еще раз.

Kz2023 06.10.2023 19:05
Ответ принят как подходящий
#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

Код без объяснения не является хорошим ответом. По этому вопросу следует обсудить вопросы времени жизни и строковых литералов в сравнении с выделенным пространством.

Eric Postpischil 06.10.2023 18:45

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

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

char words[3][256] = {"cat", "dog", "bird"};

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

Если бы массив был объявлен так, как вы показываете, char words[3][256], то его объявление const, как вы предлагаете, сделало бы невозможным выполнить то, что требует вопрос, заменив одну из строк.

Eric Postpischil 06.10.2023 18:57

А именно: «вам следует избегать изменения этих строк в реальной программе».

dieter 08.10.2023 01:41

Да, вы говорите ОП избегать изменения строк, но это не меняет того факта, что использование const не даст решения их запроса. Они попросили помочь заменить струну, но использование const делает это невозможным. Массив не следует объявлять const, поскольку его содержимое не должно быть постоянным. (Кроме того, их инициализация строковыми литералами не делает их константами.)

Eric Postpischil 08.10.2023 02:22

Этот код:

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() и так далее для управления памятью, а это усложняется, поэтому лучше избегать этого, если только вам это действительно не нужно.

Другие вопросы по теме