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

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

  Все выпуски  

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


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

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

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

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

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

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

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

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

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

Подписчикам

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

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

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

Вопросы

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

Вопрос № 71 ( zhenya1.14 )

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

Такой вопрос: Как зи строки вида "asd,fgh,jkl" создать массив т.е.
array ( 0 =>asd; 1 => fgh; 2 => jkl)

В PHP есть такая функция: explode (string разделитель, string строка [, int порог]), есть ли ее аналог в C++ ?

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

Вопрос № 72 ( Max116 )

Приветствую !
В прошлом выпуске спрашивал про скины, но забыл задать еще вопросик :)
Теперь меня интересуют плагины (plug-ins).

Очень интересно как правильно их реализовывать ?
Плагины есть во многих приложениях - в Winamp и Total Commander, например.
Насколько я понимаю, плагин - просто модуль с функциями (как например, обычная
dll). Может, в большинстве случаев это и есть dll.
Но в dll ведь можно определить некоторые функции, а в программе получится
использовать только те, о которых знаешь (надо ведь знать прототипы).
А плагины пишутся разными людьми.
Может есть способ вызывать функции из длл не зная прототипа ?
И как вообще можно получить список функций в dll ?
И как узнать какие из них надо запускать (если это плагин) ?

Вобщем, вопросов туча. Хотелось бы понять как это (плагины) работает.

Всем заранее спасибо !

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

Вопрос № 73 ( Akela )

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

Пишу в VC++ консольное приложение.
Создал его визардом. Он создал проект с функцией main.
Все вроде понятно. Все почти как в Borland C++ 3.1. под DOS.
Я могу выводить на экран информацию при помощи printf или cout.
Это работает
Но в дос можно было использовать цвет шрифта и фона для текста,
а также ставить курсор в произвольную позицию чтобы текст выводился
начиная оттуда. А тут я не нашел похожих функций.

Интересно таких функций нет вообще или есть аналоги функциям в BC 3.1.

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

Ответы

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

Вопрос № 68 ( Владимир )

Здравствуйте.
У меня такой вопрос, подскажите, кто знает. Программирую в С++ Builder. Опыта пока немного. Попросил товарищ сделать ему небольшую базу данных для его магазина. Я сделал, но есть две проблемы: 1. программа не хочет работать на другом компьютере, 2. не знаю как сделать, чтобы в поля для введения цены товара можно было вводить дробные числа. При создании таблицы при помощи Database Desktop в свойствах полей перепробовал все варианты, ничего не получается.
Спасибо.

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

1. Предположу , что не верно скомпилирован проект :-).
   Тогда сними галочки в опциях проекта здесь
   packages-> Build with runtime packages
   и здесь linker-> use dynamic RTL

2. Rогда создаешь поле в Database Desktop
   задай ему тип float мли double
   ( смотря в какой базе табличка сделана )
   , size 15, dec 2
   (если хочешь хранить там денюжки ;-)
Вопрос № 69 ( Max116 )

Приветствую всех !
Сегодня вот такой вопрос.
Не знает ли кто как реализовать поддержку "скинов" в приложении ?
Скины сейчас получают все большее и большее распространение.

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

Всем заранее спасибо.

Ответ ( 3V )

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

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

1. Получить информацию о классе окна элемента управления при помощи GetClassInfo.
2. Запомнить адрес оконной функции где нибудь.
3. Разрегистрировать класс окна контрола (::UnregisterClass).
4. В структуре WNDCLASS (в которую была получена инфа о классе окна контрола) заменить адрес оконной функции на адрес некоторой своей оконной функции.
5. Зарегистрировать заново класс окна контрола, воспользовавшись все той же структурой WNDCLASS с подмененным адресом оконной процедуры.

И так для всех используемых твоей прогой контролов.
Таким образом когда в программе будут создаваться контролы, адреса оконных процедур у них будут твои. Таким образом можно в принципе, соответствующим образом обрабатывать WM_PAINT, WM_ERASEBKGND, и.т.д (все необработанные сообщения, естесственно надо направлять в старую оконную процедуру контрола - адрес которой сохранили).
Но это, имхо очень геморно (извиняюсь) - писать надстройку над всеми возможными элементами управления. Правда, никто ведь не заставляет тебя перерисовывать их все. Ну, а тут уж как реализовать конкретные скины (картинками, или еще как - думаю, фантазии хватить должно).
Вопрос № 70 ( RaLex )

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

1  2  3  4
12 13 14 5
11 16 15 6
10 9  8  7

