Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Укажите на ошибки в упражнении


Автор: zim22 22.1.2009, 12:01
Необходимо было выполнить упражение из книги. Я выполнил, но думаю что ошибся в понимании самого упражнения или использованных типов данных.
Укажите, пожалуйста, где я ошибся.

Задание:
1) Напишите программу, читающую строки в вектор. 
2) Скопируйте этот вектор в массив указателей на тип char. 
3) Для каждого элемента вектора создайте новый символьный массив и скопируйте данные из элемента вектора в этот символьный массив. 
4) Затем поместите указатель на символьный массив в массив символьных указателей. 
5) Затем отобразите содержимое вектора и массива. 
6) После отображения не забудьте удалить символьные массивы.

6 пункт не знаю, как сделать... Если удалять их в том блоке, где оператор new использую,  то данные стираются и следовательно отобразить их в пункте 5) я не смогу...
Код

int main()
{
// 1) Напишите программу, читающую строки в вектор. 
    string str;
    vector<string> vs;
    while (cin >> str)
    {
        vs.push_back(str);
    }

//2) Скопируйте этот вектор в массив указателей на тип char. 
// Как динамически создать массив указателей не знаю, поэтому создал на 100 штук явно.
    const size_t max_el = 100;
    const char *acp[max_el];
    
    size_t cnt = 0;
    for (vector<string>::size_type ix = 0; ix != vs.size(); ++ix)
    {
        acp[ix] = vs[ix].c_str();
        ++cnt;
    }

// 3) Для каждого элемента вектора создайте новый символьный массив 
// и скопируйте данные из элемента вектора в этот символьный массив. 
    for (vector<string>::const_iterator ci = vs.begin(); ci != vs.end(); ++ci)
    {        
        char *el = new char[(*ci).size() + 1];
        strcpy(el, (*ci).c_str());

// 4) Затем поместите указатель на символьный массив в массив символьных указателей. 
        acp[cnt++] = el;        
    }

// 5) Затем отобразите содержимое вектора и массива. 
    for (vector<string>::iterator iter = vs.begin(); iter != vs.end(); ++iter)
        cout << *iter << endl;

    for (size_t ix = 0; ix != cnt; ++ix)
    {
        cout << acp[ix] << endl;

// 6) После отображения не забудьте удалить символьные массивы.
// delete [] acp[ix]; не работает, т..к не диманически память выделял. как удалить символьные массивы, созданные ранее?
    }        

    return 0;
}

Автор: Andrey44 22.1.2009, 12:19
Цитата(zim22 @  22.1.2009,  12:01 Найти цитируемый пост)
т..к не диманически память выделял

Код

char *el = new char[(*ci).size() + 1];

А это как? Статически?

Автор: zim22 22.1.2009, 12:36
Andrey44, это динамически smile
Я имел ввиду, что нельзя написать строчку 
Код

delete [] el;

после этой:
Код

 acp[cnt++] = el;  

т.к. данные сотрутся и ниже по коду я не смогу их отобразить оператором cout

пытаюсь символьные массивы удалять  ниже (закомментировал строчку в коде) 
Код

delete [] acp[ix];

код компилируется, но во время выполнения приложение завершается с крит.ошибкой: Debug Assertion Failed! Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

Автор: mes 22.1.2009, 12:40
Цитата

// 5) Затем отобразите содержимое вектора и массива. 
    for (vector<string>::iterator iter = vs.begin(); iter != vs.end(); ++iter) 
        cout << *iter << endl; // вывод вектора вижу , а где вывод массива ?

 // а вот тут выведите длину вектора, и длину массива (cnt) -  и будете удивлены smile
 


а виновата строчка 20, к тому же блок 17-21 бессмысленный

Автор: Andrey44 22.1.2009, 12:40
zim22, ты смотрел чему равно ix когда ты вызываешь delete [] acp[ix]; ?

Автор: zim22 22.1.2009, 13:33
Andrey44, смотрел. ix = 0; следовательно в этом участке кода
Код

