Advertisement
Guest User

Untitled

a guest
Nov 25th, 2017
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.33 KB | None | 0 0
  1. //#define _WINSOCK_DEPRECATED_NO_WARNINGS
  2. #pragma comment(lib, "ws2_32.lib")
  3. #include <WinSock2.h>
  4. #include <WS2tcpip.h>
  5. #include <iostream>
  6. #include <vector>
  7. //#pragma comment(lib, "ws2_32.lib")
  8.  
  9. /*
  10.  
  11. TECHNOLOGIE SIECIOWE
  12. LABORATORIA
  13.  
  14. Zajęcia numer: 7
  15. Zadanie numer: 6
  16.  
  17. Implementacja autorskiego protokołu binarnego.
  18. Serwer.
  19.  
  20. by: Artur Bronka, Łukasz Dobek
  21.  
  22. */
  23.  
  24. // Funkcje konieczne do zamiany naglówków.
  25. std::vector<char> headerChanger(std::vector<bool> tab);    
  26. std::vector<bool> headerBinChanger(std::vector<char> tab);
  27. std::vector<bool> binary(std::vector<char> piaskownica);
  28. std::vector<char> decimal(std::vector<bool> piasek);
  29.  
  30. // Wypisywanie wektora.
  31. template <typename T>
  32. void wypisz(std::vector<T> tab);
  33.  
  34. // Funkcje wykorzystywane do zamiany liczb.
  35. std::vector<bool> dec_to_bin(int liczba, int wielkosc);    
  36. int bin_to_dec(std::vector<bool> tab);
  37.  
  38.  
  39. // Operacje wykonywane na argumentach, ktorych wyniki i ID przesylane sa w naglowku.
  40. int add(int a, int b);                                     
  41. int subtract(int a, int b);
  42. int divide(int a, int b);
  43. int multiply(int a, int b);
  44. int whichMax(int a, int b);
  45. int whichMin(int a, int b);
  46. int modulo(int a, int b);
  47. int silnia(int arg);
  48. bool isEqual(int a, int b);
  49.  
  50. // Zmienna odpowiedzialna za numerowanie klientow i nadawanie ID.
  51. int id_int = 0;                                            
  52.  
  53. int main() {
  54.  
  55.     int n = 0;
  56.     std::cout << "Na ilu maksymalnych klientow chcesz pozwolic?" << std::endl << "> ";
  57.     std::cin >> n;
  58.  
  59.     WSAData wsaData; // Zmienna potrzebna do otworzenia socketa.
  60.     WORD DllVersion = MAKEWORD(2, 1);
  61.     if (WSAStartup(DllVersion, &wsaData) != 0){
  62.  
  63.         // Warunek pozwalający na podstawową obsługę błędów przy starcie winsocka.
  64.         MessageBoxA(NULL, "Start Winsocka zostal przerwany.", "Blad", MB_OK | MB_ICONERROR);
  65.  
  66.         // Wyświetla okienko dialogowe.
  67.         exit(1);
  68.     }
  69.  
  70.     // Struktura odpowiedzialna za adresację IP.
  71.     SOCKADDR_IN addr;
  72.     int addrlen = sizeof(addr);
  73.     // W przypadku łączenia dwóch komputerów, tutaj wpisujemy swój własny adres jako serwer.
  74.     // Na komputerze klienckim wpisujemy adres serwera.
  75.     // W przypadku korzystania z protokołu na komputerze lokalnym używamy adresu loopback: 127.0.0.1 na obu wersjach aplikacji.
  76.     inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
  77.     addr.sin_port = htons(1111);
  78.     addr.sin_family = AF_INET;
  79.  
  80.     // Socket odpowiedzialny za nasłuchiwanie.
  81.     SOCKET sListen = socket(AF_INET, SOCK_STREAM, NULL);
  82.  
  83.     // Przypisujemy adres do socketa odpowiedzialnego za nasłuchiwanie.
  84.     bind(sListen, (SOCKADDR*)&addr, sizeof(addr));
  85.  
  86.     // Funkcja odpowiedzialna za nasłuchiwanie.
  87.     listen(sListen, SOMAXCONN);
  88.  
  89.     std::cout << "Serwer wlaczony. Oczekuje na polaczenia.  \nAby zamknac, wyslij kombinacje klawiszy CTRL+C." << std::endl << std::endl;
  90.  
  91.     // Socket odpowiedzialny za połączenie z klientem.
  92.     SOCKET newConnection;
  93.  
  94.     // Zliczamy występujące połączenia. Przyzwalamy na "n" maksymalnych połączeń, przy czym zmienna "n" deklarowana na początku programu.
  95.     for (int i = 0; i < n; i++) {
  96.  
  97.         // Akceptujemy socket na zasadzie przypisania połączenia znalezionego w trakcie nasłuchiwania
  98.         // do socketa odpowiedzialnego za połączenie z klientem.
  99.         newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen);
  100.  
  101.         // Zmienna odpowiedzialna za numerowanie klientów.
  102.         int clientNum;
  103.  
  104.         // Podstawowa obsługa błędów, w przypadku braku połączenia pomiędzy klientem a serwerem.
  105.         if (newConnection == 0) {
  106.             std::cout << "Wystapil blad zwiazany z brakiem polaczenia pomiedzy serwerem a klientem.";
  107.         } else {
  108.             // Numerowanie klienta.
  109.             clientNum = id_int;
  110.             std::cout << std::endl << "Klient " << clientNum << " podlaczony." << std::endl;
  111.  
  112.             /*
  113.            
  114.             std::vector<bool> header - struktura odpowiedzialna za nagłówek danych przesyłany w trakcie transmisji.
  115.             Zawiera ona pola:
  116.             - operacja - 3 bity;
  117.             - status - 4 bity;
  118.             - długość pola danych - 32 bity;
  119.             - pole danych - zmienny rozmiar.
  120.             Na pole danych składają się sub-pola:
  121.             - ID - 6 bitów;
  122.             - argumenty - zmienny rozmiar, zależny od klienta;
  123.             - wynik - zmienny rozmiar, zależny od rozmiaru argumentów i wykonywanej na nich operacji;
  124.             - wynik silnii - 10 bitów.
  125.  
  126.             */
  127.             std::vector<bool> header;
  128.  
  129.             // Pole operacje (szerzej opisane po stronie klienta.
  130.             std::vector<bool> operacje = { 0,0,0 };
  131.  
  132.             /*
  133.  
  134.             Pole status domyślnie wypełniamy 0. Każda kolejna operacja wysyłania/odbierania określonych danych
  135.             wpływa na jego wartość.  Przykładowo - odebranie nagłówka po stronie klienta z wypełnioną częścią
  136.             ID oraz statusu ustawi jego wartość na 0011.
  137.            
  138.             */
  139.             std::vector<bool> status = { 0,0,0,0 };
  140.  
  141.             // Liczba odpowiadająca AKTUALNEJ długości danych, którą umieszczany w nagłówku. Długość ta może ulec zmianie.
  142.             int dataLength = 6+64+3;
  143.  
  144.             // Zamiana długości pola danych z liczby dziesiętnej na binarną z pomocą tablicy.
  145.             std::vector<bool> vecDataLength = dec_to_bin(dataLength, 32);
  146.  
  147.             // Pole ID.
  148.             // Zamiana ID zapisanego w postaci dziesiętnej na binarną z pomocą tablicy.
  149.             std::vector<bool> ID = dec_to_bin(id_int, 6);
  150.            
  151.             // Pole długość nagłówka.
  152.             // Całkowita długość nagłówka. Początkowy nagłówek, będzie miał długość 112 bitów, czyli 14 bajtów.
  153.             int headerLength = 112;
  154.             std::vector<bool> headerLengthVec = dec_to_bin(headerLength, 64);
  155.  
  156.             // Pole wielkość dopełnienia.
  157.             // Określa wielkość dopełnienia do wielokrotności liczby 8. Zapisywane na trzech bitach.
  158.             int fill = 0;
  159.             std::vector<bool> fillVec = dec_to_bin(fill, 3);
  160.  
  161.             // Wypełnienie pola operacji nagłówka zerami - klient jeszcze nie podjął decyzji
  162.             // którą z 8 operacji będzie chciał wykonać.
  163.             for (int i = 0; i < 3; i++) {
  164.                 header.push_back(0);
  165.             }
  166.  
  167.             // Wypełnienie pola statusu nagłówka.
  168.             for (int i = 0; i < 4; i++) {
  169.                 header.push_back(status[i]);
  170.             }
  171.  
  172.             // Wypełnienie pola długość danych nagłówka.
  173.             for (int i = 0; i < 32; i++) {
  174.                 header.push_back(vecDataLength[i]);
  175.             }
  176.  
  177.             // Wypełnienie pola ID nagłówka.
  178.             for (int i = 0; i < 6; i++) {
  179.                 header.push_back(ID[i]);
  180.             }
  181.  
  182.             // Wypełnienie pola długość nagłówka.
  183.             for (int i = 0; i < 64; i++) {
  184.                 header.push_back(headerLengthVec[i]);
  185.             }
  186.  
  187.             // Wypełnienie pola długość dopełnienia.
  188.             for (int i = 0; i < 3; i++) {
  189.                 header.push_back(fillVec[i]);
  190.             }
  191.  
  192.             // Ustawienie statusu na 1 - Wysyłam header z wypełnionymi polami ID oraz status.
  193.             status[0] = 0;
  194.             status[1] = 0;
  195.             status[2] = 0;
  196.             status[3] = 1;
  197.  
  198.             // Wypełnienie pola status nagłówka.
  199.             for (int i = 3; i < 7; i++) {
  200.                 header[i] = status[i - 3];
  201.             }
  202.             // Konwersja vector<bool> -> vector<char> z pomocą funkcji.
  203.             std::vector<char> headerCharToSend = decimal(header);
  204.            
  205.             // Przesłanie klientowi faktycznego nagłówka.
  206.             send(newConnection, &headerCharToSend[0], headerCharToSend.size() , NULL);
  207.  
  208.             /*
  209.            
  210.             Operacje wykonywane po stronie klienta...
  211.            
  212.             */
  213.             std::cout << "Odbieram dane..." << std::endl;
  214.  
  215.             // Odbieranie nagłówka z wpisaną nową długością nagłówka. Potem przyjmiemy faktyczne dane.
  216.             std::vector<char> headerCharReceived(14);
  217.             recv(newConnection, &headerCharReceived[0], headerCharReceived.size(), NULL);
  218.             std::vector<bool> headerBinRecv = binary(headerCharReceived);
  219.  
  220.             // Wyłuskanie wartości długości pola danych.
  221.             for (int i = 0; i < 32; i++) {
  222.                 vecDataLength[i] = headerBinRecv[i + 7];
  223.             }
  224.             dataLength = bin_to_dec(vecDataLength);
  225.             for (int i = 0; i < 64; i++) {
  226.                 headerLengthVec[i] = headerBinRecv[i + 45];
  227.             }
  228.             headerLength = bin_to_dec(headerLengthVec);
  229.             for (int i = 0; i < 3; i++) {
  230.                 fillVec[i] = headerBinRecv[i + 109];
  231.             }
  232.             fill = bin_to_dec(fillVec);
  233.             // Modyfikacja długości nagłówka na rzecz odebrania pełnych danych od klienta.
  234.             std::vector<char> headerArgRcv(headerLength / 8);
  235.             recv(newConnection, &headerArgRcv[0], headerArgRcv.size(), NULL);
  236.             headerBinRecv = binary(headerArgRcv);
  237.             headerBinRecv.resize(headerLength - fill);
  238.             std::cout << std::endl;
  239.             headerLength -= fill;
  240.             dataLength -= fill;
  241.             // Modyfikacja pola status. Status 4 - odebrano dane od klienta.
  242.             status[0] = 0;
  243.             status[1] = 1;
  244.             status[2] = 0;
  245.             status[3] = 0;
  246.  
  247.             // Uzupełnienie pól nagłówka: status oraz długość.
  248.             for (int i = 3; i < 7; i++) {
  249.                 headerBinRecv[i] = status[i - 3];
  250.             }
  251.  
  252.             // Modyfikacja lokalnej wartości zmiennej długość pola danych. Zmiana o sumę rozmiarów dwóch argumentów.
  253.             int wielkoscArgumentu = (dataLength - 81) / 2;
  254.             // Modyfikacja lokalnej tablicy odpowiedzialnej za reprezentację pola operacji.
  255.             operacje[0] = headerBinRecv[0];
  256.             operacje[1] = headerBinRecv[1];
  257.             operacje[2] = headerBinRecv[2];
  258.  
  259.             // Zamiana argumentów z nagłówka, na liczby dziesiętne.
  260.             std::vector<bool> argX;
  261.             std::vector<bool> argY;
  262.             std::vector<bool> argument;
  263.  
  264.             for (int i = 0; i < wielkoscArgumentu; i++) {
  265.                 argX.push_back(headerBinRecv[i + 112]);
  266.             }
  267.             for (int i = 0; i < wielkoscArgumentu; i++) {
  268.                 argY.push_back(headerBinRecv[i + 112 + wielkoscArgumentu]);
  269.             }
  270.             for (int i = 0; i < 8; i++) {
  271.                 argument.push_back(headerBinRecv[i + 112 + wielkoscArgumentu + wielkoscArgumentu]);
  272.             }
  273.             int argX_int = bin_to_dec(argX);
  274.             int argY_int = bin_to_dec(argY);
  275.             int argument_int = bin_to_dec(argument);
  276.             std::cout << "Pierwsza liczba: " << argX_int << std::endl
  277.                 << "Druga liczba: " << argY_int << std::endl;
  278.  
  279.             // Tablica w której przechowujemy wynik. Jej wielkość ustalamy na podwojoną wartość rozmiaru argumentów.
  280.             std::vector<bool> vecResult(wielkoscArgumentu * 2);
  281.  
  282.             // W zależności od podanej operacji wykonujemy zestaw określonych funkcji.
  283.             // Jedyną różnicą jest operacja odejmowania, w której ostatni bit liczby ustalamy jako kod znaku.
  284.             if (operacje[0] == 0 && operacje[1] == 0 && operacje[2] == 0) {
  285.                 std::cout << "Wynik dodawania: " << add(argX_int, argY_int) << std::endl;
  286.                 vecResult = dec_to_bin(add(argX_int, argY_int), vecResult.size());
  287.             }
  288.             else if (operacje[0] == 0 && operacje[1] == 0 && operacje[2] == 1) {
  289.                 std::cout << "Wynik odejmowania: " << subtract(argX_int, argY_int) << std::endl;
  290.                 vecResult = dec_to_bin(subtract(argX_int, argY_int), vecResult.size());
  291.                 if (subtract(argX_int, argY_int) < 0) vecResult[0] = 1;
  292.             }
  293.             else if (operacje[0] == 0 && operacje[1] == 1 && operacje[2] == 0) {
  294.                 std::cout << "Wynik mnozenie: " << multiply(argX_int, argY_int) << std::endl;
  295.                 vecResult = dec_to_bin(multiply(argX_int, argY_int), vecResult.size());
  296.             }
  297.             else if (operacje[0] == 0 && operacje[1] == 1 && operacje[2] == 1) {
  298.                 std::cout << "Wynik dzielenia: " << divide(argX_int, argY_int) << std::endl;
  299.                 vecResult = dec_to_bin(divide(argX_int, argY_int), vecResult.size());
  300.             }
  301.             else if (operacje[0] == 1 && operacje[1] == 0 && operacje[2] == 0) {
  302.                 std::cout << "Ktora wieksza: " << whichMax(argX_int, argY_int) << std::endl;
  303.                 vecResult = dec_to_bin(whichMax(argX_int, argY_int), vecResult.size());
  304.             }
  305.             else if (operacje[0] == 1 && operacje[1] == 0 && operacje[2] == 1) {
  306.                 std::cout << "Ktora mniejsza: " << whichMin(argX_int, argY_int) << std::endl;
  307.                 vecResult = dec_to_bin(whichMin(argX_int, argY_int), vecResult.size());
  308.             }
  309.             else if (operacje[0] == 1 && operacje[1] == 1 && operacje[2] == 0) {
  310.                 std::cout << "Czy liczby sa rowne? " << isEqual(argX_int, argY_int) << std::endl;
  311.                 vecResult[0] = isEqual(argX_int, argY_int);
  312.             }
  313.             else if (operacje[0] == 1 && operacje[1] == 1 && operacje[2] == 1) {
  314.                 std::cout << "Wynik dzielenia modulo: " << modulo(argX_int, argY_int) << std::endl;
  315.                 vecResult = dec_to_bin(modulo(argX_int, argY_int), vecResult.size());
  316.             }
  317.  
  318.  
  319.  
  320.             // Modyfikacja lokalnego pola długość pola danych.
  321.             dataLength += wielkoscArgumentu * 2;           
  322.             headerLength += wielkoscArgumentu * 2;
  323.             // Ustalamy maksymalną wielkość tablicy odpowiadającej za przechowywanie wyniku silnii
  324.             // na 10 ze względu na szybko rosnacą złożoność obliczeniową.
  325.             std::vector<bool> resultSilnia(10);
  326.    
  327.             for (int i = 0; i < 10; i++) {
  328.                 resultSilnia[i] = 0;
  329.             }
  330.             // Obliczanie silnii.
  331.             if (argument_int == 1) {
  332.                 if (argX_int > 6) {
  333.                     std::cout << std::endl << "Wartosc obliczonej silnii jest zbyt duza, zeby przeslac ja do klienta." << std::endl;
  334.                 } else {
  335.                     resultSilnia = dec_to_bin(silnia(argX_int), 10);
  336.                     std::cout << "Silnia z " << argX_int << " = " << silnia(argX_int);
  337.                 }
  338.             } else if (argument_int == 2) {
  339.                 if (argY_int > 6) {
  340.                     std::cout << std::endl << "Wartosc obliczonej silnii jest zbyt duza, zeby przeslac ja do klienta." << std::endl;
  341.                 } else {
  342.                     resultSilnia = dec_to_bin(silnia(argY_int), 10);
  343.                     std::cout << "Silnia z " << argY_int << " = " << silnia(argY_int) << std::endl;
  344.                 }
  345.             }
  346.             std::vector<char> headerCharToSendResult = decimal(headerBinRecv);
  347.  
  348.             std::cout << std::endl;
  349.             // Zwiekszenie liczby odpowiadającej długości pola danych.
  350.             dataLength += 10;
  351.             headerLength += 10;
  352.             fill = 8 - (headerLength % 8);
  353.             headerLength += fill;
  354.             dataLength += fill;
  355.             vecDataLength = dec_to_bin(dataLength, 32);
  356.             fillVec = dec_to_bin(fill, 3);
  357.             for (int i = 7; i < 39; i++) {
  358.                 headerBinRecv[i] = vecDataLength[i - 7];
  359.             }
  360.             for (int i = 45; i < 109; i++) {
  361.                 headerBinRecv[i] = headerLengthVec[i - 45];
  362.             }
  363.             for (int i = 109; i < 112; i++) {
  364.                 headerBinRecv[i] = fillVec[i - 109];
  365.             }
  366.             // Uzupełnienie nagłówka odpowiednimi danymi.
  367.             for (int i = 7; i < 39; i++) {
  368.                 headerBinRecv[i] = vecDataLength[i - 7];
  369.             }
  370.             for (int i = 0; i < vecResult.size(); i++) {
  371.                 headerBinRecv.push_back(vecResult[i]);
  372.             }
  373.             for (int i = 0; i < resultSilnia.size(); i++) {
  374.                 headerBinRecv.push_back(resultSilnia[i]);
  375.             }
  376.  
  377.             // Ustawienie statusu 5 - wysłanie ostatecznych danych.
  378.             status[0] = 0;
  379.             status[1] = 1;
  380.             status[2] = 0;
  381.             status[3] = 1;
  382.  
  383.             for (int i = 3; i < 7; i++) {
  384.                 headerBinRecv[i] = status[i - 3];
  385.             }
  386.  
  387.             // Przesłanie ostatecznych danych wynikowych w postaci nagłówka (w postaci tablicy char utworzonej z tablicy bool).
  388.             headerCharToSendResult = decimal(headerBinRecv);
  389.             send(newConnection, &headerCharToSendResult[0], headerCharToSendResult.size(), NULL);
  390.             std::cout << std::endl;
  391.             // Zwiększenie liczby ID klienta dla potencjalnego następnego klienta.
  392.             id_int++;
  393.  
  394.             std::cout << "Zamykanie polaczenia z klientem: " << clientNum << std::endl << std::endl;
  395.             closesocket(newConnection);
  396.         }
  397.     }
  398.     return 0;
  399. }
  400.  
  401. std::vector<char> headerChanger(std::vector<bool> tab) {
  402.     std::vector<char> header(tab.size());
  403.     for (int i = 0; i < tab.size(); i++) {
  404.         if (tab[i] == 0) {
  405.             header[i] = '0';
  406.         }
  407.         else if (tab[i] == 1) {
  408.             header[i] = '1';
  409.         }
  410.     }
  411.     return header;
  412. }
  413.  
  414. std::vector<bool> headerBinChanger(std::vector<char> tab) {
  415.     std::vector<bool> header(tab.size());
  416.     for (int i = 0; i < tab.size(); i++) {
  417.         if (tab[i] == '0') {
  418.             header[i] = 0;
  419.         }
  420.         else if (tab[i] == '1') {
  421.             header[i] = 1;
  422.         }
  423.     }
  424.     return header;
  425. }
  426.  
  427. std::vector<bool> dec_to_bin(int liczba, int wielkosc)
  428. {
  429.     std::vector<bool> tab(wielkosc);
  430.  
  431.  
  432.     int i = wielkosc - 1;
  433.     while (liczba) //dopóki liczba będzie różna od zera
  434.     {
  435.         tab[i--] = liczba % 2;
  436.         liczba /= 2;
  437.     }
  438.     return tab;
  439. }
  440.  
  441.  
  442. int bin_to_dec(std::vector<bool> tab) {
  443.     int wielkosc = tab.size();
  444.     int dec = 0;
  445.     for (int i = 0; i < wielkosc; i++) {
  446.         int pom = tab[i] * pow(2, wielkosc - i - 1);
  447.         dec += pom;
  448.     }
  449.     return dec;
  450. }
  451.  
  452. int add(int a, int b) {
  453.     return a + b;
  454. }
  455. int subtract(int a, int b) {
  456.     return a - b;
  457. }
  458. int divide(int a, int b) {
  459.     return a / b;
  460. }
  461. int multiply(int a, int b) {
  462.     return a*b;
  463. }
  464. int whichMax(int a, int b) {
  465.     if (a > b) return a; else return b;
  466. }
  467. int whichMin(int a, int b) {
  468.     if (a > b) return b; else return a;
  469. }
  470. bool isEqual(int a, int b) {
  471.     if (a == b) return true; else return false;
  472. }
  473. int modulo(int a, int b) {
  474.     return a%b;
  475. }
  476. int silnia(int arg) {
  477.     if (arg < 2) return arg;
  478.     return arg*silnia(arg - 1);
  479. }
  480.  
  481. std::vector<char> decimal(std::vector<bool> piasek) {
  482.     std::vector<char> piaskownica;
  483.     if (piasek.size() % 8 == 0) {
  484.         piaskownica.resize(piasek.size() / 8);
  485.         for (int i = 0; i < piaskownica.size(); i++) {
  486.             int pom2 = 8 * i;
  487.             std::vector<bool> pom(8);
  488.             for (int j = 0; j < 8; j++) {
  489.                 pom[j] = piasek[pom2 + j];
  490.             }
  491.             piaskownica[i] = bin_to_dec(pom);
  492.         }
  493.     }
  494.     else {
  495.         int pom = piasek.size() % 8;
  496.         int dopelnienie = 8 - pom;
  497.         piaskownica.resize((piasek.size() + dopelnienie) / 8);
  498.         for (int i = 0; i < piaskownica.size(); i++) {
  499.             int pom2 = 8 * i;
  500.             std::vector<bool> vecpom(8);
  501.             for (int j = 0; j < 8; j++) {
  502.                 if (pom2 + j >= piasek.size()) {
  503.                     vecpom[j] = 0;
  504.                 }
  505.                 else vecpom[j] = piasek[pom2 + j];
  506.             }
  507.             piaskownica[i] = bin_to_dec(vecpom);
  508.         }
  509.     }
  510.     return piaskownica;
  511. }
  512.  
  513. std::vector<bool> binary(std::vector<char> piaskownica) {
  514.     std::vector<bool> header;
  515.     std::vector<bool> pom(8);
  516.     for (int i = 0; i < piaskownica.size(); i++) {
  517.         unsigned char k = piaskownica[i];
  518.         int test = k;
  519.         pom = dec_to_bin(test, 8);
  520.         for (int j = 0; j < pom.size(); j++) {
  521.             header.push_back(pom[j]);
  522.         }
  523.     }
  524.     return header;
  525. }
  526.  
  527. template<typename T>
  528. void wypisz(std::vector<T> tab){
  529.     for (int i = 0; i < tab.size(); i++) {
  530.         std::cout << tab[i];
  531.     }
  532. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement