#c
#c
Вопрос:
похоже, что когда я cout * cp, он выводит только первую букву строки, и после того, как я помещаю их в vector, мой вывод остается пустым. что я делаю не так?
//write a program to assign the elements from a list of char* pointers to c-style character strings to a vector of strings
#include <iostream>
#include <cstring>
#include <vector>
#include <list>
#include <string>
using namespace std;
int main ()
{
list<const char*> clist;
cout<<"please enter a string"<<endl;
for(string s; getline(cin,s); )
{
const char* cp=s.c_str();
clist.push_back(cp);
cout<<*cp;
}
cout<<*clist.begin();
vector<string> svec;
svec.assign(clist.begin(),clist.end());
for(vector<string>::iterator iter=svec.begin(); iter!=svec.end(); iter)
cout<<*iter<<endl;
return 0;
}
Комментарии:
1. codereview.stackexchange.com вместо тегирования. Хотя на самом деле это не вопрос CR.
2.
cout<<*cp;
когда вы разыменовываетеcp
переменную (используя*
оператор), вы получаете один символ из вашей строки. Следовательно, чтобы напечатать всю строку целиком, вы должны передать фактический указатель, например:cout << cp;
. Тем не менее, вы должны использоватьstd::string
, а не голые указатели .3. Что натолкнуло вас на мысль, что вы должны использовать указатели? Если вы новичок в C , вам может понравиться рассмотреть это псевдо-правило: «Если вы используете указатель, вы делаете это неправильно».
4. Вы также копируете внутренний указатель строки и не создаете полную копию при возврате в clist. Указатель, который у вас там есть, не будет действительным после следующего цикла, поскольку вы снова читаете обратно в s, возможно, перераспределяя этот буфер.
Ответ №1:
При этом будет напечатана вся строка:
cout << cp; // You're providing cout a const char *
При этом будет напечатан только один символ:
cout << *cp; // You're providing cout a char
Что касается того, что не так с вашим вектором, вы храните только указатели на строки, а не сами строки. Объем памяти для строки вышел за пределы области видимости. Как уже говорили другие, используйте std::string
вместо raw const char *
.
Комментарии:
1. ах да. как насчет нижней части, где я хочу присвоить символы char * вектору строк
2. Я хочу просто использовать строки. это просто вопрос из книги. Я пытаюсь выяснить, как присвоить список символов * вектору строк.
Ответ №2:
cout *cp, он выводит только первую букву строки
Ну, *cp
это символ (тот, который находится в местоположении, на которое указывает указатель cp
). Так что, да, так и будет.
после того, как я поместил их в вектор, мой вывод пустой
К сожалению, ваша программа не завершилась сбоем сразу, поскольку указатели в вашем списке становятся висячими указателями почти сразу после их сохранения.
Сохраняйте std::string
s с самого начала.
Комментарии:
1. Сначала я хочу иметь список символов *, а затем присвоить эти строки в стиле c вектору string
2. @ihm: Почему? Это смешно. Не делайте этого.
3. почему они становятся висячими? Прошу прощения, если это беспокоит.
4. да, я понял. они указывают на локальную строку s. каждый цикл сбрасывает значения s, и указатели становятся висячими.
5. @ihm: Правильно. 🙂 Хранение указателей в контейнерах C обычно является признаком недостатка дизайна; вы уже используете
std::list
, так что используйтеstd::string
, пока вы этим занимаетесь!
Ответ №3:
cout<<*cp;
выведет один символ, потому что он указывает на const char *
Вам нужно сделать:
cout<<cp;
Это выведет всю строку, на которую указывает cp
.
Ответ №4:
Здесь у вас есть пара больших проблем. Прежде всего,
const char* cp=s.c_str();
возвращает указатель на строку внутреннего элемента в std::string. При изменении строки значение, на которое ссылается возвращаемый указатель на c_str, может быть изменено (может даже находиться в новом местоположении). Итак, значения в вашем списке недопустимы. Убедитесь, что вы не используете c_str и пытаетесь использовать результат после изменения исходной строки (если только вы не скопируете результат c_str в новый массив символов.
Также,
cout<<*cp;
печатает только наш ваш первый элемент. Избавьтесь от *, чтобы напечатать всю c-строку в этом элементе списка.
Ответ №5:
похоже, что когда я cout * cp, он выводит только первую букву строки
*cp
является первой буквой строки. cout << cp
будет напечатана вся строка.
после того, как я поместил их в вектор, мой вывод остается пустым.
Ваш список содержит указатели на содержимое s
, которое допустимо только в теле цикла. Как только строка выходит за пределы области видимости, указатель «зависает» — указывает на освобожденную память. Попытка использовать указатель приведет к неопределенному поведению.
Вам нужно сохранить копию самой строки, либо создав clist
a list<string>
, либо сохранив строки в другом контейнере и сохранив указатели на данные в этом контейнере в clist
.
В качестве альтернативы, вы могли бы использовать строковые литералы вместо чтения строк из cin
. Строковые литералы живут столько же, сколько и программа, поэтому проблем с висячими указателями нет.
(Это предполагает, что комментарий в первой строке вашего кода является спецификацией, которую вы не можете изменить. В противном случае я бы clist
полностью избавился от них и вставлял каждую строку в конец svec
по мере ее чтения. Редко бывает хорошей идеей использовать указатели для чего-либо.)
Комментарии:
1. это не домашнее задание. Я читаю книгу, и это вопрос в книге. Я понимаю, почему они теперь становятся зависшими. помимо наличия другого контейнера строк и указателей, указывающих на каждую из них. есть ли способ получше? если это возможно
2. @ihm: вы могли бы использовать строковые литералы вместо чтения строк из
cin
:clist.push_back("Hello!");
будет работать без проблем с зависшим указателем. Но если вам нужно создать и сохранить кучу строк, нет ничего лучше, чем контейнер строк.3. Спасибо. это очень полезно. кстати. какой хороший текстовый редактор для написания кода в Linux? Я использую gedit. но по какой-то причине это становится действительно медленным.
4. @ihm: Я не нашел ничего достаточно хорошего, чтобы рекомендовать. В основном я использую vim, gedit и eclipse.