strcat_s и проблема новичка с указателем символа
Я делаю простые упражнения с использованием Visual Studio. Используя функцию strcat_s, я получаю исключение нарушения через этот код:
char *str1;
str1 = (char *)malloc(20);
*str1 = "Ciao ";
char *str2 = "Marco";
strcat_s(str1, sizeof(str1), str2);
printf("%s", str1);
Теперь, если я использую предопределенный массив с фиксированным размером, strcat_s работает отлично. Как я могу использовать указатели на char вместо массива, чтобы он работал?
Любое другое решение или совет будет очень признателен.
Заранее спасибо.
2 ответа
Вы должны сначала скопировать строки в выделенную память. Если вам нравится знать длину строки, используйте strlen()
, sizeof()
возвращает размер типа данных в байтах. В вашем случае это указатель (4 байта на 32-битной, 8 байт на 64-битной машине). Следующий код должен работать правильно:
char *str1 = (char *)malloc(20);
strcpy(str1,"Ciao ");
char *str2 = (char *)malloc(20);
strcpy(str2,"Marco ");
strcat(str1, str2);
printf("%s", str1);
Есть некоторые проблемы с вашим кодом, и есть некоторые общие замечания по strcat_s
,
Ваш код str1 = (char *)malloc(20); *str1 = "Ciao "
не копирует Ciao
; *str
это один символ в первой позиции str
и ваше выражение преобразует строковый литерал "Ciao "
(который является указателем на последовательность символов) на некоторый отдельный символ (T
в этом случае; Удивительно, не правда ли?). Нужно было бы использовать strcpy
вместо. Массив, как char buffer[20] = "Ciao "
напротив, работает, потому что этот (особый) случай не является присваиванием, а инициализатором массива.
Ваш код sizeof(str1)
дает размер значения указателя, который, вероятно, 4
или же 8
и не имеет ничего общего с реальным размером содержимого или зарезервированного блока памяти. Надо использовать strlen
вместо.
Что касается strcat_s
Следует учитывать, что он доступен не на всех платформах и что вам нужно знать об его особом поведении. Например, если вы звоните strcat_s(somebuffer, 3, "somestrlongerthan3")
, который превышает максимальную длину 3
как предоставлено, somebuffer
будет "пустой" строкой (т.е. первый символ будет установлен в \0
,
Я бы предложил использовать strncat
или же snprintf
вместо. Смотрите следующие варианты:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main () {
char c = "Ciao "; // Gives a compiler warning and yields 'T'
#define maxlen 20
// Variant 1: start with initialized buffer, yet no "pointer" and dynamic allocation
char resultBuffer[maxlen] = "Ciao ";
size_t charactersRemaining = maxlen-strlen(resultBuffer)-1;
strncat(resultBuffer, "Marco", charactersRemaining);
// Variant 2: use dynamically allocated buffer and snprintf, with constant "Ciao".
char *resultBuffer2 = malloc(maxlen);
const char* second2 = "Marco";
snprintf(resultBuffer2, maxlen, "Ciao %s", second2);
// Variant 3: use dynamically allocated buffer and snprintf, with probably variable "Ciao" and "Marco"
char *resultBuffer3 = malloc(maxlen);
const char* first3 = "Ciao";
const char* second3 = "Marco";
snprintf(resultBuffer3, maxlen, "%s %s", first3, second3);
return 0;
}