Строка C++, сформированная путем копирования индексных символов из другой уже инициализированной строки. Невозможно напечатать недавно сформированную строку, используя cout

В C++ я создал новую строку (класс строки), скопировав символы с указанием индекса из другой строки (класс строки), которая уже была инициализирована.

Но я не могу распечатать эту новую строку на экране, используя cout, С помощью c_str() Я могу распечатать его, используя cout, Но не c_str() нужен только при использовании printf() потому что ему нужна строка типа ac?

#include <cstring>
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

int main() {
    int i;
    string a,b;
    cin>>a;
    for(i=0;a[i]!='\0';i++){
        b[i]=a[i];
    }
    cout<<b;
    return 0;
}

РЕДАКТИРОВАТЬ: Спасибо за помощь! Но, возможно, я не совсем понял свой вопрос, поэтому это основные проблемы, которые у меня есть. Пожалуйста, прочитайте следующее, и если бы вы могли помочь мне дальше, это было бы здорово! (Также я понимаю b=a; это самый простой способ назначить, но я пытаюсь понять строки и, следовательно, вопрос.)

а) я не знаю, когда строка cpp заканчивается нулем, а когда нет, но в этом случае строка после инициализации была нулевой, потому что цикл завершился и закончился после последнего символа строки a, потому что при выходе из цикл и делать cout<<a[i]; последний символ печатается.

б) в цикле, после назначения, когда я включаю cout<<b[i]; он распечатывает ожидаемое нами значение, которое было присвоено b[i]. Так что b [i] существует по какой-то странной причине.

c) Вне цикла for, в конце программы, когда я cout<<b[2]; он печатает третий символ строки. И если я сделаю cout<<b.c_str(); распечатывает всю строку. Это только если я cout<< b; что ничего не печатается. Почему это?

3 ответа

Вы могли заметить, что std::string не ведет себя как обычная строка в стиле C Важно это заметить.

Во-первых, такое прямое назначение не работает. Настоящая причина в том, что это не меняет размер строки. Вы можете сами это выяснить, выведя b.size()или проверяя, что оба b.start() а также b.end() ссылаются на тот же символ, b[0],

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

b.resize(a.size());

Во-вторых, взгляните в свою петлю. Не сравнивать с \0 как будто это была строка в стиле C. Вместо этого проверьте, i < a.size()нет гарантии std::string будет нулевым (\0) прекращено

Что вы действительно должны сделать, тем не менее, это просто назначить a для b, и b будет иметь копию a, как вы и предполагали.

b = a;

Вам нужно выделить место в b прежде чем начать переписывать его символы с помощью b[n], Так b.resize(...) будет необходимо. В противном случае вам нужно добавить каждый символ в конец, используя b += a[i];,

Также std::string не завершены, поэтому, пожалуйста, не проверяйте \0, использовать их size():

Учти это:

int main()
{
    int i;

    string a, b; // these are both empty

    std::cout << "a.size() = " << a.size() << '\n';
    std::cout << "b.size() = " << b.size() << '\n';

    cin >> a; // now a contains something

    std::cout << "a.size() = " << a.size() << '\n';
    std::cout << "b.size() = " << b.size() << '\n';

    // for(i = 0; a[i] != '\0'; i++) // no don't test for null
    // {
    //  b[i] = a[i]; // no b has no spaces
    // }

    for(std::size_t i = 0; i < a.size(); ++i)
        b += a[i]; // increases b's size by one each time

    std::cout << "b.size() = " << b.size() << '\n';

    cout << b;
}

Чтобы ответить на дополнительные вопросы:

а) Это внутренняя деталь реализации, которая std::string теряет силу Дело в том, что завершающий символ null находится за пределами правовых границ общедоступного интерфейса, и это технически "неопределенное поведение" для доступа к нему. Правильный способ найти конец std::string использует его size() функция или ее end() итератор.

б) Чистая удача, если за концом строки выделена память. Даже если там есть память, она не является частью строки и не будет скопирована во время допустимой строковой операции, такой как a = b;,

в) Это совершенно неопределенное поведение. Скорее всего std::cout << b; смотрит на size() строки, которая zero и решает ничего не печатать, потому что size() является zero (см. мой пример). тем не мение c_str() просто возвращает адрес памяти начала строки. Из одного адреса памяти std::cout не может сказать, насколько велика предполагаемая строка. Поэтому он просто печатает символы, пока не найдет ноль. Это чистая удача, если она напечатает то, на что вы надеетесь.

b пустой. Назначение b[i] имеет неопределенное поведение для любого значения i,

a[i]!='\0' условие допустимо только в том случае, если ваш компилятор поддерживает C++11 или более позднюю версию. До C++11 str[str.size()] имеет неопределенное поведение.


Вы можете решить первую проблему, сначала изменив размер b, Если у вас есть поддержка C++11, цикл, основанный на диапазоне, будет намного проще. Если у вас нет C++11, тогда допустимым является следующее:

b.resize(a.size());
for(i=0; i < a.size(); i++)

Хотя писать цикл для копирования строки немного глупо. Вы можете просто использовать назначение:

b = a;

а) я не знаю, когда строка cpp заканчивается нулем, а когда нет, но в этом случае строка после инициализации была нулевой, потому что цикл завершился и закончился после последнего символа строки a, потому что при выходе из цикл и делать cout<<a[i]; последний символ печатается.

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

б) в цикле, после назначения, когда я включаю cout<<b[i]; он распечатывает значение, которое мы ожидаем, было просто присвоено b[i], Так b[i] существует по какой-то странной причине

Это не значит что b[1] "существует". Поведение не определено.

c) Вне цикла for, в конце программы, когда я cout<<b[2]; он печатает третий символ строки. И если я сделаю cout<<b.c_str(); распечатывает всю строку. Это только если я cout<< b; что ничего не печатается. Почему это?

Это потому, что поведение не определено.

Другие вопросы по тегам