Проблема с указателями C при объединении строк

#c #pointers #concatenation

#c #указатели #объединение

Вопрос:

Я выполняю некоторые упражнения и пытаюсь объединить две строки, используя только указатели (без массивов символов). Кажется, что мой код компилируется (примечание: я использую старый 16-разрядный компилятор Open Watcom):

 #include <stdio.h>

int main(){
  char *str1 = "first";
  char *str2 =" second";

  strcat2(str1,str2);

  for(;*str1!='';str1  ){
      printf(str1);
  }

  return 0;
}

int strcat2(char *s,char *t){
  for(;*s!='';s  ){
    ;
  }

  while((*s   = *t  )!=''){
    ;
  }

  *t  ;
  t='';

  return 0;
}
  

Когда я попытался запустить его, ничего не произошло.
Я уверен, что моя вышеупомянутая работа ужасно ошибочна. Мы будем признательны за любые советы и помощь.

Комментарии:

1. подсказка: где находится пространство для объединения?

Ответ №1:

str1 и str2 , которые вы объявили, являются строковыми литералами, которые не могут быть изменены. В исполняемых файлах Linux содержимое адреса, на который указывает str1 и str2 , хранится в .rodata разделе исполняемого файла, который недоступен для записи. В других исполняемых файлах содержимое хранится в аналогичном месте, которое недоступно для записи. Для выполнения этой работы вы должны использовать массив или динамически выделяемую область памяти. Убедитесь, что при объединении строки, в которую вы вставляете, в другой строке достаточно места для их размещения.

ПРАВКА1:

Либо сделайте

 char str1[BUFF_SIZ] = "Hello", str2[BUFF_SIZ] = " Man";
/* Now do strcat */ 
/* The strlen (str1)   strlen (str2) should be lessthan BUFF_SIZ */
  

или

 char *str1, *str2;
str1 = malloc (sizeof (char) * BUFF_SIZ);
str2 = malloc (sizeof (char) * BUFF_SIZ);
strcpy (str1, "Hello");
strcpy (str2, " Man");
/* Now do strcat */ 
/* The strlen (str1)   strlen (str2) should be lessthan BUFF_SIZ */
  

Комментарии:

1. Вопрос от K amp; R. И в нем конкретно говорится о необходимости объединения строк с использованием указателей.

2. @JJG: Проверьте правку, посмотрите, отвечает ли это на ваш вопрос. То, что вы реализовали, — это использование указателя, но, к сожалению, содержимое адреса указателя не может быть записано в соответствии со стандартами, строковые литералы не могут быть записаны. При использовании динамического выделения памяти память обычно выделяется из кучи, и вы можете ее изменить. Для массива также он хранится внутри стека, в общем случае, который вы можете записать.

3. Сейчас я перевариваю ваш ответ. Кажется, нет способа выполнить strcat для произвольных str1 и str2. Мы должны заранее знать их размер, верно?

4. посмотрите, если две строки имеют длину n каждая, тогда объединение будет максимально, 2n поэтому вы должны сохранить предоставление 2n размера.

5. не следует ли вам скопировать "Man" строку в str2 и также выделить для str2 памяти?

Ответ №2:

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

 char *str1 = "first";
char *str2 =" second";
  

str1 указывает на «first», который находится в постоянной ячейке памяти.

Вместо указателя на строковый литерал у вас должен быть массив символов достаточной емкости для хранения объединенной строки "firstsecond"

Это работает в соответствии с ожиданиями

 #include <stdio.h>
int strcat2(char *s,char *t){    
   for(;*s!='';s  ){
   }
   while((*s   = *t  )!=''){        
   }
   t='';
   return 0;
}
int main(){
  char str1[15] = "first";
  char *str2 =" second";

  strcat2(str1,str2);
  printf("%s",str1);
  return 0;
}   
  

Онлайн-демонстрация здесь

Комментарии:

1. Вопрос взят из знаменитого справочника K amp; R. В упражнении говорится: «Напишите версию функции strcat с указателем … …strcat(s,t) копирует строку t в конец s». Если мой метод изначально ошибочен, как мне это сделать?

2. Спасибо за вашу помощь. У меня есть небольшая оговорка в том, что str1 является предопределенным массивом символов. Такое ощущение, что это противоречит духу вопроса при использовании указателей.

Ответ №3:

цитата из man:strcat:

   char * strcat ( char * destination, const char * source );
  ...
  Parameters
  destination
  Pointer to the destination array, which should contain a C string, and be large enough to contain the concatenated resulting string.
  

Ваша строка назначения не достаточно большая.

Ответ №4:

Вам нужен доступный для записи и достаточно большой буфер для записи, например

 char str1[32] = "first";