Как переписать часть строки в C? - PullRequest
0 голосов
/ 28 ноября 2018

У меня есть, например, строка.И я только хочу изменить несколько начальных символов строки и оставить остальные как есть.Каков наилучший способ сделать это в C?

#include <stdio.h>
#include <string.h>

int main() {
    char src[40];
    char src2[40];
    char dest[12];

    memset(dest, '\0', sizeof(dest));
    strcpy(src, "This is a string");
    strcpy(src2, "That");
    strncpy(dest, src, sizeof(src));
    strncpy(dest, src2, sizeof(src2));

    printf("Final copied string : %s\n", dest);
}

Я бы хотел, чтобы строка была изменена с "This is a string" на "That is a string".

Есть ли простой способ выполнитьэто то, что мне не хватает?

Ответы [ 4 ]

0 голосов
/ 28 ноября 2018

Расширяя ответ @dbush:

Я думаю, что код все еще довольно хрупок.

#include <stdio.h>
#include <string.h>

int main() {
    char src[40];
    char src2[40];
    char dest[20];

Здесь создается первая ловушка: dest меньше, чем оба источника.Хотя это может быть обработано, это требует гораздо большего усердия в последующем коде.Было бы лучше сделать место назначения всегда достаточно большим, чтобы вместить источник (и).

memset(dest, '\0', sizeof(dest)); //Good

Но также неплохо инициализировать другие массивы с 0.

memset(src, '\0', sizeof(src));
memset(src2, '\0', sizeof(src2));

Примечание: конечно, вы можете избежать проблем с memset, просто используя синтаксис инициализации массива:

    char src[40] = {0};
    char src2[40] = {0};
    char dest[20] = {0};

Две следующие строки потенциально опасны при условии, что IRLдве строки могут не быть строковыми константами.(И даже тогда!) Проверка длины не предусмотрена ... Лучше:

//    strcpy(src, "This is a string");
//    strcpy(src2, "That");

strncpy(src, "This is a string", sizeof(src)- 1);
strncpy(src2, "That", sizeof(src2) -1);

Таким образом, мы гарантируем, что мы не вызовем переполнения.Мы также следим за тем, чтобы строки в src и src2 правильно заканчивались нулем.

Теперь копирование src / src2 в dest также опасно.Мы должны следить за тем, чтобы не переполнять dest.

//strncpy(dest, src, strlen(src));
//strncpy(dest, src2, strlen(src2));

Лучше:

strncpy(dest, src, sizeof(dest) - 1);
strncpy(dest, "That is a long rubbish string that easily could overflow dest", sizeof(dest) -1);

Мы копируем только столько, сколько dest может удержать и сохранить нулевой терминатор.

Сейчасна замену первых X символов.Опять же, мы должны убедиться, что переполнения не происходит.Мы используем strlen для определения фактического размера строки с нулевым символом в конце в src2, но нам нужно использовать / оценивать максимальный размер dest.Поэтому смесь strlen и sizeof.

memcpy просто для удовольствия.Вы также можете использовать strncpy.

memcpy(dest, src2, strlen(src2) < sizeof(dest) ? strlen(src2) : sizeof(dest));

printf("Final copied string : %s\n", dest);

}

Таким образом, вся безопасная реализация выглядит так:

#include <stdio.h>
#include <string.h>

int main() {
    char src[40] = {0};
    char src2[40] = {0};
    char dest[20] = {0};


    strncpy(src, "This is a string", sizeof(src)- 1);

    strncpy(src2, "That is a long rubbish string and sooooooooooooooooooooooooo much more", sizeof(src2) -1);

    strncpy(dest, src, sizeof(dest) - 1);

    memcpy(dest, src2, strlen(src2) < sizeof(dest) ? strlen(src2) : sizeof(dest));

    printf("Final copied string : %s\n", dest);
}

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

0 голосов
/ 28 ноября 2018

Здесь есть несколько проблем.

Во-первых, dest имеет длину всего 12 байтов, что слишком мало, чтобы содержать "Это строка".Попытка скопировать эту строку в dest приведет к переполнению буфера.Это вызывает неопределенное поведение .Сделайте это по крайней мере 20 байтов.

Секунда sizeof(src) дает вам размер всего массива, который составляет 40, а не длину строки.Это также даст неопределенное поведение, если целевой буфер недостаточно велик.Вместо этого используйте strlen.То же самое относится и к sizeof(src2).

. С этими изменениями вы должны иметь следующее:

#include <stdio.h>
#include <string.h>

int main() {
    char src[40];
    char src2[40];
    char dest[20];

    memset(dest, '\0', sizeof(dest));
    strcpy(src, "This is a string");
    strcpy(src2, "That");
    strncpy(dest, src, strlen(src));
    strncpy(dest, src2, strlen(src2));

    printf("Final copied string : %s\n", dest);
}
0 голосов
/ 28 ноября 2018

Я смущен и немного обеспокоен звонком memset().Вызов memset позволяет использовать strncpy (), не беспокоясь о завершающем '\ 0'.Такой вызов предполагает, что эта логика будет использоваться в функции общего назначения, которая будет вызываться из функции более высокого уровня.

Если это не так, то первый strncpy () должен быть заменен на strcpyи memset должен быть заброшен:

#include <stdio.h>
#include <string.h>

int main() {
    char src[40];
    char src2[40];
    char dest[20];

    /* memset(dest, '\0', sizeof(dest)); -- No need for this */
    strcpy(src, "This is a string");
    strcpy(src2, "That");
    strcpy(dest, src, strlen(src)); /* strcpy will put a '\0' at the end */
    strncpy(dest, src2, strlen(src2));

    printf("Final copied string : %s\n", dest);
}

Однако, если это будет вызвано из функции более высокого уровня, тогда нам действительно нужно проверить длину входящих строк и / или malloc буфер dest иосвободи это.Memset () - это слон в комнате, который предполагает, что есть больше логики, которая должна быть рассмотрена.В противном случае просто замените первый strncpy () на strcpy ().

0 голосов
/ 28 ноября 2018

sizeof(src2) равно 40 (это размер всего массива) - вы, вероятно, имели в виду strlen(src2) (это просто количество символов, используемых для строки):

strncpy(dest, src2, strlen(src2));

ПримечаниеКстати, ваш код имеет проблему переполнения буфера: массив dest недостаточно большой, чтобы вместить полученную строку.Для размещения строки "This is a string" он должен быть не менее 17 символов.Вы также хотите использовать:

strncpy(dest, src, strlen(src));
...