Одна из особенностей С++ заключается в том, что на нем с одинаковой легкостью можно написать громоздкую программу, которую потом будет трудно поддерживать (поддержка программ заключается в том, чтоб более новые версии программы были совместимы со старыми версиями, устранения различных ошибок, расширение ее возможностей и т. д.), так и компактные, эффективные, легко расширяемые и удобные в поддержке. Все зависит от того, как С++ программист использует тот потенциал, который заложен в язык С++.
Чтобы понять, о чем я говорю, давайте создадим небольшую программу, которая будет получать от пользователя данные и выводить на экран название товара, количество, его цену и сумму, которую мы должны заплатить за товар (код программы внизу).
#include <iostream>
#include <windows.h>
using namespace std;
void setName(char *name);
void setPrice(float &price);
void setQuantity(float &quantity);
char* getName(char *name);
float getPrice(float price);
float getQuantity(float quantity);
float calculatePayment(float &quantity, float &price);
void enterData(char *name, float &price, float &quantity);
void printData(char *name, float &price, float &quantity);
void manipulateData(char *name, float &price, float &quantity);
int main()
{
char name[80];
float price;
float quantity;
manipulateData(name, price, quantity);
cout << "\n\n";
system("PAUSE");
return 0;
}
void manipulateData(char *name, float &price, float &quantity)
{
enterData(name, price, quantity);
printData(name, price, quantity);
}
void enterData(char *name, float &price, float &quantity)
{
cout << "Введите название товара:\n\n";
setName(name);
cout << "\nВведите цену за единицу товара:\n\n";
setPrice(price);
cout << "\nВведите количество купленного товара:\n\n";
}
void printData(char *name, float &price, float &quantity)
{
setQuantity(quantity);
cout << "\nВы купили:\n\n";
cout << getName(name) << endl;
cout << "\nЦена за единицу товара:\n\n";
cout << getPrice(price) << endl;
cout << "\nКоличество:\n\n";
cout << getQuantity(quantity) << endl;
cout << "\nК оплате:\n\n";
cout << calculatePayment(quantity, price);
}
void setName(char *name)
{
cin >> name;
}
void setPrice(float &price)
{
cin >> price;
}
void setQuantity(float &quantity)
{
cin >> quantity;
}
float calculatePayment(float &quantity, float &price)
{
float totalPrice = quantity * price;
return totalPrice;
}
char* getName(char *name)
{
return name;
}
float getPrice(float price)
{
return price;
}
float getQuantity(float quantity)
{
return quantity;
}
Я специально оставил в функции main() лишь вызов функции manipulateData(name, price, quantity), для того, чтобы в случае необходимости достаточно было сделать дополнительный набор переменных и вызвать с ними функцию manipulateData(), чтобы функция могла работать не с одним набором переменных, а с гораздо большим количеством переменных.
Давайте изменим нашу программу, что она могла работать не с одним товаром, а с пятнадцатью. Вот что у меня получилось:
#include <iostream>
#include <windows.h>
using namespace std;
void setName(char *name);
void setPrice(float &price);
void setQuantity(float &quantity);
char* getName(char *name);
float getPrice(float price);
float getQuantity(float quantity);
float calculatePayment(float &quantity, float &price);
void enterData(char *name, float &price, float &quantity);
void printData(char *name, float &price, float &quantity);
void manipulateData(char *name, float &price, float &quantity);
int main()
{
char name1[80];
char name2[80];
char name3[80];
char name4[80];
char name5[80];
char name6[80];
char name7[80];
char name8[80];
char name9[80];
char name10[80];
char name11[80];
char name12[80];
char name13[80];
char name14[80];
char name15[80];
float price1;
float price2;
float price3;
float price4;
float price5;
float price6;
float price7;
float price8;
float price9;
float price10;
float price11;
float price12;
float price13;
float price14;
float price15;
float quantity1;
float quantity2;
float quantity3;
float quantity4;
float quantity5;
float quantity6;
float quantity7;
float quantity8;
float quantity9;
float quantity10;
float quantity11;
float quantity12;
float quantity13;
float quantity14;
float quantity15;
manipulateData(name1, price1, quantity1);
manipulateData(name2, price2, quantity2);
manipulateData(name3, price3, quantity3);
manipulateData(name4, price4, quantity4);
manipulateData(name5, price5, quantity5);
manipulateData(name6, price6, quantity6);
manipulateData(name7, price7, quantity7);
manipulateData(name8, price8, quantity8);
manipulateData(name9, price9, quantity9);
manipulateData(name10, price10, quantity10);
manipulateData(name11, price11, quantity11);
manipulateData(name12, price12, quantity12);
manipulateData(name13, price13, quantity13);
manipulateData(name14, price14, quantity14);
manipulateData(name15, price15, quantity15);
cout << "\n\n";
system("PAUSE");
return 0;
}
void manipulateData(char *name, float &price, float &quantity)
{
enterData(name, price, quantity);
printData(name, price, quantity);
}
void enterData(char *name, float &price, float &quantity)
{
cout << "Введите название товара:\n\n";
setName(name);
cout << "\nВведите цену за единицу товара:\n\n";
setPrice(price);
cout << "\nВведите количество купленного товара:\n\n";
}
void printData(char *name, float &price, float &quantity)
{
setQuantity(quantity);
cout << "\nВы купили:\n\n";
cout << getName(name) << endl;
cout << "\nЦена за единицу товара:\n\n";
cout << getPrice(price) << endl;
cout << "\nКоличество:\n\n";
cout << getQuantity(quantity) << endl;
cout << "\nК оплате:\n\n";
cout << calculatePayment(quantity, price);
cout << "\n\n";
}
void setName(char *name)
{
cin >> skipws >> name;
}
void setPrice(float &price)
{
cin >> price;
}
void setQuantity(float &quantity)
{
cin >> quantity;
}
float calculatePayment(float &quantity, float &price)
{
float totalPrice = quantity * price;
return totalPrice;
}
char* getName(char *name)
{
return name;
}
float getPrice(float price)
{
return price;
}
float getQuantity(float quantity)
{
return quantity;
}
Теперь все в порядке. Но что будет, если мы случайно допустим опечатку и вместо manipulateData(name10, price10, quantity10) напишем manipulateData(name1, price10, quantity10)? Компилятор промолчит, так синтаксических ошибок в такой программе нет. Все переменные объявлены, инструкция завершается точкой с запятой. Функции передано необходимое количество аргументов. С типами аргументов тоже все в порядке. В результате мы получаем трудно уловимую логическую ошибку. А уж что-что, а логические ошибки попортили кровь не одному программисту. А все дело в том, что наши переменные, хотя логически и связаны между собой, формально являются независимыми друг от друга. Как же их связать? Для этого есть переменные типа структура. В отличие от массивов, они связывают переменные разных типов в одну.
И так как объявить структуру в С++? Для этого нужно использовать ключевое слово «struct». Вот как мы могли бы объявить структуру типа payment:
struct payment
{
char name[80];
float price;
float quantity;
};
Обратите внимание, что после закрывающей фигурной скобки стоит точка с запятой. Ели их не будет после закрывающей фигурной скобки, компилятор выдаст ошибку. Так что будьте внимательны. Сразу после объявления структуры можно создать переменные нового типа. Пример объявления переменных тип payment приведен в низу:
struct payment
{
char name[80];
float price;
float quantity;
} item1, item2, item3, item4, item5;
Другой способ это сначала объявить тип данных, а потом создавать переменные по мере необходимости. Пример объявления нового типа данных payment и создание переменных отдельно от объявления структуры:
struct payment
{
char name[80];
float price;
float quantity;
};
payment item1, item2, item3, item4, item5;
Как видим название нашей структуры, при объявлении переменной становиться типом. Так же при создании переменной типа payment автоматически резервируется место под переменные входящие в структуру. Их еще называют членами структуры. Их так же могут называть элементами или полями. Теперь о том, как получить доступ к членам структуры... Для этого используется оператор точка. Вот как присвоить переменной значение поля структуры типа payment:
float price = item1.price;
Можно даже объявить массив переменных типа payment. Выглядеть это будет так:
payment myBill[15];
Если нам потребуется вывести значение какого-нибудь поле определенного элемента массива, то достаточно после квадратных скобок, через точку написать название нашего поля. Вот как можно вывести на экран значения поля price пятого элемента массива myBill:
cout << myBill[4].price;
Теперь используя массив из пятнадцати элементов типа payment и цикл for можно изменить нашу программу так, чтобы нам не пришлось создавать дополнительный набор переменных, если бы мы вдруг захотели увеличить количество товаров. Итак, внизу, код нашей программы с использованием структур:
#include <iostream>
#include <windows.h>
using namespace std;
struct payment
{
char name[80];
float price;
float quantity;
};
void setName(char *name);
void setPrice(float &price);
void setQuantity(float &quantity);
char* getName(char *name);
float getPrice(float price);
float getQuantity(float quantity);
float calculatePayment(float &quantity, float &price);
void enterData(char *name, float &price, float &quantity);
void printData(char *name, float &price, float &quantity);
void manipulateData(char *name, float &price, float &quantity);
int main()
{
payment myBill[15];
for(int i = 0; i < 15; i++)
{
manipulateData(myBill[i].name, myBill[i].price, myBill[i].quantity);
}
cout << "\n\n";
system("PAUSE");
return 0;
}
void manipulateData(char *name, float &price, float &quantity)
{
enterData(name, price, quantity);
printData(name, price, quantity);
}
void enterData(char *name, float &price, float &quantity)
{
cout << "Введите название товара:\n\n";
setName(name);
cout << "\nВведите цену за единицу товара:\n\n";
setPrice(price);
cout << "\nВведите количество купленного товара:\n\n";
}
void printData(char *name, float &price, float &quantity)
{
setQuantity(quantity);
cout << "\nВы купили:\n\n";
cout << getName(name) << endl;
cout << "\nЦена за единицу товара:\n\n";
cout << getPrice(price) << endl;
cout << "\nКоличество:\n\n";
cout << getQuantity(quantity) << endl;
cout << "\nК оплате:\n\n";
cout << calculatePayment(quantity, price);
cout << "\n\n";
}
void setName(char *name)
{
cin >> skipws >> name;
}
void setPrice(float &price)
{
cin >> price;
}
void setQuantity(float &quantity)
{
cin >> quantity;
}
float calculatePayment(float &quantity, float &price)
{
float total_price = quantity * price;
return total_price;
}
char* getName(char *name)
{
return name;
}
float getPrice(float price)
{
return price;
}
float getQuantity(float quantity)
{
return quantity;
}
Согласитесь, изменить размерность массива, и условие в цикле for гораздо легче, чем писать price16, price17, price18 и т. д.
В следующем уроке мы продолжим изучение структур.