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

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

  Все выпуски  

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


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

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

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

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

Прежде всего, я искренне поздравляю всех Вас

С Новым Годом !

Хочу пожелать в новом году счастья и творческих успехов !


Далее я хочу извиниться за выпуск рассылки, произошедший 31-го декабря 2004 года. К сожалению, я ошибся кодом рассылки при вводе очередного выпуска рассылки "Visual С++ - расширенное программирование", в результате чего выпуск ушел сюда.

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

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

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

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

Подписчикам

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

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

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

Вопросы

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

Вопрос № 62 ( Виктор )

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

Ситуация такая:
при генерации кода из Rational Rose в MFS, в MFS
создаётся проэкт и генерируется исходный код.
Подскажите, каким образом можно связать сгенерированный класс с
создаваемым отдельно диалоговым окном (когда я пытаюсь привязать к
окну сгенерированный клас, мастер этот класс не видит).

Виктор

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

Вопрос № 63 ( Diosso )

Как создать меню к окну, используя только функции
WinAPI?

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

Вопрос № 64 ( Max116 )

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

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

Ответы

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

Вопрос № 56 ( Сергей Ващенко )

Hello, programmers!
Я учусь программировать на C и никак не могу разобраться с рекурсией. Помогите чем сможете :)

Ответ ( newmail )

Hello,

Рукрсивные функции вызывают сами себя. Например, находим факториал
некоторого числа N. Из курса математики известно что факториал числа
равен произведению предыдущих чисел на данное число, например, факториал числа 3
будет такой 3!=1*2*3=6; 4!=1*2*3*4=24 и т.д. Исходя из этого пишем
рекурсивную функцию:

  int factorial(int n) //n - число факториал которого мы ищем
  {
      if(n==1 || n==0) return 1;
      /*(из математики) факториал чисел 1 и 0 равен 1*/
      
      return n*factorial(n-1);
      /* Здесь мы вычасляем факториал. Поновой вызывается функция
      factorial(). Она будет вызыватся до тех пор, пока переданное
      число не будет ранвно 1(см. выше). Когда выполнется проверка и
      factorial() вернет 1 и начнется, так сказать, обратный путь.*/
  }

Для примера вернемся к уже упоминавшемуся числу 4. Сперва в
factorial() передается число 4. Проверку оно не проходит и
передается в следующую строчку:"return n*factorial(n-1);". Здесь n=4
и снова вызывается фунция factorial(), но уже с числом n-1, т.е. 3.
Число 3 опять же не проходит проверку и мы вновь подходим к строчке:
"return n*factorial(n-1);". В этом месте уже работает вторая копия
функции и поэтому здесь n=3, а factorial() вызывается с новым
значением - 2. При двойке мы поторяем теже ходы, что и 3 и с 4.
Когда запускается 4-ая копия функции(n=1) выподняется
условие(if(n==1 || n==0) return 1;) и 4-ая
копия функции возврашает 3-ей единицу. В 3-ей копии n=2 умножается
на возвращенное значение. Мы получаем 2. Это значение возврещается
2-ой копии. Во 2-ой копии n=3 умножается на 2. Мы получаем 6.Далее
это значение возвращается первой копии функции, где n=4. Умножаем n
на возврщенное число, т.е. 4*6=24. Итак, мы получили, что факториал
4 равен 24.
Так как при использовании рекурсии создается много копии функции, а
соответственно столькоже копии набора переменных, то она съедает
очень много памяти и работает медленно, поэтому , по возможности, её
лучше заменить циклом.

Ответ ( администратор )

