Форум программистов, компьютерный форум CyberForum.ru

вектор string в масив указателей на char - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 26, средняя оценка - 4.92
Arderun
1 / 1 / 0
Регистрация: 12.09.2011
Сообщений: 17
12.09.2011, 19:01     вектор string в масив указателей на char #1
Доброго дня, комрады. Вот несколько дней как начал разбираться в С++ по 4-му вводному курсу липмана. наткнулся на задачку в общем-то тривиальную, но в определенном месте немного вывихнул мозг.
Задание:
Напишите программу читающую строки в вектор. Скопируйте этот вектор в массив указателей на тип char. Для каждого элемента вектора создайте новый символьный массив и скопируйте данные из элемента вектора в этот символьный массив. Затем поместите указатель на символьный массив в массив символьных указателей.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>  
#include <string> 
#include <vector> 
#include <bitset> 
#include <stddef.h>  
#include <cstring>   
using std::bitset;
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
 
int main()
{ 
    char * himas[10];
    int j,D;
    string V;
    vector<string> liter;
string a ;
for(int i=0; i!=10; ++i)
{cin >> a ;
liter[i].push_back(a);
}
for(int i=0; i!=10; ++i)
{
j=liter[i].size();
V=liter[i];
for(int k=0; k!=j; ++k)               // <-
{**(himas+k)=V[k];                  //  <-
}
}
for(int i=0; i!=10; ++i)
{cout << himas[i] << endl;
}
return 0;
}
не знаю всю ли пунктуацию почистил, но запнулся собсвтенно на записи в указатель на char строки.
Вроде как индексированием на двумерный массив пользоваться не могу так как многомерные массивы собственно следующая глава.
Заранее спасибо.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.09.2011, 19:01     вектор string в масив указателей на char
Посмотрите здесь:

Массив из указателей на масив из указателей на массив из int) C++
есть массив char. есть строка string. как присвоить значению string-a значение char-a? C++
Вектор строк и массив указателей на тип char C++
Передача в функцию char*([Warning] deprecated conversion from string constant to 'char*' [-Wwrite-strings]) C++
Создать специфицированный шаблон функции, принимающей массив указателей на char и количество самих указателей C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Петррр
 Аватар для Петррр
5915 / 3352 / 333
Регистрация: 28.10.2010
Сообщений: 5,926
12.09.2011, 19:17     вектор string в масив указателей на char #2
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <string>
#include <vector>
 
using namespace std;
 
int main(int argc, char ** argv)
{
    vector<string> vec;
    string str;
    while (cin >> str)
        vec.push_back(str);
    char ** array = new char*[vec.size()];
    for(int i = 0; i < vec.size(); i++)
    {
        array[i] = new char[vec[i].size() + 1];
        for(int j = 0; j < vec[i].size(); j ++)
            array[i][j] = vec[i][j];
        array[i][vec[i].size()] = '\0';
    }
    for(int i = 0; i < vec.size(); i++)
        cout << (i + 1) << ": " << array[i] << endl;
    for(int i = 0; i < vec.size(); i++)
        delete [] array[i];
    delete [] array;
    system("pause");
    return 0;
}
Сыроежка
Заблокирован
12.09.2011, 20:06     вектор string в масив указателей на char #3
Цитата Сообщение от Петррр Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
    for(int i = 0; i < vec.size(); i++)
    {
        array[i] = new char[vec[i].size() + 1];
        for(int j = 0; j < vec[i].size(); j ++)
            array[i][j] = vec[i][j];
        array[i][vec[i].size()] = '\0';
    }
}
Вместо цикла по копированию строки из вектора в массив проще воспользоваться стандартной функцией std::strcpy из библиотеки <cstring>

C++
1
2
3
4
5
    for(int i = 0; i < vec.size(); i++)
    {
        array[i] = new char[vec[i].size() + 1];
                strcpy( array[i], vec[i].c_str() );
    }
