for (size_t i1 = 0; i1 < delka_pole_1; ++i1)
for (size_t i2 = 0; i2 < delka_pole_2; ++i2)
for (size_t i3 = 0; i3 < delka_pole3; ++i3)
std::cout << pole1[i1] << ", " << pole2[i2] << ", " << pole3[i3] << '\n';
Příspěvky odeslané z IP adresy 89.203.160.–
Jestli to padá v destruktoru, tak by to mohlo být tím, že se dělá delete na již uvolněnou instanci té třídy (nebo jejího potomka), ke které patří destruktor.
To _Radek_ : Ano, tak by to mělo fungovat.
To vdolek : Tak to asi bude zrovna slabé místo implementace STL od Microsoftu. Nechtělo se mi tomu věřit, tak jsem zkusil tento program:
#include <algorithm>
#include <cstdlib>
#include <vector>
template <typename T>
void straightSelectionSort2(const T& begin, const T& end)
{
if (begin == end)
return;
for (T i = begin; i != end - 1; ++i)
{
T min = i;
// je je ukazatel na položku, se kterou se porovnává
for (T j = i + 1; j != end; ++j)
if (*j < *min)
min = j;
if (*min != *i)
std::iter_swap(min, i);
}
}
template <typename T>
void straightSelectionSortIndex(T &container, int size)
{
for (int i = 0; i != size - 1; ++i)
{
int min = i;
for (int j = i + 1; j != size; ++j)
if (container[j] < container[min])
min = j;
if (container[min] != container[i])
std::swap(container[i], container[min]);
}
}
template <typename T>
void straightSelectionSort3(const T& begin, const T& end)
{
if (begin == end)
return;
// i je ukazatel na první položku nesetříděné části
for (T i = begin; i != end - 1; ++i)
{
std::iter_swap(i, std::min_element(i, end));
}
}
int main()
{
const size_t SIZE = 100000;
std::vector<int> v;
v.reserve(SIZE);
srand(1);
for (size_t i = 0; i < SIZE; ++i)
v.push_back(rand());
// straightSelectionSortIndex(v, v.size()); // varianta index
// straightSelectionSort2(v.begin(), v.end()); // varianta sort2
straightSelectionSort3(v.begin(), v.end()); // varianta sort3
}
Přeložil jsem to vždy jenom s jednou variantou řazení (jeden z poslednách tří řádků těla main). Výsledky gcc [g++.exe (TDM-2 mingw32) 4.4.1] (Přeloženo s -O3):
index .... cca 24s
straightSelectionSort2 ... cca 15.4s
straightSelectionSort3 ... cca 9.7s
Visual studio 2008 Express (přeloženo s /O2):
index ... cca 30s
straightSelectionSort2 ... cca 1m28s
straightSelectionSort3 ... cca 15.3s
Visual studio 2010 Express (přeloženo s/O2):
index ... cca 30s
straightSelectionSort2 ... cca 1m28s
straightSelectionSort3 ... cca 15.4s
Takže obě verze Visual Studia generují v tomto případě rovnocenný kód. Ovšem zdržení ve variantě straightSelectionSort2 je fascinující. Z tohoto jediného izolovaného příkladu nejde sice vyvodit závěr, že Visual Studio generuje horší kód, než gcc, ale je vidět, že s implementací STL Microsoft pořád bojuje. (Svědčí o tom i množství warningů, pokud použiju jakýkoliv header z STL - ty warningy jsou přímo na jejich kód.)
Takže na původní otázku, jestli iterátory jsou rychlejší než indexy lze asi dát jenom jednu odpověď: Jak kdy a jak ve kterém překladači.
To Petr : Ano, třeba tak.
Ale čtení ze std::cin dost často stačí.
To Bald3rr : Ano, jenom bych dodal, že je zbytečné to načítat po 1 znaku, funkcí fgets lze rovnou načíst více znaků.
Pokud se jednalo o programování v C++ s využitím standardní knihovny C++, tak se nemění nic.
Problém je obecně v případě, pokud je člověk zvyklý na používání nějakých platformově závislých knihoven. Buď musí najít nějakou multiplatformní náhradu nebo příslušnou část aplikace přepsat.
To všechno platí pro přechod z jakékoliv platformy na nějakou jinou.
Obecně lze doporučit používání knihoven, které jsou podporovány na různých platformách. Např. pro GUI to může být wxWidgets, Qt, fltk. Pro síťovou komunikaci libcurl, wxWidgets, Qt, boost::thread, pro práci se souborovým systémem boost::filesystem, wxWidgets, Qt. Určitě jich existuje mnohem více.
To Lordest : Ano.
To ondra.holub : Tak bohužel, horní indexy 1, 2, 3 a n se vložily jenom jako ⁿ¹²³.
To pidgin :
#include <iostream>
#include <locale>
#include <locale.h>
int main()
{
setlocale(LC_ALL, "");
std::wcout.imbue(std::locale(""));
std::wcout << L"aⁿ¹²³\n";
}
Zkoušel jsem na Linuxu v gcc.
Bohužel jiný index než zmíněné ⁿ¹²³ v unicode neznám. Pokud nemáte nějaký znak ve fontu, ve kterém tu konzolu zobrazujete, tak tam ten znak nejspíš nedostanete. Možná v nějakém specifickém terminálu.
No pokud to chce šéf, který si nedá říct, tak nezbývá než dělat i nesmysly (nebo změnit šéfa :-)).
No jestli je to pro Windows, tak to stačí otevřít v průzkumníku (explorer). Vykašlal bych se na vymýšlení nějakých specialit. Stažení prohlížečem je naprosto dostatečné. Funguje tak např. Chip-DVD. Pokud prohlížeč nenabízí variantu spuštění, lze to stáhnout do nějakého tempu a odtud bez problémů spustit. Pokud je někdo natolik BFU, že toto nedokáže, rozhodně bych ho nenechával instalovat programy jakkoliv zjednodušeným způsobem.
Znovu říkám, že si myslím, že to nestojí za tu práci. Jednalo by se vlastně o zjednodušený file manager a těch už existuje docela dost.
Trošku jsem to upravil, aby to vůbec šlo přeložit bez warningů. (Alespoň při použití gcc na Linuxu.)
Celý program by to chtělo trošku přepsat tak, aby se některé části dělaly v nějaké funkci. Jenom kvůli přehlednosti. Ostatní změny jsem okomentoval přímo ve zdrojáku.
// Vzhledem k tomu, ze main je deklarovano jako main()
// a ne main(void), jedna se o C++
#include <stdio.h> // V C++ lepe #include <cstdio>
// Nasledujici headery chybi
#include <cstring>
#include <cctype>
#include <cstdlib>
// Toto neni k nicemu potreba (a navic je to nestandardni)
//#include <conio.h>
// K cemu globalni promenne, kdyz je tam stejne jenom jedna funkce?
double Op[20]; /* zasobnik pre operandy */
int sp; /* pre zasobnik */
int main()
{
char riadok[100];
char s[10];
double Op1,Op2;
char c;
int i,j,k,Bodka;
sp = 0; /* inicializacia zasobnika */
for (i=1;i<100;i++)
riadok[i]=' ';
for (j=1;j<10;j++)
s[j]=0;
printf("Zadajte vyraz v postfixovej notacii:\n");
j=strlen(fgets(riadok, sizeof(riadok), stdin)); // fgets je bezpecnejsi
// j=strlen(gets(riadok));
riadok[j]='='; /* zarazka */
i=0;
zac: while(riadok[i]==' ')
i++;
c=riadok[i];
if(c!='.' && !isdigit(c))
{ /* operator */
if ((c!='=') && (sp<2))
{
printf("nespravny vyraz\n");
return 1; // Tady chybela navratova hodnota
}
if (c!='=')
{
Op2=Op[--sp]; Op1=Op[--sp];
}
switch (c)
{
case '+':
Op[sp++]=Op1+Op2;
break;
case'-':
Op[sp++]=Op1-Op2;
break;
case'/':
if (Op2!=0)
Op[sp++]=Op1/Op2;
else
{
printf("delenie nulou\n");
return 2; // Tady chybela navratova hodnota
}
break;
case'*':
Op[sp++]=Op1*Op2;
break;
case'=':
Op1=Op[--sp];
if (sp!=0) printf("Vyraz nebol spravny\n");
printf("Vysledok=%f \n",Op1);
getchar();
return 3; // Tady chybela navratova hodnota
default:
printf("Neznamy prikaz\n");
return 4; // Tady chybela navratova hodnota
}
}
else
{ /* operand */
k=0;Bodka=0;
while(riadok[i]==' ')
i++;
while((isdigit(riadok[i])) || (riadok[i]=='.'))
{
if (riadok[i]=='.')
{
if (Bodka==0)
{
Bodka=1;
}
else
{
printf("Dve des.bodky v jednom cisle\n");
return 5; // Tady chybela navratova hodnota
}
}
s[k]=riadok[i];
if (k < 9)
k++;
else
{
printf ("Dlhy operand!\n");
return 6; // Tady chybela navratova hodnota
}
i++;
}
if (sp < 19)
{
Op[sp++]=atof(s);
for (j=1;j<10;j++)
s[j]=0; Bodka=0;
goto zac;
}
else
{
printf("Plny zasobnik\n");
return 7; // Tady chybela navratova hodnota
}
}
i++;
goto zac; // To goto je zcela zbytecne, lze nahradit cyklem
return 0;
}
Pokud tomu zadám např.
2 3 + 4 * =
tak to správně vypíše 20.Je tam Makefile. Takže v příkazovém řádku jsem napsal make a přeložilo se to. V Linuxu.
Pokud to chceš zkoušet ve Windows, tak nejjednodušší to asi bude v cygwinu. Lze najít na http://www.cygwin.com
Zkus tam ještě přidat
#include <locale>
astd::cout.imbue(std::locale(""));
To bukaj_001 : enom pro zápis znamená mód w, nebo a. Jenže w všechno ze souboru vysype, takže i když budu mít již připravený druhý FILE otevřený pro čtení, nebude co číst. Při a se zase bude přidávat na konec souboru, takže budu nakonec číst data, která jsem právě zapsal, a pravděpodobně to skončí chybou. Nebo mi něco uniká?
Neuniká. Prostě je zbytečně neefektivní mít vstup i výstup ve stejném souboru. Nejlepší je mít vstup stdin a výstup stdout a uživatel si s tím už udělá co chce (přesměruje z/do jiného souboru, uloží na filesystém apod.). Pokud takto zkusím použít stejný soubor pro obojí, dojde k chybě. A o to jde - stejný soubor pro vstup i výstup je obvykle zbytečný. (Vždycky se dá vstup nebo výstup přejmenovat.)
Prostě bych vstup otevřel jenom pro čtení (i když třeba u programů pro windows to nebývá zvykem, ale je to opravdu naprosto normální věc) a výstup jenom pro zápis. Stačí ohandlovat chyby při otevírání. Není jedno, jestli se výstup nepodaří otevřít, protože je zároveň vstupem, nebo jenom proto, protože ho má zamčený zcela jiný program?
To Lordest : No, řekl bych, žes tam předtím měl if (int(cislo)). Ale to je celkem jedno. Zkus si, co znamená podmínka if (0). Nula je číslo, ale ta podmínka určitě neprojde, protože nula je automaticky převoditelná na false. To samé platí i pro 0.0 (tedy pro float).
To Lordest : Takto tedy ne. Copak nula není číslo?
Lepší je
if (std::cin.good())
{
// Je cislo
}
else
{
// neni cislo
std::cin.clear(); // vymazu chybovy priznak
}
Jenom je třeba počítat s tím, že číslo se načte i tehdy, když zadaný vstup začíná číslem, ale může být za ním i něco jiného. Např. 2322xyz projde.
[seznam]V menu File->New->Project
Vyber Console application
Klikni na Go
Vyber jazyk (C nebo C++)
Klikni na Next
Vyplň jméno projektu (project title), adresář, kde bude umístěn (Folder to create project in), jméno souboru s projektem (Project filename) a klikni na Next
Vyber překladač (pokud možno takový, který máš nainstalovaný).
Klikni na finish
Ve stromu (obvykle na levé straně okna) klikni pravým tlačítkem na ikonu projektu (je to hned pod workspace)
Klikni na add files
Vyber soubory, které chceš přidat
A je to. Projekt stačí teď přeložit: menu Build->Build
[/seznam]
Je potřeba ten program slinkovat bez jakýchkoliv knihoven (kromě nějakých vlastních). Tzn. i bez standardní knihovny C/C++. Nejspíš na to bude nějaký parametr překladače.
Tam, kde registry nejsou (konkrétně myslím POSIXové systémy) se dost často předpokládá, že je definována proměnná prostředí BROWSER, ve které je prohlížeč, jaký má uživatel nastaven. Pokud by tato proměnná nebyla k dispozici, zkusil bych to spouštět jako
/usr/bin/env firefox
Strčíš je do jednoho projektu. DevC neznám (používám Code::Blocks), takže podrobnosti ti neřeknu. Ale obecně: vytvoř projekt, přidej do něj soubory a přelož. Všechno to bude někde v menu.
To Petr S. : Můžeš si to zabalit do nějaké třídy, která si to přealokuje sama. Nebo použít něco, co už pro tento účel existuje - std::vector.
Místo dvourozměrného pole m x n si udělej jednorozměrné pole tak velké, aby se do něj vešlo m * n prvků. K jednotlivým prvkům pak můžeš přistupovat nějakou funkcí. Prostě místo na prvek [x][y] polezeš na prvek [x + m * n]. Jednorozměrné pole je pak snadné přealokovat. Navíc je to pak mnohem rychlejší než alokovat každý řádek zvlášť (stejně je tak vnitřně dělané každé dvou (nebo i více-) rozměrné pole v C/C++).
Ve visual studiu by mělo fungovat
#include <iostream>
#include <clocale>
#include <locale>
int main()
{
std::setlocale(LC_ALL, "");
std::wcout.imbue(std::locale(""));
std::wcout << L"ěščřžýáíé\n";
}
Učím se c++ a pokud tomu rozumím dobře, tak neočekávaná výjimka nastane pokud funkce vyvolá výjimku a přitom ji nemá ve své specifikaci.
Nevím, jak je na tom VS 2008, ale VS toto nepodporovalo. Tedy, té deklaraci rozumělo, ale přímo to vypisovalo warning, že tato specifikace není podporována a bere se to stejně, jako by tam žádná výjimka specifikovaná nebyla. Tedy jinými slovy: VS bere jenom funkci bez specifikace výjimky nebo s prázdným throw.
Já to píšu do souboru s příponou tpl (je to úplně jedno, jak se to jmenuje) a ten pak #includuju jenom tam, kde je potřeba. Obecně používám (samozřejmě ne vždycky) 4 typy souborů:
- header s forward deklaracemi
- header
- implementaci
- implementaci šablon
Řekl bych, že problém bude v tom, že se do dynamické knihovny přilinkovává libglfw, které ale není přeloženos -fPIC.
Asi bych to zkusil přeložit do assembleru a prostě se podíval, co z toho vylezlo.
Když už čtu řetězec, tak bych ho zkusil načítat do std::string. Pokud to chceš jenom dostat na stdout, tak to dělá to cout << ifs.rdbuf()
Tak jsem se teda obětoval, přebootoval jsem do Windows. ZKusil jsem program
#include <iostream>
#include <fstream>
#include <locale>
int main()
{
setlocale(LC_ALL, "");
std::ifstream in("šč", std::ios::in);
std::cout << in.rdbuf();
}
Zdroják mám uložen v UTF8. Funguje to s GCC 3.4.něco a s Visual studiem 2008. GCC nepotřebuje ani to setlocale.Asi na to budeš muset jít nějak přes win API.
Ale jak tu už psal KIIV, je nějaký důvod k tomu, aby v programu bylo natvrdo nějaké jméno souboru? Jedině u názvu nějakého konfiguračního souboru. A ten snad diakritiku nepotřebuje.
PS: K čemu je v tomto fóru dobré tlačítko "Náhled", když k tomu, co jsem napsal se už nedá vrátit? Nehledě na to, že to žádný náhled nezobrazí. Funguje to asi tak dobře, jako přihlášení. Chvilku jsem přihlášen, chvilku ne, pak musím při vkládání příspěvku zodpovědět ty otázky pro neregistrovaného uživatele a příspěvek je pak vložen pod mým jménem, nebo nemusím odpovídat na žádné otázky, ale příspěvek je vložen anonymě... Funguje to tu nějak divně.
To KIIV : Neexistuje.
Odpověď je jednoduchá, ale ne taková, co chceš slyšet: všechno to záleží na překladači a na jeho nastavení.
Tak sem napiš, jaký příkaz to při překladu píše.
Závislosti projektů lze nastavit v menu Project->Properties. Na záložce Project settings je dole tlačítko Project's dependencies. Je potřeba mít všechny ty projekty otevřené.
A máš to nastavené ve správném targetu? Mělo by stačit Menu->Project->Build options, nahoře vybrat překladač, vlevo target a pak na záložce Compiler Settings vybrat podzáložku Other options a připsat tam -fPIC
To Lordest : Code::Blocks je free, je ke stáhnutí na www.codeblocks.org Doporučuji nainstalovat tu verzi, která je ke stažení a pak to přeplácnou nightly buildem (dá se k němu dostat přes odkaz forums).
Výhoda codeblocks je i v tom, že podporuje více překladačů. Např. gcc, Visual C/C++, digital mars, ... Je to jednak užitečné při psaní kódu, který má být maximálně přenositelný, ale hodí se to např. i ve chvíli, kdy překladač vyhazuje nějakou záhadnou chybu a programátor nemůže zjistit, co se tomu překladači vlastně nelíbí. Tak to zkusím přeložit jiným překladačem, ten tu chybu formuluje jinak a je nějaká šance, že mně to dojde.
Další výhoda je, že codeblocks lze bez problémů provozovat i na Linuxu. Takže stejný projekt (pokud je multiplatformě napsaný) lze v klidu překládat i na více platformách.
To KIIV : Tak si to zkus přeložit. std::string má konstruktor s jedním parametrem typu const char*, takže se jedná o jednu implicitní konverzi a není důvod, proč by to nefungovalo.
#include <cstdio>
#include <dirent.h>
#include <vector>
#include <string>
// toto je tu na nic: #include <iostream>
typedef
std::vector<std::string> svec;
svec dir(const char *path)
{
DIR *dp;
svec res;
struct dirent *dirp;
dp = opendir(path);
while (dirp = readdir(dp))
res.push_back(dirp->d_name);
closedir(dp);
return res;
} //konec cteni adresare
int main() {
svec v = dir(".");
// A ted je to ve vektoru v
const svec::const_iterator end = v.end();
for (svec::const_iterator it = v.begin(); it != end; ++it)
printf("%s\n", it->c_str());
}
Pokud se to překládá jako C, tak je možné některé standardní headery vynechat (nemusí se includovat). Obvykle pak překladač vyhazuje warning, ale není to podmínka. Ovšem v C++ už toto možné není. Tam se ten header prostě includovat musí. To je možná ten rozdíl.
Funkce system je ve standardu, funguje samozřejmě i na Linuxu, Unixech apod. Akorát už není jisté, jestli tam bude existovat to, co je parametrem té funkce system.
Pokud je záměr, aby pole bylo v paměti bylo souvisle bez výplní, je potřeba udělat pole něčeho, co má velikost bajt, tedy např. uint8_t. Ale ke každému prvku se musí přistupovat přes ten union, čímž dostaneme zadarmo (udělá to překladač) postup, jak (např.) inkrementovat jenom část toho bajtu.
#include <stdio.h>
#include <stdint.h>
enum YesNo
{
NO = 0x0,
YES = 0xF
};
struct Xyz
{
unsigned data_:4;
unsigned yes_no_:4;
};
union Int4
{
struct Xyz xyz_;
uint8_t integer_;
};
#define Data(pole, index) ((union Int4*)(pole + index))->xyz_.data_
#define YesNo(pole, index) ((union Int4*)(pole + index))->xyz_.yes_no_
int main(void)
{
union Int4 i4a___[10]; // Toto je jenom pro ilustraci - budou tam vyplne
uint8_t i4a[10]; // Toto bude souvisle za sebou bajt po bajtu - to potrebujeme
printf("sizeof(i4a) = %d\n", sizeof(i4a___));
printf("sizeof(i4a) = %d\n", sizeof(i4a));
Data(i4a, 5) = 3;
YesNo(i4a, 5) = YES;
printf("5. prvek pole 0x%x\n\n", i4a[5]);
for (int i = 0; i < 20; ++i)
{
++Data(i4a, 5);
printf("5. prvek pole 0x%x\n", i4a[5]);
}
return 0;
}
To bukaj_001 : Použít bitové pole asi nebude to pravé ořechové, jelikož se jeho velikost, alespoň myslím, zaokrouhluje na počet bitů intu.
Pokud se bude jednat o proměnnou na zásobníku, tak je to jedno. To zaokrouhlení bude stejné. Buď to bude zarovnané na nějaké násobky 4 (nebo 8) bajtů nebo to bude zkomprimované, ale pomalejší. To zarovnání bude stejné jako zarovnání struktury nebo unionu.
Jediný rozdíl je v případě, že to chci mít uloženo v poli souvisle za sebou. Tady ale obvykle není problém mít ukazatel na konkrétní prvek, takže ten ukazatel stačí přetypovat na ten union a je to zase triviální. Přetypování nestojí v runtime nic. ZBytek udělá překladač a věřil bych tomu, že pro danou platformu to udělá hodně dobře.
CreateProcess není v API, ale ve Win API. Já používám celou řadu API a ani v jednom z nich to není :-)
No a kdo chce řešení pro POSIXové systémy (unixy, linux apod.), tak ať se podívá na fork a wait (a jejich varianty).
Porovnávej načtený znak se znakem '\n' a máš to.
A není teda problém v tom převodu z pole charů do stringu? Je třeba si uvědomit, že v těch binárních datech může být i znak číslo 0, který ovšem ta data neukončuje.
> Jde použít ukazatel na funkci jako atribut třídy?
ano
> JAk by vypadal kód?
class Xyz
{
public:
Xyz(int (*fn)(double cislo))
: fn_(fn)
{
}
int ZavolejFunkci(double d)
{
assert(fn_ != 0);
return fn_(d);
}
private:
int (*fn_)(double cislo); // Ukazatel na funkci vracejici int s parametrem typu double
};
> A bylo by možné si funkci uložit do externího souboru a poté ji díky ukazateli ze souboru nakopírovat do RAM?
Možné by to asi bylo, ale ukazatele není obecně dobré ukládat do souborů jako data. To má smysl jenom jako ladící informace, ale jinak ne. Možná by to i fungovalo, ale při sebemenší změně programu (nebo parametrů překladu) by to přestalo fungovat se staršími daty.
Lepší je uložit si to pod nějakým číslem nebo textově a při načítání to zpětně převést.