(силентий) Мои искренние соболезнования. Вряд ли кто Вам поможет. Это невозможно объяснить, это нужно пережить :) Или смириться с ее существование. Или обходиться без нее. Любая задача, которая может быть решена рекурсивно, решаема и итерационно. Правда, лично я не возьмусь развернуть некоторые нетривиальные алгоритмы, в том числе и классический QuickSort. Попробуйте, скажем, набросать схемку какого-нибудь классического вычисления( 5! например, программа - в любой книжке) С какими аргументами функция вызывается, что и с чем вызывает сама, что возвращает. Скажем для 3! схема может выглядеть как-нибудь так: fact(3) -> 3*fact(2) -> 3*(2 * fact(1)) = 3*2*1 = 6. Возможно, Ваша запись будет Вам понятнее. Рекурсия от Бога, итерация от человека. (с) не помню кто.

Ответ ( Andrey Gordeev )

Рекурсия - это вызов функцией саму себя.

Допустим есть ф-ия с прототипом

void func(void);


тогдапри использование рекурсии допустим вызов

void func(void)
{
    func();
}


Например классический пример - подсчёт факториала

void main()
{
 
long Result=Fact(...);
}


Без рекурсии:

long Fact(int Num)
{
    long Res=1;
    for(int i=2;i


С рекурсией:

long Fact(int Num)
{
   if(Num>1)
    return Num*fact(Num-1);
else
    return 1;
}


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

Ответ ( bvb )

Рекурсия это вызов процедуры из самой себя.
Допустим процедура

BOOL proc()
{
 ......
 ......
 BOOL a=proc();
 .....
}


т.е внутри процедуры proc() вызывается сама процедура proc() т.е. при
некотором стечении обстоятельств возможен случай не выхода из
бесконечного вызова самой себя из самой себя.

Поэтому задача программиста исключить данный вариант.

Например необходимо искать файл в некоторых директориях вложенных в
некую основную директорию.
Рекурсивный вызов позволяет резко упростить алгоритм, а то
обстоятельство что вложенных директорий не бывает бесконечное
количество, гарантирует что количество вызовов будет ограничено и
начнется обратный выход из всех произведенных вызовов
Вопрос № 57 ( Хорошилов Евгений )

Как в C++ Builder создать модальное дочернее окно в MDI?
Пытался обычным ShowModal() ругает, что нельзя сделать модальным
видимое окно. Птался его прятать при помощи Hide() и Visible,
ругаеться, что дочернее окно нельзя прятать...:)

Ответ ( Maria Shpileva )

хм. странно. надо просто в инспекторе объектов сделать для формы Visible = false. и всё должно переть в верном напрвлении...

Ответ ( bev )

Все достаточно просто. Во-первых, создав новую форму, которую
планируется использовать в качестве модльного окна, заходишь в меню:
Project->Options (Alt+F7)-> вкладка Forms, где
добавляешь свою форму в список Available Forms (
это формы, которые будут считаться формами MDI проекта -
дочерние формы). Далее просто в нужном месте пишешь код
примерно такого содержания:

//Этот код вызывается при выборе пункта меню
void __fastcall TMainForm::SubMenuPrivateUserClick(TObject *Sender)
{
TFormCreateUser *FormCreateUser;
FormCreateUser = new TFormCreateUser(Application, 1, false, 0);
}


где TFormCreateUser - тип формы (класс), который определен
в дочернем модуле (то, что создано способом New Form),
- короче, просто копируешь свое описание из этого модуля.
Чаще всего испоьзуется просто конструкция:
FormCreateUser = new TFormCreateUser(Application);
- так прописывается в модуле по умолчанию (в данном случае мне
потребовалось еще прарочка параметров :) )
Но,в качестве аргументов кроме Application могут присутствовать
и другие параметры (если ты их конечно описал в своем модуле - в
файлах модуля .Cpp .h если правишь заголовок(список параметров функции
), то не забудь поправить в обоих файлах).
Метод new создает дочернее окно, поэтому при его закрытии, необходимо
не просто его закрыть, а уничтожить. Это делается так:

void __fastcall TFormUOL::FormClose(TObject *Sender,
      TCloseAction &Action)
{
Action=caFree;
}


И не забудь в свойствах своей дочерней формы выставить свойство
Formstyle="fsMDIChild."
Вопрос № 58 ( argent )

