Смена строки функции C с помощью указателя

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

#include  #include  #include  void change(char *a); int main() { char a[] = "hello"; printf("\na = %s", a); change(a); printf("%\na = %s", a); getch(); } void change(char *a) { a = "goodbye"; } 

Несколько проблем с этим кодом, но сначала нам нужно сделать шаг назад и рассказать о том, как массивы обрабатываются на C.

За исключением случаев, когда это операнд операторов sizeof или унарных & или строковый литерал, используемый для инициализации другого массива в объявлении, выражение типа «N-элементный массив из T » будет преобразовано («распад») на выражение типа «указатель на T », а значение выражения будет адресом первого элемента массива.

В декларации

 char a[] = "hello"; 

"hello" – строковый литерал, который имеет тип «6-элементный массив char » (5 символов плюс 0-терминатор). Поскольку он используется для инициализации массива a в объявлении, указанное выше правило не применяется; вместо этого размер a устанавливается равным размеру литерала (6), а содержимое строкового литерала копируется в массив.

Когда вы вызываете change из main как

 change(a); 

выражение a имеет тип «6-элементный массив char ». Так как это ни строковый литерал, ни операнд операторов sizeof или унарных & , это выражение будет преобразовано в тип «указатель на char », а значение выражения будет адресом первого элемента aray. Следовательно, почему функция change объявляется как

 void change(char *a); 

В этом контексте a – просто указатель. Когда вы пишете

 a = "goodbye"; 

строковый литерал "goodbye" не используется в инициализаторе, и он не является операндом операторов sizeof или унарных & , поэтому выражение преобразуется в тип «указатель на char », а значение выражения – это адрес первый символ. Итак, что происходит здесь, так это то, что вы копируете адрес строкового литерала "goodbye" к a . Это перезаписывает значение в a , но это не тот же объект в памяти, что и массив a в main , поэтому любые изменения в нем не отражены в main .

Если вы хотите обновить содержимое массива, вам нужно будет использовать библиотечные функции strcpy/strncpy (для строк с memcpy завершением) или memcpy (для всего остального) или обновить каждый элемент явно ( a[0]='g'; a[1]='o'; a[2]='o'; и т. д.).

Чтобы обновить содержимое a , вы должны использовать

 strcpy( a, "goodbye" ); 

Кроме

a достаточно велик, чтобы удерживать 5 символов плюс 0-терминатор; "goodbye" – 7 символов плюс 0-терминатор; это на два символа больше, чем то, что можно хранить. C happliy позволит вам выполнить операцию и уничтожить байты сразу после a , что может привести к возникновению любого количества проблем (переполнение буфера, такое как classический вредоносный код). На этом этапе у вас есть пара вариантов:

Во-первых, вы можете объявить, a должно быть достаточно большим для обработки любой строки:

 #define MAX_LEN 10 ... char a[MAX_LEN] = "hello"; 

Во-вторых, вы можете ограничить размер строки, скопированной на:

 void change( char *a, size_t size ) { strncpy( a, "goodbye", size - 1 ); a[size - 1] = 0; } 

Обратите внимание, что вам нужно будет передать количество элементов, которые можно сохранить в качестве отдельного параметра, когда вы вызываете change ; нет способа сказать из указателя, насколько большой массив, на который он указывает:

 change( a, sizeof a / sizeof *a ); // although in this case, sizeof a would be // sufficient. 

Основная проблема заключается в том, что вы отправляете копию символа chareur a, делая это:

 void change(char *a) { a = "goodbye"; } 

если вы хотите изменить значение в другой функции, вы должны сделать это:

 #include  #include  #include  void change(char **a); int main() { char *a = "hello"; printf("\na = %s", a); change(&a); printf("%\na = %s", a); getch(); } void change(char **a) { *a = "goodbye"; } 

Я изменил функцию, теперь она работает, таким образом:

 void change(char *a) { strcpy(a, "goodbye"); }