Назад На главную Вперед

Таблица умножения на Си++

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

 - Ну ко попробуем нашу табличку умножения написать на этом великом и могучем. С чего начнем? Конечно же,  консольное приложение....

// Таблица умножения на C++. Консольное приложение.
// Подключаем дополнительные заголовочные файлы
#include <condefs.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <conio.h>

// заканчиваем (прерываем) список заголовочных файлов, для ускорения
// компиляции.
#pragma hdrstop

// Начало главной функции
int main(int argc, char* argv[])
{

// Объявление переменных.

int somn, i, pr;

// Запрос для ввода первого сомножителя
cout << "Input first number. ";
// Введенные с клавиатуры данные попадают во входной поток
// и присваиваются переменной somn

cin >> somn;

// Организация цикла вычислений
for (i=1; i<=10; i++)
{
// Вычисление произведения
pr = somn * i;
// Формирование результата и направление его в поток вывода
cout << somn << " x " << i << " = " << pr << endl;
}
// Окончание цикла вычислений и вывода
// Ожидание нажатия клавиши

getch();
return 0;
// Главная функция после удачного выполнения возвращает 0
}
 

 - И чем же этот код отличается от простого Си.
 - Если интересно посмотри выше, то о чем ты просишь мы уже проходили.
 - И как же там с размером файла программы. Ничего себе: почти 170 килобайт. Кому и зачем может потребоваться такое консольное приложение. А что ни будь обычное для Windows.
 - Давай попробуем. Среда программирования С-Builder от Borland ничем оособенным не выделяется: накидал кнопок да Едитов, а о кодировании и говорить не приходится. Ну, что, вперед...

// Программа: таблица умножения на C++
// Вариант с использованием VCL, то есть Visual Component Library
// О чем мы сразу же и предупреждаем нашу программу

#include <vcl.h>
/
/ Обрываем список заголовочных файлов
#pragma hdrstop

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

#include "tab_um_cpp.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
// В файле с расширением dfm описаны использованные нами ресурсы
#pragma resource "*.dfm"
// Объявляем переменную Form1, типа TForm1
TForm1 *Form1;

// Казалось бы функция ничего не делает, но это кажущаяся бесполезность
// Именно она и показывает нашу форму (окно) на экране

__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}

// Вот она наша главная функция, которая и выполняет всю работу
void __fastcall TForm1::Button1Click(TObject *Sender)
{
// Объявляем необходимые переменные
int Somn;
char szBuf[1];

// Поместим в символьную переменную только первый символ из поля редактирования
// если мы ошиблись при вводе и поместили туда многозначное число

StrLCopy(szBuf, Edit1->Text.c_str(),1);
//И вернем это число в полее ввода
Edit1->Text=szBuf;

// Как в старом добром Паскале преобразуем символное значение в целое
Somn = StrToInt(Edit1->Text);
// Очистим текстовое поле перед выводом
Form1->Memo1->Clear();

// Организуем формирование символьной строки в цикле получая произведение перед
//
выводом

for (int K=1; K<11; K++)
{
Form1->Memo1->Text = Memo1->Text + IntToStr(Somn)+ " x " + IntToStr(K) + " = " + IntToStr(Somn*K) + CHAR(13)+ CHAR(10);
}
}
// Работа функции, вызываемой в ответ на нажатие кнопки на форме завершена

// А это реакция на кнопочку, которая заканчивает работу приложения

void __fastcall TForm1::Button2Click(TObject *Sender)
{
Application->Terminate();
}

// В заключение мельком упомяну о некоторых вещах, о которых не рассказал
// внутри кода.
// -> это оператор косвенного доступа к элементам структур. В отличии от простой
//точки между элементами, которая выполняет прямой доступ к ним.
// :: это оператор разрешения видимости. Он позволяет обращаться к глобальным переменным.
 

  - В программах на C++ множество мелочей, которые трудно объяснить логическими обоснованиями. Чаще всего вы даже в очень толковой документации  увидите объяснение: это нужно делать вот так, чтобы получить вот это.  Я не великий знаток C++. Введите название непонятного термина в строке поиска в Интернете. Вы наверняка найдете кучу ссылок, которые смогут вам помочь.

 


  -
Вроде получилось. Смотри работает. А размер программы 25 с небольшим килобайт: неплохо.
  - Да. программа и код компактны. Как будь-то это совсем и не  Windows-программа. Создается  визуально, выглядит странно. А, что, если без выкрутасов.
 - Давай попробуем без выкрутасов.

//Таблица умножения на C++ без использования VCL на чистом API
#include <vcl.h>
// А зачем тогда строчка выше этой?
// Да, каюсь, в программе пришлось
// воспользовался несколькими функциями из этого набора
#include <windows.h>
#include <stdio.h>

// В файле ресурсов всего одна строчка про оригинальную иконку (NK)
// Даже в простой программе нельзя терять лицо фирмы
USERES("nk.RES");

// Объявление указателей на компоненты нашей программы
HWND LTEXT;
HWND sED1;
HWND sED2;
HWND sBUTT1;

//Объявление нашей оконной функции со специальным указателем на то,
// что она является функцией обратного вызова

LRESULT CALLBACK TabUmnWndProc ( HWND, UINT, UINT, LONG);

//Наша главная функция и куча параметров для ее вызова
int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR IpszCmdParam, int nCmdShow )
{
// Объявление локальных переменных
HWND hWnd;
WNDCLASS WndClass;
MSG Msg;
char szClassName[]= "TABUMN";

/* Заполняем структуру типа WNDCLASS */

WndClass.style = CS_HREDRAW | CS_VREDRAW;
WndClass.lpfnWndProc = TabUmnWndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon (hInstance, "MYICON");
WndClass.hCursor = LoadCursor(NULL, IDI_APPLICATION);
WndClass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = szClassName;

/* Регистрируем создаваемый класс */

if ( !RegisterClass(&WndClass))
{
// Если класс почему то не зарегистрировался, выдадим сообщение
MessageBox(NULL,"Проблемы при регистрации класса","Егтог", MB_OK);
return 0;
}

// А если класс зарегистрировался то создадим его его экземпляр: наше окно
hWnd = CreateWindow(szClassName, " Таблица умножения",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
260, 350,
NULL, NULL,
hInstance, NULL);

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

LTEXT=CreateWindow("STATIC", "Введи сомножитель",
WS_CHILD | WS_VISIBLE | SS_CENTER | WS_BORDER,
15, 20,
160, 20,
hWnd, NULL,
hInstance, 0);

// А теперь окошечко текстового редактирования (однострочное)
sED1=CreateWindow("EDIT", "0",
WS_CHILD | WS_VISIBLE | WS_BORDER,
15, 52,
60, 25,
hWnd, NULL,
hInstance, 0);

// А теперь кнопочку
sBUTT1=CreateWindow("BUTTON", "Расчет",
WS_CHILD | WS_VISIBLE | WS_BORDER,
170, 90,
60, 30,
hWnd, NULL,
hInstance, 0);

// А теперь окно редактирования многострочное
sED2=CreateWindow("EDIT", "",
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE,
15, 90,
130, 200,
hWnd, NULL,
hInstance, 0);

/* Покажем наше главное окно, и заставим прорисоваться */

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

/* А теперь все тот же цикл получения и обработки сообщений */
while(GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}

// И передача нашей оконной функции, полученных сообщений
return Msg.wParam;
}

//А теперь сама оконная функция
LRESULT CALLBACK TabUmnWndProc (HWND hWnd, UINT Msg,
UINT wParam, LONG lParam)
{

// Локальные переменные
char szBuf[2];
int iSomn;
int iPr;
char lpBuf[1000];
char sTemp[1];
// Одно из узких мест Си - хлеб для хакеров. ???

// Переключатель выбора реакции на сообщения
switch(Msg)
{

// Если поступило сообщение с командой то посмотрим,
// что там нужно выполнять

case WM_COMMAND:
{
// Ага это наша кнопка
if (lParam == INT(sBUTT1))
{
// Тогда в переменную szBuf поместим данные из поля ввода
// первого сомножителя.

GetWindowText(sED1, szBuf, 2);

// Очистим исходную строку, если в ней больше одной цифры
strcpy(lpBuf, sTemp);
// И забросим число в то же самое окно ввода
SetWindowText(sED2, lpBuf);

// А теперь цикл вывода результатов перемножения
for (int K=1; K<11; K++)
{
// Вот, как раз функция из VCL, о которых я упоминал вначале
iSomn=StrToInt(szBuf);

// Получим произведение
iPr = iSomn * K;

// Сформируем временную строку с частью вывода.
// Ну нет в СИ строчных переменных: вот и приходится так изголяться

sprintf(sTemp, "%d x %d = %d", iSomn, K, iPr);

// Закинем эту переменную в буфер для вывода
strcat(lpBuf, sTemp);

// Теперь сформируем остаток для перевода вывода на другую строку
sTemp[0]='\r'; sTemp[1]='\n'; sTemp[2]='\0';
// Сначала добавим к нашей строке.
// А потом, подготовленную строку к буферу

strcat(lpBuf, sTemp);

}

// Теперь наш символьный буфер с сформированной строкой
// в текстовое поле.

SetWindowText(sED2, lpBuf);
}
// после выполнения вернем 0, ведь это же функция,
// она обязана чего то возвращать

return 0;
}
// Обработаем еще одно сообщение, которое командует нашей программе
// сворачивать работу

case WM_DESTROY:
PostQuitMessage(0);
return 0;
}

// А все обилие сообщений по операциям работы с окном и
// другие полезные вещи заставим обрабатывать функцию по умолчанию.

return DefWindowProc(hWnd, Msg, wParam, lParam);
}

 

 
 - Что то в этом C++ - ном коде до боли знакомое. А вспомнил! Это же очень напоминает  Ассемблер, а как с размером?  12800 байт - почти рекорд.
 - Как код то меняется, а ведь практически одно и то же. Но разница между консольным приложением, программой с VCL и программой на API очень существенная. Вот и скажи потом, что программирование это не творчество.

  Назад На главную Вперед  

Другая информатика. (C) Публикация на draginf.ru. При использовании материалов ссылка на сайт обязательна.