sandye51
программист С++
 Аватар для sandye51
677 / 579 / 39
Регистрация: 19.12.2010
Сообщений: 2,016
12.09.2011, 21:33     вектор string в масив указателей на char #4
Цитата Сообщение от Петррр Посмотреть сообщение
for(int j = 0; j < vec[i].size(); j ++)
вызов size() в цилке - нехорошо
Arderun
1 / 1 / 0
Регистрация: 12.09.2011
Сообщений: 17
13.09.2011, 14:32  [ТС]     вектор string в масив указателей на char #5
Спасибо
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
13.09.2011, 14:39     вектор string в масив указателей на char #6
Цитата Сообщение от sandye51 Посмотреть сообщение
вызов size() в цилке - нехорошо
если размер вектора в цикле не меняется - только так и надо делать.
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9373 / 5423 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
13.09.2011, 15:54     вектор string в масив указателей на char #7
Знаю, что не по заданию, просто интересно было, что получится...
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cstring>
    
class Str2Char {
    std::vector<char*> & vref;
public:
    Str2Char(std::vector<char*> & holder) : vref(holder) {}
    void operator () ( const std::string & str ){
        char * ptr = new char [ str.size() + 1 ];
        strcpy(ptr, str.c_str());
        vref.push_back(ptr);
    }
};
 
int main(void){
    std::vector<std::string> svec;
    svec.push_back("Ivanov");
    svec.push_back("Petrov");
    svec.push_back("Sidorov");
    
    std::vector<char*> cvec;
    std::for_each(svec.begin(), svec.end(), Str2Char(cvec));
    
    for ( std::vector<char*>::const_iterator i = cvec.begin(); i != cvec.end(); ++i )
        std::cout << *i << std::endl;
    
    for ( std::vector<char*>::iterator i = cvec.begin(); i != cvec.end(); ++i )
        delete [] *i;
    
    return 0;
}
получилось
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
13.09.2011, 16:49     вектор string в масив указателей на char #8
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <cstring>
#include <iterator>
#include <string>
#include <vector>
#include <algorithm>
 
int main()
{
    std::vector<std::string> strings = {"hello", "and", "what"};
    std::vector<const char*> vec;
    std::for_each(strings.begin(), strings.end(), [&vec](const std::string& str)
    {
        vec.push_back(str.c_str());
    });
    std::vector<char*> chars;
    std::for_each(vec.begin(), vec.end(), [&chars](const char* str)
    {
         chars.push_back(strdup(str));
    });
    std::copy(chars.begin(), chars.end(), std::ostream_iterator<char*>(std::cout, "\n"));
    std::for_each(chars.begin(), chars.end(), [](char* ptr) {free(ptr);});
    return 0;
}
Arderun
1 / 1 / 0
Регистрация: 12.09.2011
Сообщений: 17
13.09.2011, 17:48  [ТС]     вектор string в масив указателей на char #9
жуть какая, ссылка объявляется как вектор указателей на char . даже думать страшно, что когда-то я это смогу нормально понимать

И еще общий вопросик. Не могли бы вы порекомендовать 2 - 3 пособия где хорошо расписаны указатели, массивы и использование typedef(ну и ссылки наверно неплохо бы для верности), а то у Липмана хоть все и хорошо расписано но где-то мы с ним утеряли связь и двигаться дальше чувствуя что не до конца осознал критически важный кусок материала не хочется. Аля учебник С++ для дятлов или что-то в этом духе?
Сыроежка
Заблокирован
13.09.2011, 18:02     вектор string в масив указателей на char #10
Цитата Сообщение от ForEveR Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <cstring>
#include <iterator>
#include <string>
#include <vector>
#include <algorithm>
 
