Отправляет email-рассылки с помощью сервиса Sendsay

Инвестиции: Вопрос-Ответ

  Все выпуски  

C/C++ Вопрос-Ответ Выпуск № 26


Информационный Канал Subscribe.Ru

C/C++ Вопрос-Ответ

Выпуск      : 26
Подписчиков : 1985
Cайт        : SoftMaker.com.ru
Архив       : C/C++ Вопрос-Ответ (архив)
В этом выпуске
От ведущего

Здравствуйте уважаемые подписчики !

Как всегда, рад приветствовть вас на страницах этой рассылки.
Напоминаю, что, как обычно, вы можете отправить свои пожелания (замечания, предложения, сообщения об ошибках) по поводу рассылки и сайта по этому адресу.
Если вы хотите создать и вести какой либо раздел в этой рассылке - также пишите мне.

И, как всегда, вы можете задать свои вопросы по программированию на сайте в форуме.
Или обсудить их в дискуссионном листе "Программирование. форум !!!".

Многим может быть также интересна рассылка: Visual С++ - расширенное программирование, где можно прочитать описания нестандартных приемов программирования с помощъю библиотеки MFC - 'трюков', 'хаков', недокументированных функций.

P.S. Поздравляю всех читателей рассылки с наступающим Праздником Весны и Труда !
     Желаю всем счастья и творческих успехов !

С уважением, Вахтуров Виктор.

Подписчикам

Чтобы заранее разрешить возможные недоразумения, прошу Вас помнить, что вопросы публикуются в рассылке только один раз. Поэтому, если Вам не ответили в этом выпуске, или ваш вопрос не был опубликован, пришлите его еще раз. Не стоит отвечать на вопрос, который был задан в предыдущем выпуске (за исключением случая, когда он снова опубликован в этом).

Для того, чтобы задать свой вопрос, пришлите письмо, кликнув по этой ссылке.
Для того, чтобы ответить на вопрос, надо кликнуть по ссылке "ответить", расположенной под текстом вопроса.

Небольшое примечание. Господа, если Вы хотите, чтобы Ваш e-mail был опубликован в рассылке, специально и явно укажите это в письме. Иначе e-mail адреса, указанные в теле Вашего письма в рассылке опубликованы не будут.

Вопросы

Для того, чтобы задать свой вопрос, кликните этой ссылке (вопрос будет опубликован в следующем номере).
Вы можете задавать любые вопросы, касающиеся программирования на языке C и C++. Это могут быть вопросы, касающиеся как конструкций языка, применения библиотек классов, шаблонов (таких как MFC или STL), использования компиляторов, так и самой философии программирования на C или C++. Здесь нет ограничений - спрашивайте и получайте ответы.

Вопрос № 100 ( Arsa )

Приветствую всех !

Простой, наверно, вопрос. Но как сделать такое - не знаю.
Пишу на Visual C++ (MFC).
В диалоге есть обычный редактор. Для него с помощью Class Wizard-а я сделал объект класса CEdit. В этот редактор я заношу текст.
Я хочу использовать этот редактор только для просмотра. То есть пользователь не должен иметь возможности редактировать текст. Такое достигается установкой стиля ES_READONLY (есть также соответствующий флажок в редакторе ресурсов).
НО !!! При этом фон редактора становится СЕРЫМ.
А мне хотелось бы, чтобы он был такого же цвета как и при редактировании.

Буду очень признателен, если кто нибудь подскажет решение проблемы (правда уже не уверен, что такое вообще возможно).

Ответить на вопрос

Вопрос № 101 ( synops )

Здравствуйте. Начал тут разбираться с исключениями в C++. Как то все странно пока выглядит. В связи с чем и возникли вопросы.

Итак.

1. В нескольких источниках (в основном смотрел в инете) прочитал, что обработчики исключений помогают разработчикам делать программы легче, избавляя от написания множества проверок корректности различных значений. Потому что если что то некорректно, то вылетит исключение. Его можно "поймать" и вроде, ничего не должно произойти.
Значит ли это, что можно вообще ни о каких значениях не забититься ? То есть если функция возвращает число, и я знаю, что она может возвратить 0, а этот результат я использую как знаменатель при делении в каких то вычислениях, то можно все равно не проверять на ноль это значение, а просто ловить исключения из этого блока кода ? Или все таки лучше делать проверки ?

2. Для обработки исключений есть конструкции try и catch.
Но есть также __try, __except и __finally.
Что то не понятно, чем они отличаются, если обе нужны для одного и того же.

