Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 26, средняя оценка - 4.92
Arderun
1 / 1 / 2
Регистрация: 12.09.2011
Сообщений: 17
#1

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

12.09.2011, 19:01. Просмотров 3793. Ответов 22
Метки нет (Все метки)

Доброго дня, комрады. Вот несколько дней как начал разбираться в С++ по 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 строки.
Вроде как индексированием на двумерный массив пользоваться не могу так как многомерные массивы собственно следующая глава.
Заранее спасибо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.09.2011, 19:01
Я подобрал для вас темы с готовыми решениями и ответами на вопрос вектор string в масив указателей на char (C++):

Вектор строк и массив указателей на тип char
Помогите, пожалуйста, с одной задачей. Сижу голову ломаю. Никак не могу понять...

Объяснить различия в работе указателей на целое число и указателей на const char (строки в стиле Си)
Уважаемые программисты, возникло несколько вопросов касательно указателей. ...

Создать специфицированный шаблон функции, принимающей массив указателей на char и количество самих указателей
Задача: создать специфицированный шаблон функции, принимающей массив указателей...

Различия указателей char* от указателей других типов
Помогите пожалуйста разобраться! Прочитал раздел про указатели и даже вроде...

есть массив char. есть строка string. как присвоить значению string-a значение char-a?
есть массив char. есть строка string. как присвоить значению string-a значение...

array char* to char* (значения массива указателей в один указатель)
Как сложить(или вывести в формате char*) все значения массива указателей(char...

22
Петррр
6155 / 3455 / 896
Регистрация: 28.10.2010
Сообщений: 5,926
12.09.2011, 19:17 #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;
}
1
Сыроежка
Заблокирован
12.09.2011, 20:06 #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() );
    }
1
sandye51
программист С++
833 / 592 / 147
Регистрация: 19.12.2010
Сообщений: 2,016
12.09.2011, 21:33 #4
Цитата Сообщение от Петррр Посмотреть сообщение
for(int j = 0; j < vec[i].size(); j ++)
вызов size() в цилке - нехорошо
0
Arderun
1 / 1 / 2
Регистрация: 12.09.2011
Сообщений: 17
13.09.2011, 14:32  [ТС] #5
Спасибо
0
ValeryLaptev
Эксперт С++
1049 / 828 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
13.09.2011, 14:39 #6
Цитата Сообщение от sandye51 Посмотреть сообщение
вызов size() в цилке - нехорошо
если размер вектора в цикле не меняется - только так и надо делать.
0
easybudda
Модератор
Эксперт CЭксперт С++
10021 / 5944 / 1483
Регистрация: 25.07.2009
Сообщений: 11,231
13.09.2011, 15:54 #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;
}
получилось
0
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
13.09.2011, 16:49 #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;
}
0
Arderun
1 / 1 / 2
Регистрация: 12.09.2011
Сообщений: 17
13.09.2011, 17:48  [ТС] #9
жуть какая, ссылка объявляется как вектор указателей на char . даже думать страшно, что когда-то я это смогу нормально понимать

И еще общий вопросик. Не могли бы вы порекомендовать 2 - 3 пособия где хорошо расписаны указатели, массивы и использование typedef(ну и ссылки наверно неплохо бы для верности), а то у Липмана хоть все и хорошо расписано но где-то мы с ним утеряли связь и двигаться дальше чувствуя что не до конца осознал критически важный кусок материала не хочется. Аля учебник С++ для дятлов или что-то в этом духе?
0
Сыроежка
Заблокирован
13.09.2011, 18:02 #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() действительны только на момент вызова этой функции. Так как любые действия с исходным контейнером по изменению своих элементов, могут привести не только к неактуальности этих указателей, но память, указываемая этими указателями, может быть вообще освобождена!
0
sandye51
13.09.2011, 21:49
  #11

Не по теме:

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

0
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
14.09.2011, 09:29 #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;
}
0
Сыроежка
Заблокирован
14.09.2011, 20:46 #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", и ваш указатель будет указывать на память, которая уже удалена.
0
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
14.09.2011, 22:53 #14
Сыроежка, Так вы ж любитель стандарта, но не понимаете что в нем написано? Оригинально.

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

Докажите мне обратное, если сможете. Пример кода, пример выполнения кода (показывающий вашу точку зрения), пункт стандарта, в котором это указано. Иначе - лесом.
1
easybudda
Модератор
Эксперт CЭксперт С++
10021 / 5944 / 1483
Регистрация: 25.07.2009
Сообщений: 11,231
14.09.2011, 23:45 #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
1
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
15.09.2011, 10:52 #16
easybudda, Кхм. Странно. Видать она не стандартная. У меня на gcc 4.5+ компилилось...

http://ru.wikipedia.org/wiki/Strdup Да. Не сразу это прочел.
0
easybudda
Модератор
Эксперт CЭксперт С++
10021 / 5944 / 1483
Регистрация: 25.07.2009
Сообщений: 11,231
15.09.2011, 11:16 #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
А вот внутри лямбда-функции её не видно. О, как!
3
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
15.09.2011, 11:45 #18
easybudda, Вау. Спасибо. Буду знать. Хотя интересно с какого это так.
0
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,048
15.09.2011, 14:03 #19
Лучший ответ Сообщение было отмечено как решение

Решение

Функция strdup не включена в стандарт C99, но включена в POSIX. MinGW при использовании -std=c++0x или -std=c99 устанавливает макрос __STRICT_ANSI__, в результате strdup и ещё некоторые функции остаются не объявленными. Чтобы скомпилировать программу с их использованием можно использовать -std=gnu++0x или -std=gnu99 соответственно.
4
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
15.09.2011, 14:40 #20
grizlik78, я c -std=c++0x компилил через gcc...
0
15.09.2011, 14:40
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.09.2011, 14:40
Привет! Вот еще темы с решениями:

Массив из указателей на масив из указателей на массив из int)
Доброго времени суток! Возникла проблема - как на C++ создать массив из...

Передача в функцию char*([Warning] deprecated conversion from string constant to 'char*' [-Wwrite-strings])
Почему компилятор на это матерится? ObjA.Show(&quot;A&quot;); deprecated conversion...

Строка: чем отличается строки string, char, char*?
Помогите разобраться,совсем плохо идёт,чем отличается строки string,char,char*...

масив char c++
доброго времени суток. #include&lt;iostream.h&gt; #define first 100 #define...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru