список символов * в вектор строк

#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.