3. Собственно, как работает __try, __except и __finally ?
Как я понял, можно использовать только __try и __except или __try и __finally, но можно и сразу __try, __except и __finally, причем вызывается и __finally и __except. Но какой в этом смысл ?

Буду очень благодарен за ответы !

Ответить на вопрос

Вопрос № 102 ( lera )

Только учусь программировать на C++.
Пытаюсь писать программы, применяя везде классы.
Расскажите пожалуйста, когда функции класса надо делать виртуальными, а когда нет ?
То есть как выбрать, сделать ли функцию виртуальной ?
Я поняла так, что если это внутренняя функция (для внутренних целей), а также ее потом изменять будет не надо, то она не должна быть виртуальной, а если она может быть изменена в классах-наследниках, то лучше ее сделать виртуальной. Но как точно узнать, какие функции будут, а какие не будут изменяться ?

Ответить на вопрос

Ответы

Ниже приведены вопросы предыдущего выпуска и ответы на них.

Вопрос № 94 ( Иван Базанов )

Как из BSTR получить LPCTSTR или string из STL ?

Ответ ( 3V )

Есть много способов... Хотя они все основаны на одном и том же - на конвертации содержимого BSTR через WideCharToMultiByte.
Вообще, есть классы для работы с BSTR. В ATL есть CComBSTR. Есть стандартный класс _bstr_t. У _bstr_t есть операторы: wchar_t* и char*, с помощью которых и можно BSTR конвертировать либо в юникодную, либо в мультибайтную строку.
Эти операторы класса _bstr_t используют функцию ConvertBSTRToString пространства имен _com_util. Вот примет использования:

   #include <comutil.h>
   #pragma comment(lib, "comsupp.lib")

   ...

   // Вот строка BSTR
   BSTR bstrText = ::SysAllocString(L"Test");

   // Конвертируем в char*
   char* lpszText = _com_util::ConvertBSTRToString(bstrText);

   // тут можно использовать lpstText
   
   delete[] lpszText;


   _bstr_t bstr;

   // Содержимое bstrText копируется
   bstr.Assign(bstrText);

   // Возвращается указатель на внутренний
   // константный буфер bstr
   LPCTSTR lpszText2 = (LPTSTR) bstr;

   // Можно использовать lpszText2

   SysFreeString(bstrText);

Ну а в STL-евский string - простым присваиванием char*.
Вопрос № 95 ( Копрова_Марина_Львовна )

Здравствуйте! Как можно запустить из программы на VC++ другую программу (exe файл) Знаю, что можно сделать это с помощью API функции CreateProcess, но разобраться с параметрами, которые она требует, не могу.

Ответ ( Neco )

Гораздо проще юзать ShellExecute, а непосредственно CreateProcess
нужен для более провинутых задач (кстати и для их [задач] создания
тоже), типа отладчика. Но если надо, то вот пример:

rez=CreateProcess(NULL,"taskmgr.exe",NULL,NULL,FALSE,
                  CREATE_SUSPENDED,NULL,NULL,&si,&pi);

или:

rez=CreateProcess("E:\\Program Files\\Microsoft Visual Stud"
                  "io\\Common\\Tools\\SPYXX.EXE",NULL,NULL,
                  NULL,FALSE,CREATE_SUSPENDED,NULL,NULL,&si,
                  &pi);

У этих стоит CREATE_SUSPENDED. Это значит, что процесс не будет
запущен после создания и запускать его придётся вручную через
ResumeThread (поток из ProcessInfo[pi])
такая фенька нужна, если планируется подправить к примеру память
процесса перед выполнением, а в общем случае этот флаг можно и не
использовать.
Более подробно об этой команде можно прочесть у Рихтера.

Ответ ( Mikhail Ermak )

Spy.

Можно не глубоко разбираться в параметрах:

BOOL RunExe( char* szNameExe ) {
   PROCESS_INFORMATION pi;
   STARTUPINFO sti;

   ZeroMemory (&sti,sizeof(STARTUPINFO));
   sti.cb=sizeof(STARTUPINFO);

   BOOL bResult =CreateProcess(NULL,
              szNameExe,
              NULL,      // process security attributes
              NULL,      // primary thread security attributes
              TRUE,      // handles are inherited
              0,         // creation flags
              NULL,      // use parent's environment
              NULL,      // use parent's current directory
              &sti,  // STARTUPINFO pointer
              &pi);  // receives PROCESS_INFORMATION
   return bResult;
}

