2016-09-28 1 views
0

В C++ я создал новую строку (строковый класс), скопировав символы index wise из другой строки (string class), которая была уже инициализирована.C++ строка, сформированная путем копирования указательных мудрых символов из другой уже инициализированной строки. Не удалось напечатать новообразованную строку с помощью cout

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

#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; 
} 

EDIT: Спасибо за помощь! Но я, возможно, не был вполне ясен в своем вопросе, так что это основные проблемы, которые у меня есть. PLease прочитал следующее, и если бы вы могли помочь мне дальше, это было бы здорово! (Кроме того, я понимаю, что b=a; - это самый простой способ назначить, но я пытаюсь понять строки и, следовательно, вопрос.)

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

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

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

+0

СТАНД :: строка не является (!), Оканчивающихся нулем C-строка Это может или не может содержать символ «\ 0» (даже в середине), –

+0

... ваш цикл неправильно –

+4

Вы mistyped 'b = a;'. – LogicStuff

ответ

1

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; 

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

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

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

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

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

Это связано с тем, что поведение не определено.

+0

Спасибо за помощь, но, пожалуйста, проверьте править – Zag

+0

@Zag см. Мои ответы на ваши изменения. – user2079303

2

Вам необходимо выделить место в 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; 
} 

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

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

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

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

+0

Спасибо за помощь, но, пожалуйста, проверьте править – Zag

+0

@ Zag Я отредактировал свой ответ, чтобы ответить на ваши дополнительные вопросы, насколько мог. – Galik

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 будет null (\0) завершено.

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

b = a; 
+0

Спасибо за помощь, но, пожалуйста, проверьте правильность! – Zag