Когда мы вставляем строковые значения в список символов по типу символа, почему мы используем длину + 1? - PullRequest
0 голосов
/ 02 мая 2020

Когда я хочу дать ввод от пользователя в виде строки, а затем вставить каждый символ в новый список, я использую следующие команды:

#include <iostream>
#include <string>
#include <cstring>

using  namespace  std;

int main()
{
    string text;
    cout<<"Text: ";
    cin>>text;

    int len = text.length();
    char char_list[len + 1];

    strcpy(char_list, text.c_str());

    cout << char_list << endl;
    return 0;
}

В приведенном выше коде, почему мы используем char char_list[len + 1];? Если я не использую +1, я вижу те же результаты.

Ответы [ 2 ]

2 голосов
/ 02 мая 2020

C строки используют массивы символов с дополнительным специальным нулевым символом для обозначения конца строки. Это называется нулевым терминатором и идет после других символов в строке. Так что в вашем коде char_list есть строка C. Это единственный тип строки, который есть в языке C.

Специальный нулевой символ в строке C - это причина, по которой вам нужно иметь len + 1. +1 должен выделить достаточно места для нулевого символа.

В C ++ существует класс std::string для представления строк, поэтому text является строкой C ++. Но C ++ также может работать со строками C. В целом, в программе на C ++ вы должны предпочитать строки на C ++.

Важным фактом в программировании на C ++ является то, что тот факт, что ваш код работает, не означает, что он правильный. Поэтому, несмотря на то, что на этот раз у вас получилось пропустить +1, в следующий раз он может не сработать. Технический термин для этого - неопределенное поведение , потому что вы пропустили +1, в вашей программе было неопределенное поведение. Неопределенное поведение означает, что может произойти все что угодно, даже работа считается неопределенным поведением, но также происходит сбой или неправильные результаты.

1 голос
/ 02 мая 2020

Для начинающих массивов переменной длины, таких как char_list

int len = text.length();
char char_list[len + 1];

, не является стандартной функцией C ++. Код не будет компилироваться, если использовать компилятор C ++, который не имеет собственного языкового расширения, позволяющего использовать массивы переменной длины.

В этом случае вам следует динамически распределять массив

int len = text.length();
char *char_list = new char[len + 1];

также плохая идея использовать подписанный тип int для хранения объекта целого типа без знака std::string::size_type, который в общем случае может быть слишком большим для хранения в объекте типа int

Вы можете просто написать, используя спецификатор auto

auto len = text.length();
char *char_list = new char[len + 1];

Тем не менее, используемая C строковая функция strcpy копирует символы из исходного массива символов в целевой массив символов до завершающего нулевого символа ' \ 0 'не будет скопировано. То есть символ завершающего нуля '\0' играет роль дозорного значения, которое хранится в строке вместе с другими символами.

Аналогичным образом ведет себя перегруженный оператор <<, когда его аргумент имеет тип char *.

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

Вы можете скопировать исходный объект типа std :: string, исключая завершающий ноль, следующим образом, используя другую строковую функцию strncpy или memcpy

int len = text.length();
char char_list[len];

memcpy(char_list, text.c_str(), len );

Но в этом случае вы не можете использовать оператор <<. Вместо этого вы можете написать </p>

cout.write( char_list, len ) << endl;
...