for (size_t ix = 0; ix != cnt; ++ix)
{
            cout << acp[ix] << endl;        
    delete acp[ix];
}

при первой итерации acp[0] указывает на строку, расположенную по индексу 0.
если например при запуске программы ввести: hello my dear
то 3 строки занесётся в вектор. и acp[0] будет указывать на строку "hello"
так что я до сих пор не понимаю, почему оператор delete не работает

mes, длину вектора и массива вывел. длина массива в 2 раза больше длины вектора. так и должно быть (как я понял) по логике работы программы.
Т.к. после пункта 2 в массиве указателей содержится 3 элемента. А после п.4 ещё 3 элемента, итого 6.

почему код в строках 17-21 бессмысленный?
если конечно вы имеете ввиду этот участок:
Код

for (vector<string>::size_type ix = 0; ix != vs.size(); ++ix)
{
    acp[ix] = vs[ix].c_str();
    ++cnt;
}


Этот код выполняет пункт 2) задания: Скопируйте этот вектор в массив указателей на тип char. 

>// вывод вектора вижу , а где вывод массива ?
вывод массива здесь:
Код

for (size_t ix = 0; ix != cnt; ++ix)
{
    cout << acp[ix] << endl;
}        

Автор: mes 22.1.2009, 14:37
Цитата(zim22 @  22.1.2009,  12:33 Найти цитируемый пост)
mes, длину вектора и массива вывел. длина массива в 2 раза больше длины вектора. так и должно быть (как я понял) по логике работы программы.
Т.к. после пункта 2 в массиве указателей содержится 3 элемента. А после п.4 ещё 3 элемента, итого 6.


Не удивлены ?! то есть Вы в курсе, что создали три элемента, а удаляете шесть ? !!! smile

Цитата(zim22 @  22.1.2009,  12:33 Найти цитируемый пост)
Этот код выполняет пункт 2) задания: Скопируйте этот вектор в массив указателей на тип char. 

а..ну если того требует задание.. просто в контексте кода этот блок не имел смысла...  к тому же он потенциально опасный .. 

Цитата(zim22 @  22.1.2009,  12:33 Найти цитируемый пост)
вывод массива здесь:

сорри, опять моя невнимательность

Автор: zim22 22.1.2009, 16:34
Цитата(mes @  22.1.2009,  14:37 Найти цитируемый пост)
Не удивлены ?! то есть Вы в курсе, что создали три элемента, а удаляете шесть ? !!! 

я создал 6 элементов, а не 3.

здесь "создаётся" (на самом деле Присваивается, правильно?) 3 элемента:
Код

acp[ix] = vs[ix].c_str();


плюс здесь ещё 3:
Код

char *el = new char[(*ci).size() + 1];
strcpy(el, (*ci).c_str());
acp[cnt++] = el;                


итого 6 элементов содержится в переменной acp
*****
добавлено 1 секунду спустя:
гениально! я понял в чём ошибка была!
В самом нижнем цикле нужно поменять
Код

delete acp[ix];

на 
Код

delete acp[ix + 3];


и я буду удалять как раз те 3 строки(последних), которые создавал оператором new.
а первые 3 строки я не мог удалить, т.к. они принадлежали вектору?

Автор: mes 22.1.2009, 17:49
Цитата(zim22 @  22.1.2009,  15:34 Найти цитируемый пост)
и я буду удалять как раз те 3 строки(последних), которые создавал оператором new.
а первые 3 строки я не мог удалить, т.к. они принадлежали вектору? 

вот вот. рад, что Вы сами дошли до понимания smile
только прибавления не достаточно.. надо ограничеть цикл до 3х .

Автор: zim22 22.1.2009, 22:28
mes, спасибо за напутствующие подсказки.
это прекрасное чувство, когда на тебя "ни-с-того, ни-с-сего" снизоходит озарение и ты понимаешь что в коде было неверно smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)