Ответ ( Ващенко Сергей )

Привет!
Смотра код, думаю разберёшься.

//Запускаем программу scr.exe
STARTUPINFO sinf;
PROCESS_INFORMATION pinf;
ZeroMemory(&sinf,sizeof(sinf));
sinf.cb = sizeof(sinf);
sinf.dwFlags = STARTF_USESHOWWINDOW;
sinf.wShowWindow = SW_SHOWNORMAL;

CreateProcess("D:\\programs\\scr\\scr.exe",0,0,0,FALSE,
              NORMAL_PRIORITY_CLASS,0,0,&sinf,&pinf);
Вопрос № 96 ( Некто Который )

Никак не могу подружиться с ссылками и с возвращаемыми значениями ф-ций =(

-почему функция, которая возвращает параметр как значение должна сначала сделать копию его а потом возвратить?
-почему при возврате значения как ссылки копия не делается? и делается ли что-то вообще? (по идее должна делать копия переменной представляющей ссылку)
-допустим у нас есть класс с открытыми методами достуап и закрытыми членами-переменними, делаются ли функциями-членами, которые возвращают значение переменных-членов, копии переменных(обьектов)-членов перед тем как их возвратить как значения?

вобщем я немного запутался и прошу не судить меня строго, я толька начинаю изучать с++!

Ответ ( Neco )

Да я и сам тока начинаю - до этого на VB сидел. Важна лишь разница
между ByVal и ByRef (это я из васятки) и этой реализацией на сишке.
Насколько я понял в си всегда создаётся копия (как собственна и в
васе, тока там это менее интересно), но тока вот копия ЧЕГО - это
важно. Т.е. если ты передал что-то просто как int a, то изменение этой
переменной внутри функции ничего не даст, т.к. функция получила копию
"a". А вот если ты передашь int *a и внутри функции будешь юзать "*a",
то изменяться будет та самая (первоначально передаваемая) "а", но при
этом значение всё-таки копироваться будет, только копия будет не
ПЕРЕМЕННОЙ, а УКАЗАТЕЛЯ на на неё.

Вот счас написал и подумал, что я совсем неправильно понял твой
вопрос...
Надо было тебе в коде выражать мысли, а то я тоже запутался совсем...
8)

Ответ ( Шматко А.А. )

> почему функция, которая возвращает параметр как значение должна сначала
> сделать копию его а потом возвратить?

Кто сказал? Это ты в примерах скорее всего частенько видел нечто подобное:

    int someFunc()
    {
        int result;
        /* ... */
        result=someExpression;
        return result;
    }

Никто не мешает просто написать

    return someExpression;

без всякого промежуточного result;

> почему при возврате значения как ссылки копия не делается? и делается ли
> что-то вообще? (по идее должна делать копия переменной представляющей
> ссылку)

Ну так значение и есть значение, а ссылка и есть ссылка. Почему это они
должны преобразовываться друг в друга просто так, без надобности и команды
программиста? Ссылки являются самостоятельными типами данных, так же как и
указатели. Ты ж не удивляешся, почему значения и указатели не преобразуются
друг в друга? Так что "идея" не верна.
Однако, это ещё смотря, что ты имеешь в виду в своём вопросе. Если функция
возвращает int&, а заканчивается return 123; то есть возвратом значения, то
как раз наоборот - компилятор обязан сделать преобразование из значения в
ссылку. Скорее всего, он заведёт "невидимую" для тебя локальную переменную
(локальную, так как он не может поступить иначе: во-первых, значение 123
используется локально в функции; во-вторых, эта временная переменная никого,
кроме оператора return, не касается; в-третьх, ему просто негде её делать,
кроме как в локальной области видимости функции), присвоит ей значение 123 и
попытается вернуть ссылку на неё. И как добропорядочный помощник, сообщит
тебе предупреждением, что ты пытаешься вернуть ссылку на локальный объект. И
то, если возвращаемая ссылка константная. В противном случае это будет
ошибка компиляции. Наверное, как раз это и побудило тебя задать этот вопрос,
не так ли?
Чтобы проникнуться проблемой, подумай над следующим. Ссылки являются
присваиваемыми сущностями (как говорят l-value), поэтому вполне можно
написать, например, someFunc()=321, если функция возвращает int&. Поэтому
компилятор и создаёт переменную, чтоб было на что ссылку возвращать. А раз
тебе нужно возвращать значения (как говорят r-value, которые
неприсваиваемые - как ты представляешь себе присваивание константе 123?), то
ссылки в качестве возвращаемого типа тебе просто не подходят. В твоём случае
возвращать нужно значение. Ссылки не для этого нужны. Они и не для этого
предназначены.

> допустим у нас есть класс с открытыми методами достуап и закрытыми
> членами-переменними, делаются ли функциями-членами, которые возвращают
> значение переменных-членов, копии переменных(обьектов)-членов перед тем
> как их возвратить как значения

Нужны ли функции-члены (методы) для доступа к закрытым членам-переменным
(элементам класса), это тебе решать. Ещё не факт что они нужны. Если их
нужно и читать, и писать, то проще оставить их открытыми, ведь доступ на
чтение-запись к элементу класса подразумевает включение этого элемента
класса в публичный интерфейс. Если же не всё так просто, и требуется
управляемый доступ с защитой этих элементов класса от прямого доступа, то
это делается свойствами (properties). В С++ непосредственно как таковых
свойств нет. Как расширение языка, они могут предоставляться конкретной
средой разработки, например Builder-ом. Однако по любому они несложно
программируются.
Если элементы класса нужно только читать, или только писать, то как раз
самое время предоставить соответсвтующие функции. Если же они вообще не
нужны для доступа, то и функций никаких не нужно. Пусть так и будут
закрытыми.
А нужно ли или нет делать их копии, я думаю, ты уже и сам понял. Не нужно,
но можно. Если хочется - делай.

Ответ ( beststory )

Каждый раз, когда вызывается ф-ция, создается новая копия ее аргументов и локальных переменных.Область памяти, отводимая данной ф-ции используется многократно , поэтому нельзя в качестве возвращаемого значения использовать ссылку на локальную переменную(т.к. что будет хранится в данной области памяти в этот момент предсказать не возможно). По этой причине возвращаемое значение сначало сохраняется(копируется), после чего происходит выход из ф-ции (все внутренние переменные уничтожаются), после чего мы имеем доступ к результату переменной через промежуточную переменную(объект).
В случае возврата значения как ссылки по-моему все очевидно - так как новой переменной для работы с этими данными не создавалось, а вся работа проводилась на "живом объекте" - при доступе через ссылку к конкретной области памяти, то соответсвтенно и никаких дополнительных действий при выходе из ф-ции делать не надо - просто передаем обратно адрес объекта(переменной) и забываем про него (правда в случае, если данная переменная(объект) создается внутри самой ф-ции необходимо позаботиться об очистке памяти, т.к. использовать delete при выходе из программы или в момент, когда данный объект станет больше не нужен - в противном случае вы получите "утечку памяти").
С уважением cronOS.
Вопрос № 97 ( atavin_ta )

Подскажите, чем в си заменена точечная нотация. Раньше я писал в дельфях, а также в версии си, не поддерживавшей визуальную разработку.
Необходимости в использовании нескалярных типов в си (если не считать таковыми массивы) не было, а значит не было и необходимости в доступе к свойствам переменных. Но в дельфях я привык часто использовать точечную нотации для доступа к свойствам объектов, в том числе, экранных элементов. Теперь у меня Borland C++Builder 6 Enterprize и я хочу использовать его возможности. Например, вставляю в форму TImage и хочу получить доступ к свойству Width и к методу SaveToFile. В принципе, я нашел, как выводить данные например в Cells от TStringGrid:
StringGrid1->cells[i][j]=v;. Но я хочу не только выводить данные в
свойства, но и читать свойства, а кроме того, мне нужен вывод строчных и символьных переменных и символьных массивов, а приведенный выше фрагмент транслирует значения числовых переменных в символьную форму и выводит результат трансляции.

С уважением Атавин Т. А.

Ответ ( beststory )

Различие при использовании точки и стрелки обусловленно природой объекта. То, что создано динамически, требует, чтобы к нему обращались через оператор доступа ("->"), в случае статического элемента обращаение идет также как и дельфи через точку. Чтобы рационально использовать память для структуры используется память выделяемая в куче (большинство "правильных" реализации исользуют именно динамическую работу с памятью). В дельфи используется другой подход - в большинстве случаев используется запоминание в локальных и глобальных переменных. Итак, создав объект(структуру) вы захватываете требуемый объем памяти в куче. Теперь имя вашего объекта указывает на эту память. Поэтому теперь вы не можете использовать точечную нотацию, т.к. символ имени объекта описывает теперь не саму структуру, а это всего лишь ссылку на структуру. Следовательно теперь вы используете оператор доступа к члену "->", который ставится между указателем структуры и именем члена и указывает на расположение его в памяти относительно начала структуры.Иными словами - вы создали структуру, динамически выделив память под ее хранение. Так как каждый из членов струкутры имеет заранее известный размер, поэтому выделенная область разделяется на подобласти, каждая из которых исользуется для конкретного члена структуры (т.е. вы можете обращаться именно к ней).
Если же вам все же очень не удобно пользоаться подобной записью, то следующая запись имеет тот же самый смысл, что и в случае использования оператора доступа: (*p).x.
Если вы загляните в заголовочный файл (.h), то увидите, что компаненты, которые вы добавляете на форму
описываются как динамические объекты (с символом "*").
Что касается чтения(вывода) и записи(присваивания) значений свойствам объекту(структуре), то это осуществляется точно также как и дельфи.
Вывод: не забивайте себе мозги подобной ерундой, просто привыкайте - если объект объявлен как динамическая структура, то используется "->", в противном случае - ".".
Вопрос № 98 ( Diosso )

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

type ver3f = array[0..2] of real;
 ...
vers:array of ver3f;
 ...
setlength(vers,n);

Diosso

Ответ ( Neco )

Я не очень долго искал ответ на этот вопрос, когда мне это тоже
понадобилось. Просто начал создавать массивы размером заведомо больше,
чем мне нужно и добавлять переменную означающую предел. Потом же
увеличивал или уменьшал тока эту переменную.
Через некоторое время этот способ я нашёл в какой-то литре по сям.
Поэтому и тебе советую...

Ответ ( Иван Базанов )

Здравствуйте! Попробуй использовать STL:

//////////////////////////////////////////////////////////////
//////////////////////////////.
// Это для использования STL
#include <vector>
using namespace std;
//
// Это постоянная часть ширины 3:
// type ver3f = array[0..2] of real;
class ver3f
{
    double data[3]; // Сами данные
public:
    // Для доступа по []
    double& operator[](int n) {return data[n];};
};
//

void SomeFunction(int n)
{
    // А это переменная: vers:array of ver3f;
     vector<ver3f> vers;
    //
    // Установка длины массива
     vers.resize(n);  // n - новая длина переменной части
    //
    // А вот так можно получить доступ к элементам массива:
    vers[индекс_переменная_часть][индекс_постоянная_часть] =
                                                     значение;
    //
};
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////

NB!
1. Не проверяется выход за пределы по 2му индексу.
2. При выходе за пределы по 1 индксу при необходимости массив удлиняется.

Ответ ( Шматко А.А. )

Смотри в сторону STL. В данном случае, тебе вполне подойдёт конструкция

typedef std::vector<double> ver3f;
std::vector<ver3f> vers;

и далее

vers.resize(n);

Единственное неудобство - ver3f требуется при создании явно устанавливать
размер в три элемента. Однако это неудобство легко преодолевается созданием
ver3f как производного класса от std::vector<double>, в котором установка
размера будет выполняться прямо в конструкторе.
Альтернативный вариант в plain-C стиле:

typedef double ver3f[3];
ver3f *vers;

Первый раз создаёшь

vers=malloc(n*sizeof(vers[0]));
if(vers==NULL) error();

изменяешь размер

ver3f *temp=realloc(vers, n*sizeof(vers[0]));
if(temp==NULL) error();
 else vers=temp;

В конце не забудь

free(vers);

Однако, при "ручной" работе с динамической памятью легко допустить массу
ошибок. Программировать и отлаживаться нужно аккуратно и тщательно.
Использование std::vector<> значительно проще и безопаснее, так как этот
класс сам всё на себя берёт. Использование же его не отличается от
"дельфийного", например: vers[21][1]=3.82 или sqrt(vers[14][0]). А если
вместо [] использовать метод std::vector<>::at(), то ещё и контроль индексов
получишь. Чего не даст решение в стиле plain-C.
Вопрос № 99 ( Arsa )

Здравствуйте !