размер матрицы - любой. И все надо написать, конечно
на C илм C++.

Если кто то подскажет как это сделать буду очень рад.
C++ я впринципе знаю. И небольшую программу самостоятельно
могу написать. Мне понятно как заполнить матрицу числами
с помощью циклов но тут как то циклами не получается.
Может быть тут как то особенно делать надо ?

Ответ ( Lexxa )

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

Вот решение, что называется, "в лоб".

const int size = 4;

int matrix[size][size];
int minColumn = 0;
int maxColumn = size-1;
int minRow = 0;
int maxRow = size-1;
int val = 1;

while (val <= size * size)
{
  for (int column = minColumn; column <= maxColumn; ++column)
  {
      matrix[column][minRow] = val;
      ++val;
  }
  ++minRow;

  for (int row = minRow; row <= maxRow; ++row)
  {
      matrix[maxColumn][row] = val;
      ++val;
  }
  --maxColumn;

  for (int column = maxColumn; column >= minColumn; --column)
  {
      matrix[column][maxRow] = val;
      ++val;
  }
  --maxRow;

  for (int row = maxRow; row >= minRow; --row)
  {
      matrix[minColumn][row] = val;
      ++val;
  }
  ++minColumn;
}

Ответ ( Александр Носков )

Вопрос N 70 очень похож на учебное задание и он опубликован несмотря на то, что автор рассылки в выпуске N 142 писал: "Студентов попрошу вопросы по написанию различных прог в рассылку не посылать, они публиковаться не будут."
Если есть вопрос, значит должен быть ответ. Программа написана на C.

#include <stdio.h>
#include <stdlib.h>


 void Generator( int *m, int a, int b)
 {
  int i, j = 0, l = 1, k = a, n = b;
  while (l <= (a*b))
  {
   for (i = j; (i < k) && (l <= (a*b)); i++)
   {
    m[(a-k)*a + i] = l;
    l ++;
   }

   for (i = j + 1; (i < n) && (l <= (a*b)); i++)
   {
    m[i*a + k - 1] = l;
    l ++;
   }
   j ++;

   for (i = j; (i <= (a-j)) && (l <= (a*b)); i++)
   {
    m[a*n - i - 1] = l;
    l++;
   }
   n --;

   for (i = n; (i > (b - n)) && (l <= (a*b)); i--)
   {
    m[a*i - k] = l;
    l ++;
   }

   k--;
  }
 }


 void help ()
 {
  printf("hrlix.exe { M N }        \n");
  printf("      L-- Генерация матрицы размера M x N\n");
  printf(" \n");
 }


 //Основная программа (точка входа)
 int main( int cc, char *vv[])
 {

  int i, j;
  int *mem;
  int Size1Matrica, Size2Matrica;

  Size1Matrica = atoi(vv[1]);
  Size2Matrica = atoi(vv[2]);

  if ( cc <= 2 || cc > 3 || Size1Matrica < 2 ||
       Size2Matrica < 2 )
  {
   help();
   exit (1);
  }

  mem = (int*) malloc(Size1Matrica * Size2Matrica *
                      sizeof(int));
  if (mem == NULL)
  {
   printf ("\n Нет памяти. Уменьшите размер матрицы или"
           "освободите память\n");
   exit (1);
  }

  Generator( mem, Size1Matrica, Size2Matrica);

  printf ("\n\t\tВаша улитка:\n");
  for (i = 0; i < Size2Matrica; i++)
  {
   for (j = 0; j < Size1Matrica; j++)
   {
    printf ("%d\t", mem[i*Size1Matrica+j]);
   }
   printf ("\n");
  }

  free (mem);
  return 0;
 }


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

(силентий) Предлагаю следующий вариант. По возможности упрощал, поэтому есть возможность оптимизации.

/* 
 * n x n - размер требуемой матрицы
 * a - матрица размером (n+2) x (n+2)
 * для упрощения кода использую так называемых "часовых",
 * дополнительные элементы на границах
 * поэтому и размер больше требуемого
 *
 * после генерации можно скопировать/вывести только
 * "подматрицу" с индексами 1..n, 1..n
 */
void gen()
{
 int i, j, k;
 int di; /* приращение индекса столбца*/
 int dj; /* и строки */
 
 /* инициализация */
 for(i=0; i<n+2; i++)
  for(j=0; j<n+2; j++)
   a[i][j] = -1;
 
 /* выставляем часовых по периметру */
 for(i=0; i<n+2; i++){
  a[0][i] = a[n+1][i] = 1;
  a[i][0] = a[i][n+1] = 1;
 }
  
 /* собственно генерация */
 i = 1; j = 1;
 di = 1; dj = 0;
 for(k=1; k<=n*n; k++){
  a[i][j] = k;
  /* а вот здесь и нужны часовые, чтобы не париться,
     отслеживая индексы */
  if(a[i+di][j+dj] > 0){
   /* натолкнулись либо на границу, либо на уже заполненную
      ячейку */
   /* меняем направление */
   if(di==1){
    di = 0;
    dj = 1;
   }else if(dj==1){
    di = -1;
    dj = 0;
   }else if(di==-1){
    di = 0;
    dj = -1;
   }else if(dj = -1){
    di = 1;
    dj = 0;
   }
  }
 }
}

Ответ ( Afonin Dmitri )

Можно так...

#include <stdio.h>

void main()
{
 const int m=7,n=5;
 int mas[n][m];
 int napr=1,p,k1,i,j;

 i=j=k1=p=0;
 while(p<m*n)
 {
  if((napr==1)&(i>n-k1-2)) napr=2;
  if((napr==2)&(j>m-k1-2)) napr=-1;
  if((napr==-1)&(i<k1+1))
  {
   k1++;
   napr=-2;
  }
  if ((napr==-2)&(j<k1+1)) napr=1;

  p++;
  mas[i][j]=p;

  if(napr==1)  i++;
  if(napr==2)  j++;
  if(napr==-1) i--;
  if(napr==-2) j--;
 }

 for(i=0;i<m;i++)
 {
  printf("\n");
  for(j=0;j<n;j++)
   printf("%d  ",mas[j][i]);
 }
}

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

Очередная нетривиальная задачка на логику Ж-),
смотри как делается (может и криво написано, но работает!):

//===========Вот полностью прога=====================
#include <stdio.h>
const max=7;
int i,j;
int t=0;
int dispatch; // правило перенаправления ,  =0,1,2,3
int matr[max][max]; // матрица должна быть заполнена 0!
void __fastcall iter()
{
  t++;
  matr[i][j]=t;
  switch (dispatch) // поворот
  {  case 0: i++; if (i>max-1 || matr[i][j]!=0)
                     {j++; i--; dispatch++; }; break;
     case 1: j++; if (j>max-1 || matr[i][j]!=0)
                  {i--; j--; dispatch++; }; break;
     case 2: i--; if (i<0 || matr[i][j]!=0)
                  { i++; j--; dispatch++;  }; break;
     case 3: j--; if (j<0 || matr[i][j]!=0)
                  { i++; j++; dispatch++;  }; break;
  }
  if (dispatch > 3) dispatch=0;
  if (t>=(max)*(max)) return;
  iter();
}

int main(int argc,char *argv[])
{
   FILE *stream;
   stream = fopen("c:\out.txt", "w+");
   i=0;j=0;dispatch=0;
   iter();
   // проверяем как отработало:
   for ( int a=0; a<max; a++)
        {for ( int b=0; b<max; b++)
            fprintf(stream,"%5d ",matr[b][a]);
         fprintf(stream,"\n");
        }
   fclose(stream);
return 0;
}

Ответ ( Vinokur Alexander-BAV016 )

Перевод с транслита:

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

Заполнение матрицы по спирали можно представить как повторяющееся заполнение четырех сторон матрицы. Это внешние циклы он будет иметь min(n/2 + 1, m/2 + 1) итерацый, где "n" и "m" - размерность матрицы. Заполнение каждой стороны делается в цикле и трудностей в кодировании не представляет. Соответственно окончательний код будет иметь следующий вид: один внешний цикл, внутри которого четыре отдельных внутренних цикла.

П.С. Думаю, что заполнение четырех сторон при желании можно представить одним циклом "размотав" один виток спирали, но в таком случае внутри цикла придется ставить проверки на нахождение индекса в правильных границах, что знать когда какой индекс остановит, а какой начат изменять. При такой реализации, на мой взгляд, код выдет сложнее

Ответ ( Alexey )

То, что циклами не получится, это неверно. Любую программу можно
написать, использовав 3 возможных расположения операторов по
отношению друг к другу: последовательное, в условии и в цикле.

Поначалу я написал программу, использовав рекурсивную функцию, потому что
сразу приходит на ум заполнение "витками" (loop), каждый следующий
меньше предыдущего.

Раскомментарь все //print(a); , чтобы лучше
увидеть алгоритм, по которому работает программа.

#include <stdio.h>
#include <conio.h>

int N;
int** matrix;

void loop(int **a, int n, int num);

void main()
{
        printf("Enter N: ");
        scanf("%d", &N);

        matrix = new int*[N];
        for(int i=0,j; i<N; i++) 
                matrix[i] = new int[N];

        for(i=0; i<N; i++)
                for(j=0; j<N; j++) matrix[i][j]=0;

        loop(matrix, 0, 1);

}

//------- prints matrix
void print(int **a)
{
        printf("\n");
        
        for(int i=0,j; i<N; i++)
        {
                printf("\n\n");
                for(j=0; j<N; j++)  printf("%4d",a[i][j]);
        }

        printf("\n");
        getch();
}

//------ fills one loop in the matrix, beginning
// with a[n][n] = num
void loop(int **a, int n, int num)
{
        for(int i=n; i<N-n; i++) a[n][i] = num++;
        //print(a);
        for(i=n+1; i<N-n; i++) a[i][N-n-1] = num++;
        //print(a);
        for(i=N-n-2; i>=n; i--) a[N-n-1][i] = num++;
        //print(a);
        for(i=N-n-2; i>n; i--) a[i][n] = num++;
        //print(a);
        if(N/2 == n)  //exit out of the recursion
        {
                print(a);
                return;
        }
        else 
                loop(a, n+1, num);
}  

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

#include <stdio.h>
#include <conio.h>

//------- prints matrix
void print(int **a, int N)
{
        printf("\n");
        
        for(int i=0,j; i<N; i++)
        {
                printf("\n\n");
                for(j=0; j<N; j++)  printf("%4d",a[i][j]);
        }

        printf("\n");
        getch();
}

void main()
{
 int N, i=0, j, n=0, num=1;

 printf("Enter the dimention of the squarte matrix: ");
 scanf("%d", &N);

 int** matrix = new int*[N];
 for( ; i<N; i++) matrix[i] = new int[N];

 for(i=0; i<N; i++)
         for(j=0; j<N; j++) matrix[i][j]=0;

 do
 { 
    //print(matrix, N);
    for(i=n; i<N-n; i++) matrix[n][i] = num++;
    //print(matrix, N);
    for(i=n+1; i<N-n; i++) matrix[i][N-n-1] = num++;
 //print(matrix, N);
    for(i=N-n-2; i>=n; i--) matrix[N-n-1][i] = num++;
 //print(matrix, N);
    for(i=N-n-2; i>n; i--) matrix[i][n] = num++;
 } while( N/2 != n++) ;

 print(matrix, N);
}

Ответ ( Нагорянский Олег )

Например, можно так:

#include "stdafx.h"
#include <iostream.h>

const int size=9;
void Integrate(int [size][size]);
void Show(int [size][size]);

namespace coord
{
      int x1=0,x2=size-1,y1=0,y2=size-1,x,y,k=1;
};

int main()
{     
      int matrix[size][size];
      Integrate(matrix);
      Show(matrix);
      return 0;
}

void Integrate(int mass[size][size])
{
 using namespace coord;
 while (x2>=int(size/2))
 {
       for (y=y1; y<=y2; y++)
       {
             x=x1;
             mass[x][y]=k;
             k++;
       }

       for (x=x1+1; x<=x2; x++)
       {
             y=y2;
             mass[x][y]=k;
             k++;
       }

       for (y=y2-1; y>y1; y--)
       {
             x=x2;
             mass[x][y]=k;
             k++;
       }
       for (x=x2; x>x1; x--)
       {
             y=y1;
             mass[x][y]=k;
             k++;
       }
       x2--;
       y2--;
       x1++;
       y1++;
 }
}

void Show(int mass[size][size])
{
      using coord::x;
      using coord::y;

      for (x=0; x<size; x++)
      {
            for (y=0; y<size; y++)
                  if (mass[x][y]<10)
                  {
                        cout << mass[x][y] << "    ";
                  }else cout << mass[x][y] << "   ";
            cout << endl;
      }
}
Книги по C/C++
Полный справочник по C++ (C++: The Complete reference)
Полный справочник по C++ (C++: The Complete reference)

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

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

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

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

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

Страница книги на Озоне
Современное проектирование на С++: Обобщенное программирование и прикладные шаблоны проектирования. (Modern C++ Design)
Современное проектирование на С++: Обобщенное программирование и прикладные шаблоны проектирования. (Modern C++ Design)

Автор: Андрей Александреску

В книге изложена новая технология программирования, представляющая собой сплав обобщенного программирования, метапрограммирования шаблонов и объектно-ориентированного программирования на С++.

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

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

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

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

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

В избранное