int main()
{
    std::vector<std::string> strings = {"hello", "and", "what"};
    std::vector<const char*> vec;
    std::for_each(strings.begin(), strings.end(), [&vec](const std::string& str)
    {
        vec.push_back(str.c_str());
    });
    std::vector<char*> chars;
    std::for_each(vec.begin(), vec.end(), [&chars](const char* str)
    {
         chars.push_back(strdup(str));
    });
    std::copy(chars.begin(), chars.end(), std::ostream_iterator<char*>(std::cout, "\n"));
    std::for_each(chars.begin(), chars.end(), [](char* ptr) {free(ptr);});
    return 0;
}
Ваше решение не соответствует условиям задачи, так как вы не копируете значения переменных типа string в символьный массив.
Но еще хуже, что оно некорректное, так как значения указателей, переданных c_str() действительны только на момент вызова этой функции. Так как любые действия с исходным контейнером по изменению своих элементов, могут привести не только к неактуальности этих указателей, но память, указываемая этими указателями, может быть вообще освобождена!
sandye51
13.09.2011, 21:49
  #11

Не по теме:

Цитата Сообщение от ValeryLaptev Посмотреть сообщение
если размер вектора в цикле не меняется - только так и надо делать.
один из советов Мейерса - такие вызовы перед циклом делать

ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
14.09.2011, 09:29     вектор string в масив указателей на char #12
Сыроежка,

the values in this array should not be modified in the program and are only guaranteed to remain unchanged until the next call to a non-constant member function of the string object.
Не вижу в моем коде вызова неконстантной функции от строк в векторе. Не вижу в моем коде изменения указателей, возвращаемых c_str(). Где некорректность?

Добавлено через 5 минут
1
2
Returns: A pointer to the initial element of an array of length size() + 1 whose first size() ele-
ments equal the corresponding elements of the string controlled by *this and whose last element is a
null character specified by charT().
Requires: The program shall not alter any of the values stored in the array. Nor shall the program treat the
returned value as a valid pointer value after any subsequent call to a non-const member function of the
class basic_string that designates the same object as this.
Пункт 21.3.6 стандарта 2003 года.

Добавлено через 6 минут
Если столь важна именно копия, тогда так.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <cstring>
#include <iterator>
#include <string>
#include <vector>
#include <algorithm>
 
int main()
{
    std::vector<std::string> strings = {"hello", "and", "what"};
    std::vector<char*> vec;
    std::for_each(strings.begin(), strings.end(), [&vec](const std::string& str)
    {
        vec.push_back(strdup(str.c_str()));
    });
    std::vector<char*> chars;
    std::for_each(vec.begin(), vec.end(), [&chars](const char* str)
    {
         chars.push_back(strdup(str));
    });
    std::copy(chars.begin(), chars.end(), std::ostream_iterator<char*>(std::cout, "\n"));
    std::for_each(vec.begin(), vec.end(), [](char* ptr) {free(ptr);});
    std::for_each(chars.begin(), chars.end(), [](char* ptr) {free(ptr);});
    return 0;
}
Сыроежка
Заблокирован
14.09.2011, 20:46     вектор string в масив указателей на char #13
Цитата Сообщение от ForEveR Посмотреть сообщение
Сыроежка,



Не вижу в моем коде вызова неконстантной функции от строк в векторе. Не вижу в моем коде изменения указателей, возвращаемых c_str(). Где некорректность?

Добавлено через 5 минут


Пункт 21.3.6 стандарта 2003 года.

Добавлено через 6 минут
Если столь важна именно копия, тогда так.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <cstring>
#include <iterator>
#include <string>
#include <vector>
#include <algorithm>
 