Dоброго времени суток вам!

Пишу вам второй раз т.к. в первый раз ответа не получил...
1.Есть ли в С++функция для отображения текущего времени(без даты)?
2.Я тут написал одну крутую(по моему) прогу.Как можно сделать, чтобы все
желающие могли её скачать?
3.Как можно сделать прогу для учета трафика(может функция какая?)

Ответ ( bev )

В Греции все есть :)
Честно говоря, проблема не совсем понятна, в каждой
среде есть свои примочки для определения текущего времени.

Например, для Borland C++ Builder годится такая конструкция:

TDate *d;
d=new TDate();
Label2->Caption="Время:"+d->CurrentTime();
delete d;


Если используешь Visual C++ от Mircosoft, то скорее всего
нужно что-то подобное:

CTime theTime;
theTime = CTime::GetCurrentTime();


Если пишешь под UNIX, то можно сделать так:

  #include <iostream.h>
  #include <time.h>
  int main()
  {
   time_t tim=time(0); //
   struct tm *t=localtime(&tim);
   cout<<"Time "<<t->tm_hour<<":"<<t->tm_min<<":"<<t->tm_sec<<"\n";
   return 0;
  }
//конечно, кусок не очень изящный, зато работает (проверено в FreeBSB 4.10)


А в TurboC можно использовать следующий код:

 #include <stdio.h>
 #include <dos.h>

 int main(void)
 {
    struct time t;
    gettime(&t);
    printf("Time: %2d:%02d:%02d\n",t.ti_hour, t.ti_min, t_ti_sec);
    return 0;
 }


Короче, покопайся в документации к своей среде разработки. Но
в любом случае смотри библиотеку time.h.

Ответ ( Lexxa )

Ответа ты не получил, ИМХО, потому что вопросы надо формулировать:

> 1.Есть ли в С++функция для отображения текущего времени(без даты)?
Отображения или получения?
Если отображения, то куда: в память, в другой формат, на экран?
А что ее отображать-то? Может вопрос в другом: есть 3 числа: час, минута и секунда - как их преобразовать в строку в нужном формате?

> 2.Я тут написал одну крутую(по моему) прогу.Как можно сделать, чтобы все
> желающие могли её скачать?
Это вообще отдельный вопрос.

> 3.Как можно сделать прогу для учета трафика(может функция какая?)
На каком языке? Допустим на С++.
Трафик HHTP или POP3 или через COM-порт или ...?
Вопрос № 59 ( Сергей Ващенко )

Здрасти!
Почему не работает следующий код: (эта программа копирует текстовые файлы. Если файл был ранее в нужной директории, то всё нормально, если же такого там не нашлось - прога вылетает)

#include <stdio.h>
#define bsz 500

int main(int argc,char *argv[])
{
 unsigned char buf[bsz];
 int tmp,a;
 FILE *in;
 FILE *out;
 if(argc<3)
 {
  printf("ERROR! Unodinary parameters.");
  scanf("%d");
  return 1;
 } 
 in=fopen(argv[1],"rb");
 if(in==NULL)
 {
  printf("File %s not found!",argv[1]);
  scanf("%d");
  return 1;
 }
 tmp=0;
 out=fopen(argv[2],"rb");
 if(out==NULL)
 {
  tmp=1;
  fclose(out);
 }
 if(tmp)
 {
  out=fopen(argv[2],"wb");
 } 
 else
 {
  printf("File %s exist. Rebuild? (y/n)>",argv[2]);
  a=getchar();
  if(a=='Y' || a=='y')
   out=fopen(argv[2],"wb");
  else return 1;
 } 
 while(fgets(buf,bsz,in))
  fputs(buf,out);
 fclose(in);
 fclose(out);
return 0;
}

Заранее спасибо!!!

Ответ ( Михаил )

