#include <iostream>
using namespace std
#include <string.h>
int main(){
char token[] = "some random string";
char c[23];
strcpy( c, token);
strncpy(c, token, 5);
c[strlen(c)] = '\0';
cout<<c;
return 0 ;
}
Мой вывод: some random string
, Но я ожидаю, что это будет: some
, Может кто-нибудь объяснить, почему он так себя ведет?
Я думаю, что ваш вывод должен быть «какой-то случайной строкой», потому что ваши две строки кода ничего не делают, смотрите комментарий.
int main(){
char token[] = "some random string";
char c[23];
strcpy( c, token);
strncpy(c, token, 5); // Does nothing
c[strlen(c)] = '\0'; // Does nothing
cout<<c;
return 0 ;
}
Если вы хотите вывести «some», вы можете сделать это:
strncpy(c, token, 5);
c[5] = '\0';
strncpy () не добавляет автоматически завершающуюся ‘\ 0’ в строку dest. Если длина исходной строки больше, чем len (3-й аргумент strncpy), тогда символы len копируются в dest без завершающего символа ‘\ 0’. Таким образом, вы должны явно указывать завершающий символ ‘\ 0’ по коду.
Это работает просто отлично — имейте в виду, что strncpy
не обязательно завершать строку нулем. Когда вы делаете это:
strncpy(c, token, 5);
Копирует первые 5 байтов token
в c
но не заканчивает нулем результат. Кроме того, эта строка бесполезна:
c[strlen(c)] = '\0';
strlen(c)
ищет существующий нулевой терминатор, и как только вы его найдете, вы перезаписываете его другим нулевым терминатором, который не имеет смысла.
В новом коде strncpy
должен редко, если вообще использоваться. Его предполагаемое использование (буферы фиксированной длины, которые не обязательно заканчиваются нулем) давно устарело. Предпочитаю вместо функции, как strlcpy
(нота: strlcpy
не является стандартным; это доступно только в BSD-подобных системах).
Или, если вы пишете код на C ++ вместо чистого C, просто используйте std::string
и вообще избегайте таких хитрых вопросов.
Вам нужно завершить нулем после слова «some» вместо завершения нулем после всей строки. strncpy скопирует «some» в c, но это не обязательно завершит вашу строку null (см. man-страницу для strncpy)
c[4] = '\0'
Как уже упоминали другие, в отличие от snprintf
в sprintf
, strncpy
не безопасная версия strcpy
, Это просто гарантирует, что «ровно N символов будут скопированы в место назначения (используйте NUL, если исходная строка короче, чем N)». (справочная страница)
Но я думаю, что вы уже заметили, что по линии
c[strlen(c)] = '\0';
Это означало обеспечить нулевое прекращение c
, Но это на самом деле бессмысленно, так как strlen
использует NUL для определения длины c
, Так что эта строка едва ли означает «найти NUL и написать NUL в это место».
Важность strncpy
это скопировать определенную часть строки. Это не исправление strcpy
и существовало до введения snprintf
функции.