Строка 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;
что ничего не печатается. Почему это?
Это потому, что поведение не определено.