V linuxe funguje diakritika bez uprav vdaka tomu ze pouziva utf-8 kodovanie ktore je viacmnej kompatibilne s ascii (obydve maju 1byte code unit). Windows pouziva daku verziu unicode16(2byte code unit) ci nieco take. Zrejme budes musiet povedat terminalu ze ocakavas vstup v takomto kodovani a to sa zrejme nastavuje nestandartnymi funkciami (alebo miesto main pouzies _wmain...). Skus sa pozret sem http://msdn.microsoft.com/en-us/library/bky3b5dh.aspx
Příspěvky odeslané z IP adresy 95.105.152.–
Len tak pre zaujimavost, vysla nava verzia c++. Je to mensi update veci ktore sa nestihli pridat do c++11. Najzaujmavejsie su podla mna polymorficke lambda funkcie a moznost dedukovat navratovu hodnotu vo funkciach pomocou decltype(auto). Zaujimave je hlavne to ze uz teraz je z velkej casti podporovana v kompilatoroch ako clang a gcc. Viac info napr tu: http://meetingcpp.com/index.php/br/items/looking-at-c14.html
Dalsia verzia ma pracovny nazov c++1z a mala by uz koncne obsahovat koncepty a std::filesystem.
Dam sem este upravenu verziu ktora ide skompilovat s c++11 kompilatorom (decltype(auto) vyzaduje c++14). Kod som aj trochu upravyl a dosiahol som zaujimavu vlastnost, cely kod nevyuiva ziadnu dynamicku alokaciu . S variadic templatmi sa daju robit divy, skoda ze je ten kod tak hnusny.
#include <iostream>
#include <memory>
#include <tuple>
#include <algorithm>
#include <array>
template <class Key>
struct MenuItemBaseKey{
const Key key;
using key_t = Key;
template <class K>MenuItemBaseKey(K&& key)
:key(std::forward<K>(key)){}
virtual bool operator()(){}
};
template <class Key, class Value>
struct MenuItemBase : MenuItemBaseKey<Key>{
Value value;
template <class Ostream> friend Ostream& operator<<(Ostream& out, const MenuItemBase& x){
return out << x.key << ") " << x.value << std::endl;
}
template <class K, class V>MenuItemBase(K&& key, V&& value)
:MenuItemBaseKey<Key>(std::forward<K>(key)), value(std::forward<V>(value)){}
bool operator()()override = 0;
};
template <class Key, class Value, class Action>
struct MenuItem final : MenuItemBase<Key, Value> {
private:
using base = MenuItemBase<Key, Value>;
Action action;
public:
template <class K, class V>MenuItem(K&& key, V&& value, Action action = Action())
:base(std::forward<K>(key), std::forward<V>(value)), action(action){}
bool operator()()override{return action();};
};
template <int N, class Key, class Value, class... Items>
struct MenuItemGet;
template <class Key, class Value, class I, class... Items>
struct Menu: MenuItemBase<Key, Value>{
template <int N, class K, class V, class... Is>
friend class MenuItemGet;
protected:
using base = MenuItemBase<Key, Value>;
using item_key_t = typename I::key_t;
std::tuple<I, Items...> items;
std::array<MenuItemBaseKey<item_key_t>*, sizeof...(Items)+1> order;
bool inicialized = false;
static bool item_cmp(const MenuItemBaseKey<item_key_t>* a, const MenuItemBaseKey<item_key_t>* b){return a->key < b->key;}
void reg_items(){
MenuItemGet<static_cast<int>(sizeof...(Items)), Key, Value, I, Items...>::reg(*this);
std::sort(std::begin(order), std::end(order),item_cmp);
inicialized = true;
}
template <class K>
MenuItemBaseKey<item_key_t>* find(K&& in){
if(!inicialized)reg_items();
MenuItemBaseKey<item_key_t> key{std::forward<K>(in)};
auto item = std::lower_bound(std::begin(order), std::end(order), &key, item_cmp);
return (item != std::end(order))?(*item):(nullptr);
}
public:
template <class K, class V, class... Is>Menu(K&& key, V&& value, Is&&... items)
:base(std::forward<K>(key), std::forward<V>(value)), items(std::forward<Is>(items)...){}
Menu(Menu&& menu)
:base(std::move(menu.key), std::move(menu.value)), items(std::move(menu.items)){}
bool operator()()override{
bool cont = true;
while(cont){
std::cout << "\n\nMenu: " << base::key << "\n";
MenuItemGet<sizeof...(Items), Key, Value, I, Items...>::show(std::cout, *this);
std::cout << "Zadejte volbu: ";
item_key_t in;
std::cin >> in;
if(auto* item = find(in)){
std::cout << "Nalezeno, spoustim\n";
cont = item->operator()();
std::cout << cont << '\n';
}
}
return true;
}
};
template <int N, class Key, class Value, class... Items>
struct MenuItemGet{
static void reg(Menu<Key, Value, Items...>& menu){
menu.order[N] = &std::get<N>(menu.items);
MenuItemGet<N-1, Key, Value, Items...>::reg(menu);
}
template<class Ostream>
static void show(Ostream& out, Menu<Key, Value, Items...>& menu){
out << std::get<sizeof...(Items) - N - 1>(menu.items);
MenuItemGet<N-1, Key, Value, Items...>::show(out, menu);
}
};
template <class Key, class Value, class... Items>
struct MenuItemGet<-1, Key, Value, Items...>{
static void reg(Menu<Key, Value, Items...>& menu){}
template<class Ostream>
static void show(Ostream& out, Menu<Key, Value, Items...>& menu){}
};
template <class Key, class Value, class... Items>
auto make_menu(Key&& key, Value&& value, Items&&... items)->Menu<Key, Value, Items...>{
return {std::forward<Key>(key), std::forward<Value>(value), std::forward<Items>(items)...};
}
template <class Key, class Value, class Action>
auto make_item(Key&& key, Value&& value, Action action)->MenuItem<Key, Value, Action>{
return {std::forward<Key>(key), std::forward<Value>(value), action};
}
template <int m, int n, bool opakovat>
bool akce(){
std::cout << "provadim akci "<< m << "/" << n << "\n";
return opakovat;
}
int main(){
auto menu = make_menu("-", "Hlavni menu",
make_item(1, "Akce 1", akce<0,1,true>),
make_item(2, "Akce 2", akce<0,2,true>),
make_item(3, "Akce 3", akce<0,3,true>),
make_menu(4, "Submenu 1",
make_item<long>(1, "Podakce 1", akce<1,1,true>),
make_item<long>(2, "Podakce 2", akce<1,2,true>),
make_item<long>(3, "Podakce 3", akce<1,3,false>) // podakce 3 a navrat do predchoziho menu
),
make_item(5, "Konec", akce<0,5,false>)
);
menu();
return EXIT_SUCCESS;
}
Takto sa strasia zaciatocnici :
#include <iostream>
#include <functional>
#include <string>
#include <map>
#include <memory>
#include <tuple>
template <class Key, class Value>
struct MenuItemBase{
const Key key;
Value value;
template <class Ostream>
friend Ostream& operator<<(Ostream& out, const MenuItemBase& x){
return out << x.key << ") " << x.value << std::endl;
}
virtual bool operator()()=0;
template <class K, class V>MenuItemBase(K&& key, V&& value)
:key(std::forward<K>(key)), value(std::forward<K>(value)){}
};
template <class Key, class Value, class Action>
struct MenuItem final : MenuItemBase<Key, Value> {
private:
using base = MenuItemBase<Key, Value>;
Action action;
public:
template <class K, class V>MenuItem(K&& key, V&& value, Action action = Action())
:base(std::forward<K>(key), std::forward<K>(value)), action(action){}
bool operator()()override{return action();};
};
template <int N, class Key, class Value, class... Items>
struct MenuItemGet;
template <class Key, class Value, class... Items>
struct Menu final : MenuItemBase<Key, Value>{
template <int N, class K, class V, class... Is>
friend class MenuItemGet;
protected:
using base = MenuItemBase<Key, Value>;
std::tuple<Items...> items;
std::map<Key, base*> map;
void reg_items(){MenuItemGet<static_cast<int>(sizeof...(Items))-1, Key, Value, Items...>::reg(*this);}
public:
template <class K, class V, class... Is>Menu(K&& key, V&& value, Is&&... items)
:base(std::forward<K>(key), std::forward<V>(value)), items(std::forward<Is>(items)...){}
Menu(Menu&& menu)
:base(std::move(menu.key), std::move(menu.value)), items(std::move(menu.items)){}
bool operator()()override{
bool cont = true;
while (cont) {
std::cout << "\n\nMenu: " << base::key << "\n";
MenuItemGet<static_cast<int>(sizeof...(Items))-1, Key, Value, Items...>::show(std::cout, *this);
std::cout << "Zadejte volbu: ";
Key in;
std::cin >> in;
if(map.size() != sizeof...(Items))reg_items();
auto item = map.find(in);
if (item != map.end()) {
std::cout << "Nalezeno, spoustim\n";
cont = item->second->operator()();
}
}
return true;
}
};
template <int N, class Key, class Value, class... Items>
struct MenuItemGet{
static void reg(Menu<Key, Value, Items...>& menu){
menu.map[std::get<N>(menu.items).key] = &std::get<N>(menu.items); //menu.reg_item<N>();
MenuItemGet<N-1, Key, Value, Items...>::reg(menu);
}
static void reg(MenuItemBase<Key, Value>& item){}
template<class Ostream>
static void show(Ostream& out, Menu<Key, Value, Items...>& menu){
out << std::get<sizeof...(Items) - N - 1>(menu.items);
MenuItemGet<N-1, Key, Value, Items...>::show(out, menu);
}
};
template <class Key, class Value, class... Items>
struct MenuItemGet<-1, Key, Value, Items...>{
static void reg(Menu<Key, Value, Items...>& menu){}
static void reg(MenuItemBase<Key, Value>& item){}
template<class Ostream>
static void show(Ostream& out, Menu<Key, Value, Items...>& menu){}
};
template <class Key, class Value, class... Items>
decltype(auto) make_menu(Key&& key, Value&& value, Items&&... items){
return Menu<Key, Value, Items...>{std::forward<Key>(key), std::forward<Value>(value), std::forward<Items>(items)...};
}
template <class Key, class Value, class Action>
decltype(auto) make_item(Key&& key, Value&& value, Action action){
return MenuItem<Key, Value, Action>{std::forward<Key>(key), std::forward<Value>(value), action};
}
bool akce(int m, int n, bool opakovat) {
std::cout << "provadim akci "<< m << "/" << n << "\n";
return opakovat;
}
int main(){
using std::bind;
using std::string;
auto menu = make_menu<string, string>("Hlavni menu", "-",
make_item<string, string>("1", "Akce 1", bind(akce,0,0,true)),
make_item<string, string>("2", "Akce 2", bind(akce,0,1,true)),
make_item<string, string>("3", "Akce 3", bind(akce,0,2,true)),
make_menu<string, string>("4", "Submenu 1",
make_item<string, string>("1", "Podakce 1", bind(akce,1,0,true)),
make_item<string, string>("2", "Podakce 2", bind(akce,1,1,true)),
make_item<string, string>("3", "Podakce 3", bind(akce,1,2,false)) // podakce 3 a navrat do predchoziho menu
),
make_item<string, string>("5", "Konec", bind(akce,0,5,false))
);
menu();
return 0;
}
#62 Martin
struktura a trieda je to iste, jediny rozdiel je v tom ze prvky v triede su defaultne privatne a v strukture su defaultne verejne, v klude mozes mat strukturu ktora dedi triedu a opacne triedu co dedi strukturu...
&& je rvalue referencia, ak si zaciatocnik tak sa tymto druhom referencii zatial nezaoberaj.
#include <iostream>
struct Test{
Test(){
//tento constructor sa spusti pri vytvarani triedy, napr:
// Test test;
// Test test{};
// Test test = Test();
// (Test());
//...
//pomocny vypis ktory vypise adresu vytvaranej premennej:
std::cout << "construct " << this << '\n';
}
Test(const Test& x){
//kopirovaci konstruktor, spusta sa pri kopirovani objektu:
// Test a;
// Test b = a; //ako keby si zavolal b.Test(a);
//
//pomocny vypis ktory vypise adresu parametra x a adresu this
std::cout << "prekopiruje " << &x << " do premennej " << this << '\n';
}
~Test(){
//destructor, spusta sa pri zaniku objektu:
// {
// Test a;
//
// //...
// } //na konci bloku sa avola destructor a.~Test();
//
// {
// (Test()); //Destructor pre docasnu premennu Test() sa vola hned za vyrazom
//
// }
//
//
//
//pomocny vypis ktory vypise adresu this
std::cout << "destroy " << this << '\n';
}
void do_something()const{
//tato funkcia len vypise adresu this, ak sa zavola destructor pre premenu this skor ako sa zavola do_something tak je v programe chyba lebo objekt uz neexistuje
std::cout << "do something " << this << '\n';
}
};
const Test& fnc(const Test& test){
return test;
}
int fnc(const int& i){return i;}
int main(){
{
std::cout << "\n\n1. test:\n";
const Test& test = Test();
test.do_something();
}
{
std::cout << "\n\n2. test:\n";
const Test& test = fnc(Test());
test.do_something();
}
{
std::cout << "\n\n3. test:\n";
Test test = fnc(Test());
test.do_something();
}
std::cin.get();
return 0;
}
Program vypise nieco taketo, ty tam budes mat ine adresy objektov:
1. test:
construct 0025F895 //vytvori sa objekt
do something 0025F895 //zavola sa do_something()
destroy 0025F895 //znici sa objekt
2. test:
construct 0025F895 //vytvori sa objekt
destroy 0025F895 //znici sa objekt
do something 0025F895 //CHYBA zavola sa do_something() pre objekt ktory uz neexistuje, cize bug
3. test:
construct 0025F896 //vytvori sa objekt A (0025F896)
prekopiruje 0025F896 do premennej 0025F897 //vytvori sa kopia objektu A, nazvyme ju B (0025F897)
destroy 0025F896 //zmaze sa objekt A
do something 0025F897 //spusti sa do_something() pre objekt B //objekt B je stale funkcny
destroy 0025F897 //znici sa objekt B
#57 mitti
bod 1: vytvori Docasnu premennu (rvalue) Test() a priradiu ju do premennej test ktora ma typ const Test&. Kedze je to referencia tak kompilator rozsiri platnost docasnej premennej na cely scope, take sa nezavola destructor hned po ukonceni vyrazu ale az na konci scopu (blocku)
bod 2: Toto je ukazka blbeho fungovania, najprv sa vytvori docasna premenna Test() ktora je rvalue, ale pretypuje sa na const&. Nasledne sa zavola funkcia fnc ktora nevie ze parameter je docasna premenna a vrati ju. Nasledne vo funkcii main je vratena referencia priradena do premennej test, main ale nevie co vrati funkcia fnc, takze nerzsiri platnost docasnej premennej na cely scope a destructor docasnej premennej sa zavola hned po skonceni vyrau.
bod3: Toto sa podoba bodu 2, len s tym rozdielom ze premenna test nie je referencia, cize sa vola copy constructor a az potom sa vola destructor docasnej premennej Test(), lokalna premenna test sa rusi az na konci scopu, cie vsetko funguje ako ma
struct Test{
Test(const Test& x){std::cout << this << "->Test(const Test& == " << &x << ");\n";} //copy constructor
Test(Test&& x){std::cout << this << "->Test(Test&& == " << &x << ");\n";} //move constructor c++11, c++14
Test(){std::cout << this << "->Test();\n";} //obycajny constructor
~Test(){std::cout << this << "->~Test();\n";} //destructor
};
struct S{
//...
};
//je to iste ako:
class S{
public:
//...
};
Rvalue premenne su implicitne konvertovatelne na const&.
Funkcia ktora ma ako parameter premennu typu const& nevie ci ten parameter je lvalue alebo rvalue, takze kompilator ti nemoze povedat ze je tam problem a umozni ti vratit tuto referenciu.
Takto vratena referencia uz nie je brana ako rvalue, takze kompilator nerosiri jej platnost na cely scope, ale zavola destructor po ukonceni vyrazu.
V c++ je ovela viac svinstiev ako toto, casom si zvyknes :)
#52 mitti
Skus sa pozret ako sa volaju destructory:
#include <iostream>
struct Test{
Test(const Test& x){std::cout << this << "->Test(const Test& == " << &x << ");\n";}
Test(Test&& x){std::cout << this << "->Test(Test&& == " << &x << ");\n";}
Test(){std::cout << this << "->Test();\n";}
~Test(){std::cout << this << "->~Test();\n";}
};
const Test& fnc(const Test& test){
return test;
}
int main(){
std::cout << "\n1.\n";
{
std::cout << "begin\n";
const Test& test = Test();
std::cout << "do...\n";
}
//--------------------------------------
std::cout << "\n2.\n";
{
std::cout << "begin\n";
const Test& test = fnc(Test());
std::cout << "do...\n";
}
//--------------------------------------
std::cout << "\n3.\n";
{
std::cout << "begin\n";
Test test = fnc(Test());
std::cout << "do...\n";
}
std::cin.get();
return 0;
}
Edit:
Tvoja trieda obsahuje az 2 premenne typu int, AZ 2!!! Kludne mozes vracat priamo objekt a nie referenciu :)
Ked skoncis s tymi knihamy tak budes mat lepsiu predstavu kam ist dalej, napr skus stranku www.opengl.org :)
Obe su pisane pre OpenGL 4.3. Vyber je na tebe, pripadne si ich mozes stiahnut z TPB a pozret si ktora ti viac vyhovuje a tu si kupit :)
To niesu diely ale edicie, OpenGL sa vyvija, takze aj knihy je potrebne prepisovat pre nove OpenGL. To je aj dovod preco sa taketo knihy neoplati kupovat v cestine/slovencine. Kym ich dakto prelozi tak su uz zastarale...
Ked uz OpenGL tak verziu 3.1+, NEHE tutorial je extremne zastarali.
Skus:
http://www.amazon.com/OpenGL-SuperBible-Comprehensive-Tutorial-Reference-ebook/dp/B00E1GL1SO/ref=zg_bs_3935_4
http://www.amazon.com/OpenGL-Programming-Guide-Official-Learning/dp/0321773039/ref=zg_bs_3935_6
#57 Kit
Niesom moderator.
Kam vlastne smeruje tato diskusia? Vadi ti ze jazyk s manualnou spravou pamete ti automaticky nespravuje pamet, alebo sa snazis niekoho presvedcit ze automaticka sprava pamete je lepsia ako manualna, pripadne len porovnavas gc s manualno spravou pamete alebo nieco ine?
class Oject{};
void fnc(){
Object* o = nullptr;
if(true){
o = new Oject();
}
delete o; //objekt musis zmazat rucne
}
//alebo pusiz std::unique_ptr
Nechci zbytecne zabirat pamet objektem pokud bych ho potom nepouzil
Kolko zabera ten objekt a pouizvas rekurziu? Mal si problemy s malym zasobnikom? Ak nie tak riesis neexistujuci problem.
#1 Jan Růžička
Riadkom double(mesic); sa snazis deklarovat premennu mesic ale premenna s tymto menom uz bola deklarovana.
Riesenie je nasledovne:
//pouzi ten isty vyraz ako expression a nie ako statement:
double d = double(mesic);
//pouzi inicializaciu z c++11:
double{mesic};
edit: alebo pouzit pretypovanie ktore sem dal KIIV, pripadne static_cast.
moes skusit nieco taketo:
struct Trieda : Render{
void render()override{assert(0);}
void render(int x, int y)override{/*...*/}
};
alebo upravit hiearchiu tried:
struct RenderXY{
virtual void render(int x, int y)=0;
};
struct Render : public RenderXY{
virtual void render()=0;
};
#3 Remder
Moze to nastat napr vtedy ked samotna trieda Foo bude vo vectore : std::vector<Foo> v;
S vectorom si treba davat velky pozor. Moze sposobyt chby ktore sa strasne zle hladaju (prejavia sa oneskorene a len niekedy).
Raz sa my to stalo v jednom programe kde som mal obrovsky strom polymorfickych prvkoch kde niektore prvky mali vetvy ulozene vo vectore. V strome sa volali virtualne funkcie( aj s nepriamou recursiou) ktore niekedy vytvarali dalsie prvky a vkladli ich do vectorov. Pri urcitych kombinaciach prvkov a urictom poradi zavolania funkcii to hadzalo segfaulty. Ale aspon som sa naucil pouzivat valgrind :)
#1 Remder
Problem moze nastat ak bude objekt triedy Foo zniceny ale ukazatel ti ostane funkcny:
int main(){
std::vector<int>* ptr = nullptr;
{
Foo foo{};
ptr = foo.getIntVect();
//foo.~Foo();
}
///objekt foo uz neexistuje
ptr->front() = 7;
}
Pouzi radsej referenciu:
std::vector<int>& Foo::getIntVect() {
return intVect;
}
//alebo rovno const referenciu:
const std::vector<int>& Foo::getIntVect()const{
return intVect;
}
Samozrejme aj z referenciu sa da vytvorit dangling "pointer", ale je to trochu pracnejsie :)
Tak pametaj si spodnu a hornu hranicu, napr:
min = 0; max = 99; //1.
min = 50; max = 99; //2.
min = 50; max = 72; //3.
...
Takto postupujes az dokym neuhadnes cislo. Akonahle sa min == max a nie je to hladane cisla tak to znamena ze uzivatel klamal :)
edit: opravena verzia:
#1 DMS
Mozes skusit takyto parser:
#include <vector>
#include <iostream>
#include <stdexcept>
#include <cassert>
enum class Key{
Number,
OpAdd,
OpSub,
OpMul,
OpDiv,
OpBracketL,
OpBracketR,
Eof
};
struct Token{
Key key;
std::string val;
Token(Key key):key(key){}
Token(Key key, const std::string& val):key(key), val(val){}
Token(Key key, std::string&& val):key(key), val(std::move(val)){}
};
std::vector<Token> scan(std::istream& in){
std::vector<Token> tokens;
while(1){
int i = in.get();
DENGO:
switch(i){
case ' ':
case '\t':
continue;
case '\n':
tokens.emplace_back(Key::Eof);
return tokens;
case '+':
tokens.emplace_back(Key::OpAdd);
continue;
case '-':
tokens.emplace_back(Key::OpSub);
continue;
case '*':
tokens.emplace_back(Key::OpMul);
continue;
case '/':
tokens.emplace_back(Key::OpDiv);
continue;
case '(':
tokens.emplace_back(Key::OpBracketL);
continue;
case ')':
tokens.emplace_back(Key::OpBracketR);
continue;
case '0':case '1':case '2':case '3':case '4':
case '5':case '6':case '7':case '8':case '9': {
std::string str;
str += (char)i;
while(1) switch((i = in.get())){
case '0':case '1':case '2':case '3':case '4':
case '5':case '6':case '7':case '8':case '9':
str += (char)i;
continue;
case '\n':
tokens.emplace_back(Key::Number, str);
tokens.emplace_back(Key::Eof);
return tokens;
default:
tokens.emplace_back(Key::Number, str);
goto DENGO;
break;
};
continue;
}
}
throw std::logic_error("Neznamy symbol");
}
assert(0);
}
double parseValue(std::vector<Token>::const_iterator& tok);
double parseAdd(std::vector<Token>::const_iterator& tok);
double parseMul(std::vector<Token>::const_iterator& tok);
double parseValue(std::vector<Token>::const_iterator& tok){
switch(tok->key){
case Key::Number:{
double d = std::stod(tok->val);
++tok;
return d;
}
case Key::OpBracketL:{
double d = parseAdd(++tok);
if(tok->key != Key::OpBracketR)throw std::logic_error("chyba znak ')'");
return d;
}
default:
throw std::logic_error("Neznama hodnota");
}
assert(0);
}
double parseMul(std::vector<Token>::const_iterator& tok){
double left = parseValue(tok);
while(1) switch(tok->key){
case Key::OpMul:
left *= parseValue(++tok);
break;
case Key::OpDiv:
left /= parseValue(++tok);
break;
default:
return left;
}
assert(0);
}
double parseAdd(std::vector<Token>::const_iterator& tok){
double left = parseValue(tok);
while(1) switch(tok->key){
case Key::OpAdd:
left += parseMul(++tok);
break;
case Key::OpSub:
left -= parseMul(++tok);
break;
default:
return left;
}
assert(0);
}
double parse(const std::vector<Token>& tokens){
//for(auto& tok : tokens)std::cout << "(" << tok.key << "\t:\t" << tok.val << ")\n";
auto tok = tokens.begin();
double d = parseAdd(tok);
if(tok->key == Key::Eof)return d;
throw std::logic_error("PARSE ERROR");
}
int main(){
using namespace std;
while(1){
std::cout << "= " << parse(scan(std::cin)) << ";\n\n";
}
return 0;
}
Tento konkretny parser vie spracovat matematicky vyraz obsahujuci operatory + - * / a zatvorky () .
Vyraz musy byt ukonceny znakom '\n'.
Operatory * a / maju vecsiu prioritu ako + a -.
Po urcitych upravach by sa tento parser dal pouzit aj pre tvoj pripad.
#1 Metodej
int cislo;
string str;
while(1){
cin >> cislo; ////pokusi sa nacitat cislo
if(cin.good())break; //cislo sa podarilo nacitat, cyklus sa ukonci.
cin.clear(); //vynuluje chbove stavy
cin >> str; //odfiltruje jedno slovo, ak chces odignorovat cely vstup tak pouzi metodu cin.ignore(...);
}
//prevod...
Co sa tyka samotneh prevodu, tak da sa to viacerimi sposobmi, viacej rieseni najdes aj na tomto fore.
#1 Kenvelo
skus nieco taketo:
std::vector<std::pair<float, float>> points;
points.emplace_back(Event.mouseButton.x, Event.mouseButton.y);
std::ofstream map("Map.txt", ios::ate | ios::out | ios::app);
for(auto& i : points){
map << i.first << ' ' << i.second << endl;
}
#5 Seph
Mne to funguje:
#include <vector>
#include <iostream>
using namespace std;
template <typename T>
class debugAllocator: public std::allocator<T>
{
public:
typedef size_t size_type;
typedef T* pointer;
typedef const T* const_pointer;
template<typename _Tp1>
struct rebind
{
typedef debugAllocator<_Tp1> other;
};
pointer allocate(size_type n, const void *hint=0)
{
cout << "Alokuji \t" << sizeof(n) * n << " bajtu na adrese ";
auto temp = std::allocator<T>::allocate(n, hint);
cout << hex << long(temp) << dec << "[" << long(temp) << "]" << endl;
return temp;
}
void deallocate(pointer p, size_type n)
{
cout << "Uvolnuji \t" << sizeof(n)*n << " bajtu na adrese " << hex << long(p) << dec << "[" << long(p) << "]" << endl;
return std::allocator<T>::deallocate(p, n);
}
debugAllocator() throw(): std::allocator<T>()
{}
debugAllocator(const debugAllocator &a) throw(): std::allocator<T>(a) { }
~debugAllocator() throw() { }
};
int main()
{
vector<vector<int,debugAllocator<int>>,debugAllocator<vector<int,debugAllocator<int>>>> vect(
0,
vector<int,debugAllocator<int>>(),
debugAllocator<vector<int,debugAllocator<int>>>()
);
vect.push_back({});
for(int i = 0; i < 10; ++i)vect.back().push_back(i);
return 0;
}
vystup mam takyto:
Alokuji 8 bajtu na adrese 1cca010[30187536]
Alokuji 8 bajtu na adrese 1cca030[30187568]
Alokuji 16 bajtu na adrese 1cca050[30187600]
Uvolnuji 8 bajtu na adrese 1cca030[30187568]
Alokuji 32 bajtu na adrese 1cca030[30187568]
Uvolnuji 16 bajtu na adrese 1cca050[30187600]
Alokuji 64 bajtu na adrese 1cca070[30187632]
Uvolnuji 32 bajtu na adrese 1cca030[30187568]
Alokuji 128 bajtu na adrese 1cca0a0[30187680]
Uvolnuji 64 bajtu na adrese 1cca070[30187632]
Uvolnuji 128 bajtu na adrese 1cca0a0[30187680]
Uvolnuji 8 bajtu na adrese 1cca010[30187536]
edit:
throw-list je v C++11 deprecated, miesto throw() sa pouziva noexcept.
#11 hlucheucho
erase() vracia prvok ktory nasleduje po prave mazanom prvku. Ak budes mazat posledny prvok vo vectore, tak ti vrati end() iterator a for cyklus ti ho na konci inkrementuje, cize bude ukazovat do niecoho co nasleduje za iteratorom end() a pri dereferencovani ti to zrejme spadne alebo vrati blbost. Inak v c++14 sa lambda da zapisat takto: [](auto& x){/*...*/}
#2 sleepy
Bohuzial nie, kompilator by to ani neprelozil. Urcite by to ani nefungovalo tak ako si myslis.
#1 flack
Skus nieco taketo:
void generujMaticuNahodne(int (&matica)[9][4]); //referencia na pole
//alebo trochu vseobecnejsie:
template <size_t N, size_t M>
void generujMaticuNahodne(int (&matica)[N][M]);
#1 kaja
Ked vkladas do vectoru prvky a vector nema alokovany dostatok miesta, tak moze alokovat nove pole do ktoreho presunie povodne prvky (nevolaju sa ziadne copy constructory a ani destructory). Vysledokom je ze ak si mal pointre alebo iteratory na prvky vectora, tak budu vsetky tieto pointre ukazovat do neplatneho miesta.
Bolo by ale lepsie ak sem das ukazku tvojho kodu (orezanu o nepotrebne casti).
#5 Tango
Ak mas spojenu deklaraciu funkcie s definiciou tak zrejme moze byt parameter formalny aj skutocny zaroven, zalezi ako sa nanho pozeras :) Radsej si ale pockaj na komentar niekoho kto to ovlada lepsie .
Asi to bude toto:
void f(int i){} //'i' je formalny parameter funkcie 'f'
void g(int x); //'x' je formalny parameter funkcie 'g'
int main(){
f(1); // cislo 1 je skutocny parameter (argument) funkcie 'f';
g(2); // cislo 2 je skutocny parameter (argument) funkcie 'g';
}
void g(int x){ //'x' je formalny parameter funkcie 'g'
f(x); //hodnota premennej 'x' je skutocny parameter funkcie 'f' a zaroven 'x' je formalny parameter funkcie 'g'
}
#3 Tango
Ja som sa zatial nestretol s takym delenim parametrov, ale ak to spravne chapem tak formalny parameter funkcie je parameter pri deklaracii:
void fnc(int a, long b, double d); //formalne parametre funkcie
A skutocne su tie s s ktorymi je funkcia volana:
fnc(1, 2, 3.14); //skutocne parametre funkcie
#4 Kowalsky95
DirectX funguje len na platformach od MS, ak chces vytvarat aplikacie ktore budu fungovat len na winoch a xboxoch tak sa ho nauc. Ak chces spustat aplikacie aj na mobilnych platformach, macoch, pripadne aj na linuxoch tak sa viac sustred na Open(GL, AL, CL, ...).
#1 lukas.balaz
Pouzi .find :
#include <iostream>
#include <string>
#include <unordered_set>
int main(){
std::unordered_set<std::string> set{
"ab",
"cd",
"e",
"fg",
"h"
};
std::string s{"abcdefghij"};
for(auto i = s.begin(); i != s.end(); ++i){
if(set.find({*i}) != set.end())std::cout << "v 'set' sa nachadza znak " << *i << '\n';
else std::cout << "v 'set' sa NEnachadza znak " << *i << '\n';
auto j = i+1;
if(j != s.end()){
if(set.find({*i, *j}) != set.end())std::cout << "v 'set' sa nachadza dvojznak " << *i << *j << '\n';
else std::cout << "v 'set' sa NEnachadza dvojznak " << *i << *j << '\n';
}
}
return 0;
}
#7 Cruppy
Mozes sa inspirovat tuto:
#5 Lorin
Metoda moze byt pretazene na zaklade const:
#include <iostream>
#include <vector>
struct C{
void fnc(){std::cout << "mutable\n";}
void fnc()const{std::cout << "const\n";}
};
int main(){
C c;
c.fnc();
reinterpret_cast<const C&>(c).fnc();
return 0;
}
//vystup je:
mutable
const
Malo by stacit nieco taketo:
class SocketPermit
{
char* ip;
public:
SocketPermit (SocketConnection *SocketConnectionThread);
};
class SocketConnection
{
//...
};
SocketPermit::SocketPermit(SocketConnection *SocketConnectionThread){
ip = SocketConnectionThread->IP; // Zkopíruj IP adresu z třídy SocketConnection do třídy SocketPermit
SocketConnectionThread->CloseConnection(); //Ukonči spojejí Soketu z třídy SocketConnection
}
#1 Kowalsky95
goto sa stale pouziva a pouzivat sa bude aj v buducnu. Sprava pameti funguje normalne, ak vyskocis zo scopu tak sa zavolaju destructory. Ak s goto preskocis deklaraciu premennej tak mozu nastat 2 situacie:
1. Ak ma premenna trivialny typ(nema konstruktor/destructor, virtualne metody, a plati to aj pre vsetky atributy a bazove triedy) tak bude premenna neinicializovana,
2. Ak nema trivialny typ tak ti prekladac zahlasi chybu.
V pripade vynimiek je to zlozitejsie. Je viacej druhov, sjlj vynimky, SEH (M$), DWARF a urcite aj rozne ine. Vecsinou sa tam vytvaraju exception framy ktore su zlinkovane a pomocou nich sa odvyja zasobnik a volaju sa case-y.(podrobnosti som si zatial nestudoval)
#1 mat007
sprav si testovaciu funkciu:
int test(Bitmap *matice, size_t index){
if(index < ((matice->rows*matice->cols*sizeof(char))+1))
return 1; //vsetko ok
return 0; //chyba
}
//.....
assert(test(matice, AktualniCisloVMatici));
matice->cells[AktualniCisloVMatici] = '0';
#4 Martin Kozibrátka
To moze rovno spravyt nieco taketo:
template<class Fnc>
void Mix_HookMusicFinished(Fnc fnc)
{
fnc();
}
///alebo bez templatov
void Mix_HookMusicFinished(std::function<void(void)> fnc)
{
fnc();
}
//...
Mix_HookMusicFinished([&](){this->f();});
#5 lukas.balaz
pomozem ti z hladanim: manipulators.
#2 Kowalsky95
S GC je to zlozitejsie ako sa moze na prvy pohlad zdat. Ak ma program nadbytok pamete, tak sa GC nemus casto spustat (pri malych alebo kratko beziacich programoch sa nemusi spustit vobec) a alokacia pamete moze byt rychlejsia ako manualna (napr ako v C/C++). GC vecsinou alokuje pamet sekvencne a nemusi riesit fragmentaciu pamete, dokonca GC moze presuvat objekty v pameti tak aby boly zasebou. Oproti tomu musi C/C++ (pripadne iny jazyk bez GC) alokator riesit fragmentaciu a tym padom je pomalsi(hlavne pri alokacii velkeho mnozstva malych objektov). Cim menej ma GC volnej pamete, tym castejsie sa musi spustat a tym je program pomalsi.
Akonahle ale potrebujes vysoku rychlost programu, nizke latencie a alokujes vela prvkov tak aj tak skoncis pri vytvarani memory/object poolov a rucnom recyklovani pamete, je jedno ci mas GC alebo nie.
Co sa tyka prekladu. Java moze byt prekladana priamo do strojoveho kod, moze byt prekladana do bytekodu ktory moze byt byt interpretovany, pripadne prekladany do natyvneho kodu (JIT kompilatorom) alebo kombinovanie interpretera a JIT compilera...
Tymto chcem povedat ze sa jasne neda povedat ze Java je pomala bez toho aby si vedel aky program spustas, ako je skompilovany, parametre stroja kde ho spustas, ake su vlastnost VM a jeho GC...
#1 Doomista
Vector 'bitmap' obsahuje len pointre na SDL_Surface. To ci tie pointre ukazuju na niake zmysluplne data ho vobec nezaujima, kludne si ho mozes predstavyt ako std::vector<void*> . Ciel pointrov vo vectore mozes uvolnit pomocou SDL_FreeSurface a vo vectore 'bitmap' ti ostanu takzvane dangling pointre.
std::vector je vecsinou implementovany tak ze obsahuje pointer na dynamicky alokovany pole dat, ich kapacitu a aktualny pocet prvkov. Aj ked je bitmap vector lokalna premenna alokovana na stacku, tak samotne pole prvkov je na heape, teda ho mozes zmazat. Vo vectore ho maze destructor.
Velkost pointra je vecsinou 32-64b, takze ak tam nemas velmi vela prvkov tak to skoro nic nezabera.
#1 Lukas
Mohlo by to vyzerat takto:
struct Ucet{
//prvky uctu
};
class Zakaznik{
///pole/vector/list/... uctov
Ucet& pridajUcet(){/*implementuj si metodu ktora prida ucet do pola/vektora alebo ineho konaineru podla tvojho vyberu*/}
};
int main(){
Zakaznik[10] zakaznici; //alebo std::vector<Zakaznik>, ak budes vytvarat pointre na zakaznikov tak radsej std::list<Zakaznik>
size_t i = 7;
zakaznici[i].pridajUcet();
}
#3 Maty
Alokacia vyzera ok.
Ak bude mat vnutorne pole vzdy rovnaku velkost tak mozes spravyt nieco taketo:
struct S{
double d[2];
};
//...
int alokace=2;
S *pole = (S*)malloc(alokace*sizeof(S));
while(!feof(stdin))
{
if(alokace<i)
{
alokace*=2;
pole = realloc (pole, alokace*sizeof(S));
}
i++;
}
#4 garamond
Toto ti mono pomoze:
#include <stdio.h>
int main(void){
char string[] = "1234578";
printf("\n&string: %p\
\n(&string+1): %p\
\nrozdiel %dB\
\nvelkost pola: %d",
&string,
&string+1,
(int)((char*)(&string+1) - (char*)&string),
(int)sizeof(string)
);
return 0;
}
#2 garamond
Nie, ty vlastne vytvoris adresu adresy (pointer na pointer):
char string[] = "text"; //pointer na prvy prvok pola (pointer bude zrejme constantny)
char *ptr = string; //pointer na prvy prvok pola
char **ptr2 = &string; //pointer na pointer(pole) ktory ukazuje na prvy prvok retazca (mozno my tam niekde chyba const)
char **ptr3 = &ptr; //pointer na iny pointer ktory tiez ukazuje na prvy prvok pola(tu my uz nechyba const :) )
#1 Gravatar
Referencia je v podstate ukazatel zo syntaktickou omackou a bez pointorvei aritmetiky. Referencie sa pridali do c++ hlavne kvoly overloadingu operatorov a copy constructorom.
Priklad:
void fnc(TvojaTrida x); //parameter x reprezenuje kopiu hodnoty ktorou si funkciu volal
void fnc(TvojaTrieda* x); //parameter reprezentuje adresu triedy, nevznika kopia
void fnc(TvojaTrieda& x); //parameter reprezentuje adresu triedy ako predchadzajuci priklad rozdiel je len v manipulaci s premennou x
//ako bonus tu mas 4 priklad:
void fnc(TvojaTrieda&& x); //rvalue referencia :)
// a.hpp
#ifndef A_HPP
#define A_HPP
class B;
//#include "b.hpp" //toto staci vlozit do A.cpp
class A
{
public:
A() {}
virtual ~A() {}
private:
A * p_a;
B * p_b;
};
# endif
// b.hpp
#ifndef B_HPP
#define B_HPP
class A;
//#include "a.hpp" //staci dat do B.cpp
class B
{
public:
B() {}
virtual ~B() {}
private:
B * p_b;
A * p_a;
};
# endif
#6 ingiraxo
Ak je return v bloku finally tak bud budes ignorovat return a budes pokracovat v spracovavani vynimky, alebo budes ignorovat vynimku a vratis sa z funkcie pomocou returnu. Tvorcovia javy si zvolily 2 sposob. V C#, D a urcite aj v inych jazykoch to spravyli lepsie a return vo finally sa vobec neprelozi. Niektore IDE vypisuju aj pri jave warningy
#7 Kent
int main(){
char** words;
const size_t POCET_SLOV = 314;
words = malloc(sizeof(char*)* POCET_SLOV);
char buff[200]; //pomocny buffer
size_t index = 0;
while(index < POCET_SLOV){
scanf("%s", buff);
words[index] = malloc(sizeof(char)*(strlen(buff)+1)); //alokujes miesto kam ulozis slovo
strcpy(words[index], buff); //prekopirujes obsah z pomocneho buffera do alokovaneho pola
}
for(size_t i = 0; i < index; ++i)
free(words[i]);
free(words);
}
#5 Kent
Nastuduj si dynamicku alokaciu pamete.
int main(){
char* str; //neinicializovany pointer
str = malloc(sizeof(char) * 20); //alokujes pole znakov s 20 prvkami
strcpy(str, "wtf omg lol"); //prekopirujes do pola string
//...
free(str); //uvolnis alokovane pole
}
#include <stdio.h>
#include <stdlib.h>
int main(){
int pocet = 11 ;
int i, j, k, l = 0;
if (pocet <= 11){
for (i = 1; i <= pocet; i++){
for (j = 0; j < i + 1; j++){
for (l = i+1; l > j; l--)
printf(" ");
//Tento cyklus treba upravyt:
//1 X pred cyklom, jedno za cyklom a vo vnutry miesto X vypises medzeru
//A este treba pridat podmienku na vykreslenie podstavy.
for (k = 0; k < 2*j+1; k++)
printf("x");
printf("\n");
}
}
}
else printf("Zadana hodnota je vetsi nez 11 !!");
return 0;
}
#1 Daniel
if (
!(i%j) //i%j vrati zvysok po celociselnom deleni, ak je cislo i delitelne s j tak vrati 0. Nulu nasledne znagujes a dostanes 1 == true
&& //logicky and, musi platit podmienka na lavej strane aj pravej (v tomto pripade hore aj dole :) )
(i!=j) //kazde prvocislo je delitelne same sebou bez zvysku, preto je tu aj tato podmienka
)break; //ukonci cyklus (len 1)