Не знаю, в чем проблема-то?
Я скомпилировал исходник - программка работает как запланировано.
Если файл не найден , то прога об этом сообщает и закрывается...

Ответ ( администратор )

Все просто: если файл существует и открылся на чтение, он не закрывается и переоткрывается на запись. Моветон, но терпимо. Интереснее, когда его нет. Первый же fclose(out) вызывается при условии out==NULL. Отсюда и проблемы. Кроме того, есть еще одна логическая ошибка: не проверяется вызов fopen(out, "wb"). А ведь не факт, что у данной программы будут права на создание файла или его перезапись. Времена NTFS и EXT2, знаете ли. И еще. Онлайновая отладка программ, пусть и тривиальных - не есть самый эффективный метод отладки. Учитесь думать. Вставляйте как можно больше проверок. Вставляйте отладочную печать. Используйте assert(). Когда все совсем плохо(и только тогда!!!) - пользуйтесь отладчиком. По отладке, да и по всем прочим околопрограммистким вопросам очень рекомендую книжку Брайана Кернигана и Роба Пайка "Практика программирования".

Ответ ( Andrey Gordeev )

Ошибка здесь

out=fopen(argv[2],"rb");
if(out==NULL)
{
  tmp=1;
  fclose(out);
}


ты пытаешся закрыть файл, который не был успешно открыт !
надо так:

out=fopen(argv[2],"rb");
if(out!=NULL)
{
 //делаеш то что тебе надо
}
else
{
  tmp=1;

}

Ответ ( bev )

Честно говоря, ковыряться в коде особого желания нет,
но все одна идея есть:
ты пишешь return 1 - т.е. даешь команду на
завершение выполнения функции Main, т.е.
самой проги. Выходит, что она ведет себя логично -
раз файла нет - занчит вылетает.
Вопрос № 60 ( Сницаренко С.А. )

Добрый день. Скажите пожалуйста как с помощю С можна читать и остсылать даные на СОМ порт? И если можна рабочий пример!

Ответ ( bev )

Вот адрес с хорошим примером с коментсами на русском,
демонстрирующий определение, открытие и закрытие порта.
http://www.bcbdev.ru/codesamples/winapi/comportlist.htm
Например, чтобы прочитать слово с порта можно написать так:

#include <stdio.h>
#include <conio.h>
 ..................
  unsigned result;
  unsigned port = 0; // идентификатор порта   serial port 1

  result = inpw(port);
  printf("Word read from port %d = 0x%X\n", port, result);
 ..................


Что-то в этом роде...
А так, советую скачать справочное руководство по win32 api
там очень много интересных вещей (по крайней мере есть описания
функций и праметров, в т.ч. и по работе с устройствами).
Брать здесь: http://www.bcbdev.ru/winapi.htm
Вопрос № 61 ( Able )

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

Я недавно подписался на вашу разсылку, но после первогоже письма стало ясно,
что это тошто мне нужно. У меня затруднения:
Мне необходимо создать вид вкладок (СTabView)в разделяемом окне (CSplitterWnd)
проблема в том, что вкладка не хочет разтягиваться в размер вида, и остается
в заданных при создании размерах. И если не трудно подскажите как на
подобных вкладках разместить дерево (CTreeCtrl). Зарание благодарен!

Ответ ( Lexxa )

Здравствуй.
Надо на WM_SIZE вида пересчитывать и изменять размеры вкладки.
TTreeCtrl, насколько я помню, размещается на вкладках так же, как и в простом окне.
Книги по C/C++
C++. Экспресс курс
C++. Экспресс курс

Автор: Валерий Лаптев

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

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

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

Для начинающих программистов.

Страница книги на Озоне
Алгоритмические трюки для программистов
Алгоритмические трюки для программистов

Автор: Генри С. Уоррен, мл.

В этой книге слову 'хакер' возвращено его первозданное значение - человека увлеченного, талантливого программиста, способного к созданию чрезвычайно эффективного и элегантного кода.

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

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

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

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

В избранное