Очень надеють на помошь читателей рассылки, потому что от моих тщетных
попыток заставить работать простейшую вещь, уже голова идет кругом :(

Значит так.
Делаю прогу в Visual C++ 6.0 Проект - MFC, на основе диалога.
Есть обычный диалог. На нем расположен обычный static control.
Этому статику я хочу просто сменить шрифт. Шрифт в окне веняется
при помощи SetFont, поэтому я делаю так (сначала получаю текущий шрифт,
получаю из него LOGFONT, меняю поля структуры LOGFONT, создаю новый
шрифт, и устанавливаю окну):

void CMyDlg::OnButton1() 
{
    CFont font;

    LOGFONT lf;

    m_wndStatic.GetFont()->GetLogFont(&lf);

    lf.lfWeight  = 900;
    lf.lfUnderline = 1;

    font.CreateFontIndirect(&lf);

    m_wndStatic.SetFont(&font);
}

И шрифт элемента меняется как надо. НО !!!
Как только я сворачиваю прогу в панель задач, а потом снова ее
разворачиваю, шрифт этого статика становится другим (похоже,
системмным).

Я был бы безмерно рад, если бы кто нибудь подсказал, как все таки задать
шрифт произвольному элементу диалога (это точно можно сделать - видал, что
в некоторых прогах так сделано). Но как ?

Ответ ( Neco )

Никогда не юзал MFC (даже постоянно забываю что стоит на конце S или
C), но могу предположить, что таким макаром происходит реагирование на
системное сообщение. Какой-нибудь PAINT там (хотя это точно отпадает),
короче попробуй оппосылать сам сообщения этому элементу и когда он
сбросит шрифт - ты нашёл его. А лечить наверное тока перехватом и
обновлением...

Ответ ( Mikhail Ermak )

Spy

Всё замечательно, но у вас после выхода из функции font разрушается.
Сделайте его членом класса или глобальным:

CFont m_font;

void CMyDlg::OnButton1()
{
//    CFont font;

    LOGFONT lf;

    m_wndStatic.GetFont()->GetLogFont(&lf);

    lf.lfWeight  = 900;
    lf.lfUnderline = 1;

if(m_font.GetSafeHandle() ) m_font.DeleteObject();
    // чтобы не было утечки ресурсов
    // в деструкторе то же надо удалять!!!
    m_font.CreateFontIndirect(&lf);

    m_wndStatic.SetFont(&m_font);
}

Ответ ( 1 )

После вызова font.CreateFontIndirect(&lf) ты создал шрифт и он поменялся, но ты уже вышел из функции, где у тебя объявлена переменная font и ее уже нет после выхода из функции. Где же бедной программе взять информацию о шрифте?
Ест-но шрифт сохраниться до первой перерисовки окна, а поскольку и про старый шрифт ты программе дал забыть вызовом той же font.CreateFontIndirect(&lf), то она подставляет первый попавшийся шрифт. Попробуй объявить переменную font как глобальную.
Сам не проверял. Удачи.

Ответ ( Rred Cat )

Здравствуйте Arsa. Когда окно разворачивается, оно перерисовуется наново в функции OnPaint(). Дальше думаю понятно?
Книги по C/C++
Полный справочник по C++ (C++: The Complete reference)
Полный справочник по C++ (C++: The Complete reference)

Автор: Герберт Шилдт

В четвертом издании этой книги полностью описаны и проиллюстрированы все ключевые слова, функции, классы и свойства языка С++, соответствующие стандарту ANSI/ISO.

Информацию, изложенную в книге, можно использовать во всех современных средах программирования. Освещены все аспекты языка С++, включая его основу - язык С.

Справочник состоит из пяти частей:
  • подмножество С;
  • язык С++;
  • библиотека стандартных функций;
  • библиотека стандартных классов;
  • приложения на языке С++.

Книга предназначена для широкого круга программистов.

Страница книги на Озоне
C/C++. Алгоритмы и приемы программирования. Код с комментариями
C/C++. Алгоритмы и приемы программирования. Код с комментариями

Автор: Арт Фридман, Ларс Кландер, Марк Михаэлис, Г. Шилдт

Книга является репринтным изданием C/C++. Архив программ.

В ней представлен код работоспособных программ на C/C++, относящихся к самым разнообразным областям и аспектам написания приложений - от работы с достаточно простыми структурами данных (списки, деревья) до построения синтаксических анализаторов и интерпретаторов, доступа к Internet и т. п.

Программный код может использоваться в ваших программах без изменений или в модифицированном и усовершенствованном виде. Чрезвычайно полезно также его изучение в целях освоения главнейших принципов, алгоритмов и приемов решения разных задач.

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

Книга предназначена для широкого круга программистов, пишущих на языках C/C++.

Страница книги на Озоне
Всего доброго. До встречи в следующем номере.

http://subscribe.ru/
http://subscribe.ru/feedback/
Подписан адрес:
Код этой рассылки: comp.soft.prog.cppqa
Отписаться

В избранное