int main()
{
    std::vector<std::string> strings = {"hello", "and", "what"};
    std::vector<char*> vec;
    std::for_each(strings.begin(), strings.end(), [&vec](const std::string& str)
    {
        vec.push_back(strdup(str.c_str()));
    });
    std::vector<char*> chars;
    std::for_each(vec.begin(), vec.end(), [&chars](const char* str)
    {
         chars.push_back(strdup(str));
    });
    std::copy(chars.begin(), chars.end(), std::ostream_iterator<char*>(std::cout, "\n"));
    std::for_each(vec.begin(), vec.end(), [](char* ptr) {free(ptr);});
    std::for_each(chars.begin(), chars.end(), [](char* ptr) {free(ptr);});
    return 0;
}
Я не понял, что вы там на английском цитируете, но, как я уже сказал, ваш код некорректный. Хранить указатели на память, возвращаемую функцией c_str() - это безграмотно! Достаточно в исходном массиве первую строку "hello" поменять на "hello to everybody", и ваш указатель будет указывать на память, которая уже удалена.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
14.09.2011, 22:53     вектор string в масив указателей на char #14
Сыроежка, Так вы ж любитель стандарта, но не понимаете что в нем написано? Оригинально.

Вектор создается в функции. Удаляется он после выхода из функции. До тех пор строки корректны. Так же как и указатели на них, если данный объект строки не был изменен в процессе.

Докажите мне обратное, если сможете. Пример кода, пример выполнения кода (показывающий вашу точку зрения), пункт стандарта, в котором это указано. Иначе - лесом.
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9373 / 5423 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
14.09.2011, 23:45     вектор string в масив указателей на char #15
ForEveR, не знаю, почему, не компилируется оно у меня, вот, что пишет:
Код
C:\cpp\strings>g++ -std=c++0x -o ForEverStr2Char ForEverStr2Char.cpp -enable-aut
o-import
ForEverStr2Char.cpp: In lambda function:
ForEverStr2Char.cpp:14:41: error: 'strdup' was not declared in this scope
ForEverStr2Char.cpp: In lambda function:
ForEverStr2Char.cpp:19:36: error: 'strdup' was not declared in this scope

C:\cpp\strings>g++ -dumpversion
4.5.0
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
15.09.2011, 10:52     вектор string в масив указателей на char #16
easybudda, Кхм. Странно. Видать она не стандартная. У меня на gcc 4.5+ компилилось...

http://ru.wikipedia.org/wiki/Strdup Да. Не сразу это прочел.
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9373 / 5423 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
15.09.2011, 11:16     вектор string в масив указателей на char #17
Сообщение было отмечено автором темы, экспертом или модератором как ответ
ForEveR, так сама-то по себе функция strdup() для компилятора не новость, то есть код
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
int main(void){
    const char * cptr = "hello world";
    char * sptr = strdup(cptr);
    if ( ! sptr ){
        perror("strdup");
        exit(1);
    }
    *sptr = 'H';
 
    printf("%s\n%s\n", cptr, sptr);
 
    exit(0);
}
прекрасным образом отработает
Код
C:\cpp\strings>teststrdup.exe
hello world
Hello world
А вот внутри лямбда-функции её не видно. О, как!
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
15.09.2011, 11:45     вектор string в масив указателей на char #18
easybudda, Вау. Спасибо. Буду знать. Хотя интересно с какого это так.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
15.09.2011, 14:03     вектор string в масив указателей на char #19
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Функция strdup не включена в стандарт C99, но включена в POSIX. MinGW при использовании -std=c++0x или -std=c99 устанавливает макрос __STRICT_ANSI__, в результате strdup и ещё некоторые функции остаются не объявленными. Чтобы скомпилировать программу с их использованием можно использовать -std=gnu++0x или -std=gnu99 соответственно.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.09.2011, 14:40     вектор string в масив указателей на char
Еще ссылки по теме:

C++ В чем отличие двумерного массива типа char от массива указателей на char?
C++ Вектор ссылок и вектор указателей
array char* to char* (значения массива указателей в один указатель) C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
15.09.2011, 14:40     вектор string в масив указателей на char #20
grizlik78, я c -std=c++0x компилил через gcc...
Yandex
Объявления
15.09.2011, 14:40     вектор string в масив указателей на char
Ответ Создать тему
Опции темы

Текущее время: 19:58. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru