#7 Marty
Skus si pozriet knihy a ine materiali od Scott Meyersa. Zistis ako malo toho o c++ vies :) Take variadic templaty a reference kolapsing ta zabavi...
C ma oproti C++ a inym jazykom vyhodu ze kompilator je skoro vsade.
Dalsia vyhoda je v tom ze s C sa dobre pouziva z inych jazykov, vdaka tomu ze C nema pretazovanie operatorov, funkcii, namespaces, metody, templaty a ine vlastnosti ktore vyzaduju name mangling... Takze ked volate funckiu z 1 jazyka v inom jazyku, tak sa to velmi casto robi cez C interface.
C je jednoduchy jazyk (neznamena to e sa v nom pise jednoducho).
#3 ondrej39
Ved pouzi pow a vysledok pretypuj na int, ak ti ide o rychlost tak mocniny 2 si sprav cez switch(jump table) a bude to ovela rychlejsie.
Inak ipow moze vyzerat takto:
int ipow(int base, int exp){
if(exp < 0)return 0;
int res = 1;
while(exp--)res *= base;
return res;
}
#3 ellke
Aj tak to mas zle (daklaracia ma mat velkost 5).
Lepsie by sa to dalo napisat takoto:
#include <iostream>
#include <string>
using namespace std;
int main(){
enum{N = 5};
string znak[N];
cout << "Zadejte prvni znak" << endl;
for(int i = 0; i < N; ++i){
cin >> znak[i];
}
cout << endl;
for(int i = 0; i < N; ++i){
cout << znak[i] << endl;
}
return 0;
}
C++ je dost zlozity jazyk a webove tutoriali maju zlu kvalitu, doporucil by som radsej daku knihu (kludene aj vo forme pdf).
Knihy v cz/sk su vecsinou zastarale, preto sa viac oplatia knihy v eng: http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list
#40 BDS
Slo by to aj jednoduhsie:
int DruheNejmensi(unsigned velikost_pole, const int *pole){ assert(pole); assert(velikost_pole >= 1); int min_val = pole[0]; int ok = min_val; for(unsigned i = 1; i < velikost_pole; ++i){ if(pole[i] < min_val){ ok = min_val; min_val = pole[i]; } }
//edit: if(min_val == ok)return INT_MAX; return ok; }
#32 hlucheucho
http://dlang.org/
#28 hlucheucho
Ja pouzivam iterovanie pomocou indexov len ak potrebujem modifikovat vector pocas iterovania. Ak by som pouzil iteratory tak by to neskoncilo dobre :). Ak mas c++11 tak samozrejme vstavany foreach, ak mas c++14 tak std::for_each a polymorficke lambdy.
#7 Zelenáč
Naco ti je pole, nestaci nieco taketo?
#include <iostream>
enum{
N = 10,
};
int main(){
for(unsigned i = 0; i < N*N; ++i){
if(i%N == 0)std::cout << std::endl;
if(i%3 == 0)std::cout << '*';
else std::cout << '0';
}
return EXIT_SUCCESS;
}
#1 Lukáš
Mozes vratit NaN:
double deleni(const double delenec, const double delitel) {
if(delitel == 0)return 0.0/0.0; //NaN
return delenec / delitel;
}
edit: float/double moze okrem normalnych cisiel obsahovat aj kladnu a zapornu nulu, kladne a zaporne nekonecno a NaN (Not a number)
#7 ondrej39
assert vecsinou funguje tak ze v debug mode sa testuje a v release mode sa asserty ignoruju.
Tak ako ti povedal Kit, asserty nemaju byt zavysle na vstupnych datach.
Ja pouzivam asserty na otestovanie chyb ktore by nemali nikdy nastat, testovanie takychto chyb pomocou if-ov vynimiek... zbytocne spomaluje program a zneprehladnuje kod, preto sa na ne hodi asserty ktore sa v release mode ignoruju.
#15 ingiraxo
Vratenie adresy lokalnej premennej je 'undefined behavior', to znamena ze compilator moze z kodom spravyt hocico, moze to nahodou fungovat tak ako si chcel, compilator moze pouzit daku optimalizaciu ktora ti totalne rozhasi cely kod a kludne ti to moze aj zmenit status na facebooku. Preto sa nevrcaju adresy lokalnych premennych.
#12 ingiraxo
Okrem toho ze ten tvoj priklad je chybny (viz KIIV a voty), tak s nim ani nic nedosiahnes lebo ak by si rovno vratil strukturu Time tak snad skoro kazdy prekladac pouzie pouzie copy elision optimalizaciu (alebo priamo vrati navratovu hondotu cez registre ak sa tam zmesti), pripadne rovno inlinuje celu funkciu.
#1 polenog
Vecsinou je doporucovana kniha C++ Primer (5th Edition) (je aj vo forme pdf na TPB).
Vsetky knihy ktore su v slovencine/cestine su velmi zastarale.
#9 Jurin
skus si spustit toto a porozmyslat preco sa vystupy lisia:
struct Test{
Test(){std::cout << "Test::Test()\n";}
Test(Test& ){std::cout << "Test::Test(Test&)\n";}
Test(int){std::cout << "Test::Test(int)\n";}
operator int(){std::cout << "Test::operator int()\n";}
~Test(){std::cout << "Test::~Test()\n";}
};
int main(){
std::cout << "\nA:\n";{
Test x;
Test A = x;
}
std::cout << "\nB:\n";{
Test B = Test();
}
return 0;
}
Neviem ci to je v standarde, ale v gcc je mozne zadat flag -fno-elide-constructors a tym vypnut tuto optimalizaciu.
Na strane 274|31 mas presnejsie pravidla: https://isocpp.org/files/papers/N3690.pdf
#3 vrtkoo
spz by mala mat fixnu velkost, mozes spravyt nieco taketo:
enum{ SPZ_SIZE = 7 };
typedef char SPZ[SPZ_SIZE+1];
void printSPZ(SPZ* spz){
assert(spz);
assert(SPZ_SIZE >= 7);
printf("%.2s %.3s %.2s\n", (*spz), (*spz)+2, (*spz)+5);
}
void testSPZ(){
SPZ spzs[] = {
"BA123AB",
"BA353AB",
"DS353AB",
};
for(int i=0; i < 3; ++i){
printSPZ(spzs+i);
}
}
#1 JakubD
std::vector interne uchovava 3 hodnoty, alokovane pole(pointer na data), velkost alokovaneho pola ( capacity() ) a pocet prvkov(size()). Metoda rezerve() len zvysuje kapacitu, nevytvara konkretne prvky. Na pridanie prvku do vectora s pouziva push_back/emplace_back/insert/... alebo konstruktor std::vector(pocet_prvkov, defaultna_hodnota). Metoda clear() vola destructory na vsetky prvky ktore boly pridane cez push_back/emplace_back/insert/... ale nemeni kapacitu(capacity()), len nastavy pocet prvkov(size()) na 0 a zavola destructory.
#11 vrtkoo
ak bude v subore viac riadkov ako 30 tak si budes prepisovat data na stacku, preto tam treba mat este jednu podmienku:
while (i < 30 && (fgets(udaje[i], 52, subor)) != NULL){
++i;
}
Radsej nepouzivaj magicke cisla.
#9 vrtkoo
Cez staticke pole, potom ani nepotrebujes pomocnu premennu str, rovno budes zapisovat do toho pola.
void proc(){
const int max_udaje_len = 30;
const int max_data_size = 52;
int udaje_len = 0;
char udaje[max_udaje_len][max_data_size];
FILE* file;
if(!(file = fopen("data/subor.txt", "r"))){
printf("subor fail");
return;
}
while(udaje_len < max_udaje_len && fgets(udaje[udaje_len], max_data_size, file)){
++udaje_len;
}
if(ferror(file)){
printf("subor fail");
goto cleanup_file;
}
for(int i = 0; i < udaje_len; ++i){
printf("%d. %s\n", i, udaje[i]);
}
cleanup_file:
fclose(file);
}
#1 JakubD
Nemalo by byt vystupne pole vecsie ako vstupne?
Skus nieco taketo:
vector<double> in(data, data+size);
vector<fftw_complex> out((in.size()/2+1)*2, 0);
fftw_plan p;
p = fftw_plan_dft_r2c_1d(in.size(), in.begin(), out.begin(), FFTW_ESTIMATE);
fftw_execute(p);
#6 Tomáš
Ked uz by si chcel pouzit tie zbytocne alokacie a chcel by si aj spravne dealokovat data pri chybach tak by si mohol pouzit nieco taketo:
void proc(){ const int max_udaje_len = 30; const int max_data_size = 52; int udaje_len = 0; char str[max_data_size]; char** udaje; FILE* file; if(!(file = fopen("data/subor.txt", "r"))){ printf("subor fail"); return; } if(!(udaje = (char**)malloc(max_udaje_len * sizeof(char*)))){ printf("pamät fail"); goto cleanup_file; } while(udaje_len < max_udaje_len && fgets(str, max_data_size, file)){ if(!(udaje[udaje_len] = (char*)malloc(max_data_size))){ printf("pamät fail"); goto cleanup_malloc; } strcpy(udaje[udaje_len], str); ++udaje_len; }
if(ferror(file)){ printf("subor fail"); goto cleanup_malloc; } for(int i = 0; i < udaje_len; ++i){ printf("%d. %s\n", i, udaje[i]); } cleanup_malloc: for(int i = 0; i < udaje_len; ++i){ free(udaje[i]); } free(udaje); cleanup_file: fclose(file); }
Aky ocakavas vstup a aky vystup?
Toto ti funguje? :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
typedef struct zasobnik
{
int data[10000]; //pole pre pismenka a operatori ktore budem davat do zasobnika
int vrch; //vrch zasobnika
}zasobnik;
char vrch(zasobnik *s);
int priorita(char);
int je_prazdny(zasobnik *s);
char vyber(zasobnik *s);
void vloz(zasobnik *s, char x);
int je_plny(zasobnik *s);
void inicializacia(zasobnik *s);
int main()
{
zasobnik s;
char x;
int c;
inicializacia(&s); //inicializacia vrchu zasobnika
while ((c = getchar()) > 0)
{
if (c >= 'A' && c <= 'Z') //ak je to pismeno tak ho vypise
printf("%c", c);
else
if (c == '(') //ak je to lava zatvorka tak vlozi do zasobnika
vloz(&s, '(');
else
{
if (c == ')') //ak je to prava zatvorka tak..
while ((x = vyber(&s)) != '(') //..sa vybera zo zasobnika kym nenarazi na pravu zatvortku
printf("%c", x);
else //ak je to operator
{
while (priorita(c) <= priorita(vrch(&s)) && je_prazdny(&s) != 1) //porovna sa priorita operatoru
{
x = vyber(&s);
printf("%c", x);
}
vloz(&s, c); //vlozenie operatoru
}
}
}
while(je_prazdny(&s) != 1) //vyprazdnenie zasobnika
{
x = vyber(&s);
printf("%c", x);
}
getchar();
getchar();
return 0;
}
int priorita(char x){
switch(x){
case '(':
return 0;
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
}
assert(0);
}
int je_prazdny(zasobnik *s){
assert(s);
return s->vrch == -1;
}
void inicializacia(zasobnik *s){
assert(s);
s->vrch = -1;
}
void vloz(zasobnik *s, char x){
assert(s);
assert(s->vrch >= -1);
assert((s->vrch+1) < (int)(sizeof(s->data)/sizeof(int)));
s->vrch++;
s->data[s->vrch] = x; //zapisem znak
}
char vyber(zasobnik *s){
assert(s);
assert(s->vrch >= 0);
assert(s->vrch < (int)(sizeof(s->data)/sizeof(int)));
char x = s->data[s->vrch];
s->vrch--;
return x;
}
char vrch(zasobnik * s){
assert(s);
assert(s->vrch >= 0);
assert(s->vrch < (int)(sizeof(s->data)/sizeof(int)));
return s->data[s->vrch]; //vrati znak ktory je na vrchu zasobnika
}
Precompiled Headers je nestandartne riesenie (nie je definovane v c++ stndarde) ktore riesi dlhe kompilacie ktore su sposobene absenciou modulou v c++. Ak si zaciatocnik tak sa uplne vykasli na predkompilovane hlavicky a zacni sa s nimi zaoberat az ked budes mat vecsi projekt a kompilacia bude trvat dlho.
edit: Mozno dovtedy budu v standarde moduly: http://llvm.org/devmtg/2012-11/videos/Gregor-Modules.mp4 :)