HOWTO - C/C++

Céčko není složité :o)
// Pole nespecifikované velikosti s ukazateli na funkce,
// které vrací ukazatele na funkce, které vrací void

void (*(*f[])())()
Debug výpisy
#define DEBUG(x) cerr << "DEBUG: " << __FILE__ << ":" << __LINE__ << " " \
<< __FUNCTION__ << "() " << #x << " = " << (x) << endl
OpenGL obdélník
glBegin(GL_QUADS);
	glTexCoord2f(0.0f, 0.0f); glVertex3i(-50, -50, -100);
	glTexCoord2f(1.0f, 0.0f); glVertex3i( 50, -50, -100);
	glTexCoord2f(1.0f, 1.0f); glVertex3i( 50,  50, -100);
	glTexCoord2f(0.0f, 1.0f); glVertex3i(-50,  50, -100);
glEnd();
PI ;-)

http://3.141592653589793238462643383279502884197169399375105820974944592.com/

Přetížení vstupu/výstupu
friend ostream& operator<<(ostream& o, const CList& l);

ostream& operator<<(ostream& o, CList& l)
{
    CList* tmp = &l;

    while(tmp->next != NULL)// Vsechny prvky
        o << tmp->i << " ";

    return o;
}


///////////////////////////////////////////////////////////////////////////
//// I/O support
istream& operator>>(istream& is, CColor& color);
ostream& operator<<(ostream& os, CColor& color);

///////////////////////////////////////////////////////////////////////////
//// I/O support

istream& operator>>(istream& is, CColor& color)
{
	Uint8 tmp;

	is >> tmp; color.SetR(tmp);
	is >> tmp; color.SetG(tmp);
	is >> tmp; color.SetB(tmp);
	is >> tmp; color.SetA(tmp);

	return is;
}

ostream& operator<<(ostream& os, CColor& color)
{
	os << color.GetR() << " " << color.GetG() << " "
	   << color.GetB() << " " << color.GetA();
	return os;
}
Jednoduchý makefile
TARGET		= prg
CC		= g++
CFLAGS		= -Wall
LDFLAGS		= -lm

$(TARGET): src.cpp
	$(CC) -o $(TARGET) src.cpp $(CFLAGS) $(LDFLAGS)

clean:
	rm -f $(TARGET) core
Makefile pro větší projekty
# With SDL and OpenGL support

TARGET		= prg
CC		= g++
CFLAGS		= -Wall $(shell sdl-config --cflags)
LDFLAGS		= -L/usr/X11R6/lib $(shell sdl-config --libs) -lSDL_image -lSDL_ttf -lGL -lGLU -lm
OBJECTS		= $(shell ls *.cpp | sed 's/.cpp/.o/')


.PHONY: depend
.PHONY: run
.PHONY: clean


%.o: %.cpp
	$(CC) -c $< $(CFLAGS)

$(TARGET): $(OBJECTS)
	$(CC) -o $(TARGET) $(OBJECTS) $(LDFLAGS)

# Mozna bude nadavat kvuliva STL a SDL hlavickam, ale je to OK
depend:
	makedepend $(shell ls *.cpp)

run:
	./$(TARGET)

clean:
	rm -f $(TARGET) *.o core


# DO NOT DELETE

Pythonovské skripty spouštěné z Céčka
http://www.linuxjournal.com/article/8497

///// Makefile /////

TARGET		= prg
CC		= g++
CFLAGS		= -Wall -I/usr/include/python2.4
LDFLAGS		= -lpython2.4 -lm -L/usr/lib/python2.4/config

$(TARGET): python_v_cecku.cpp
	$(CC) -o $(TARGET) python_v_cecku.cpp $(CFLAGS) $(LDFLAGS)

clean:
	rm -f $(TARGET) core


///// source.cpp /////

#include <Python.h>
#include <stdio.h>

void exec_pycode(const char* code)
{
	Py_Initialize();
	PyRun_SimpleString(code);
	Py_Finalize();
}

int main(int argc, char *argv[])
{
	FILE *fp;
	long len;
	char *buf;

	fp=fopen("script.py", "rb");
	fseek(fp, 0, SEEK_END);
	len=ftell(fp);
	fseek(fp, 0, SEEK_SET);
	buf = (char *)malloc(len);
	fread(buf, len, 1, fp);
	fclose(fp);

	exec_pycode(buf);

	free(buf);

	return 0;
}


///// script.py /////

print 'Program vypise nejvyssi zadane cislo, pri zaporne hodnote se ukonci'

act = 5
max = None

while act > -1:
    try:
        act = int(raw_input())
    except ValueError:
        print 'Invalid Number'
        continue

    if act > max:
        max = act

print 'Nejvyssi zadane cislo:', max
Přátelské objekty a funkce
class NejakaTrida
{
	friend class CTrida;
	friend ostream& operator<<(ostream&, const CTrida&);
};
Zákaz kopírování objektů
class CTrida
{
// Metody se nemusí definovat (asi)
private:
	CTrida::CTrida(const CTrida&);
	CTrida& operator=(const CTrida&);
};
Zákaz implicitních koverzí u tříd
class CCislo
{
public:
	// Nikdy se nepoužije pro implicitní konverzi
	explicit CCislo(int cis);

private:
	int cislo;
};
Šablona auto_ptr
#include <memory>

auto_ptr<CTrida> uk(new CTrida(parametr));
// Paměť se uvolňuje automaticky
Zjištění jména třídy
#include <typeinfo>// ???

CTrida obj;
cout << type_id(obj).name() << endl;
Načtení celého souboru do paměti
    ifstream infile(file_src, ios::in | ios::binary);
    if(!infile)
    {
        cerr << "Cannot open " << file_src << endl;
        return;
    }

    infile.seekg(0, ios::end);
    long file_size = infile.tellg();
    infile.seekg(0, ios::beg);
    char* file_content = new char[file_size];
    infile.read(file_content, file_size);
    infile.close();
Barevný výstup textu (musí být podpora v shellu)
#include <stdio.h>

/* Attributes */
#define RESET           0
#define BRIGHT          1
#define DIM             2
#define UNDERLINE       3
#define BLINK           4
#define REVERSE         7
#define HIDDEN          8

/* Colors */
#define BLACK           0
#define RED             1
#define GREEN           2
#define YELLOW          3
#define BLUE            4
#define MAGENTA         5
#define CYAN            6
#define WHITE           7

void textcolor(int attr, int fg, int bg)
{
	printf("%c[%d;%d;%dm", 0x1B, attr, fg + 30, bg + 40);
}

int main(int argc, char* argv[])
{
	textcolor(BRIGHT, RED, BLACK);
	printf("In color\n");
	textcolor(RESET, WHITE, BLACK);
	return 0;
}

/*
// Bright, fg red, bg black
cerr << (char)0x1B << "[" << 1 << ";" << 31 << ";" << 40 << "m";
cerr << "[error] Something bad :-(" << endl;
cerr << (char)0x1B << "[" << 0 << ";" << 37 << ";" << 40 << "m";
// Reset, fg white, bg black
*/

http://www.linuxjournal.com/article/8603
Zřetězení stringu s charem
const string operator+(const string& str, const char ch)
{
	char tmp[2] = { ch, '\0' };
	return str + tmp;
}
Přesměrování streamu
#include <iostream>
#include <fstream>

using namespace std;

int main ()
{
	streambuf *psbuf;
	ofstream filestr;
	filestr.open ("test.txt");

	psbuf = filestr.rdbuf();
	cout.rdbuf(psbuf);

	cout << "This is written to the file" << endl;

	filestr.close();

	return 0;
}

http://www.cplusplus.com/ref/iostream/ios/rdbuf.html
Převody čísel mezi soustavami
#include <cstdlib>
strtoul()
stringstream
#include <sstream>

string GetString(void)
{
	stringstream ss;
	ss << "Klasicky" << "vystup" << " do " << "streamu";

	return ss.str();
}
Spuštění preprocesoru nad zdrojovým kódem
g++ -E soubor.cpp -std=c++98 -pedantic -Wall > preprocesovany.cpp
Formátování data a času v C++
#include <ctime>

string GenerateFilename()
{
	time_t rawtime;
	struct tm* timeinfo;
	char buffer[80];

	time(&rawtime);
	timeinfo = localtime(&rawtime);

	// transfered_YYYY-MM-DD_HH-MM-SS.dat
	strftime(buffer, 80, "transfered_%Y-%m-%d_%H-%M-%S.dat", timeinfo);

	return buffer;
}
Mapování signálů
#include <signal.h>

void sigint_handler(int param)
{
	cout << "ctrl+c pressed." << endl;
}

int main(int argc, char* argv[])
{
	signal(SIGINT, sigint_handler);

	while(true)
		;
}
Přeložení projektu z příkazové řádky (VC 2500)
"C:\Program Files\Microsoft Visual Studio 8\VC\bin\vcvars32.bat"
devenv solution.sln /Rebuild debug
devenv solution.sln /Rebuild release
Převedení řetězce na malá písmena
#include <string>
#include <algorithm>

string str = "Ahoj";
transform(str.begin(), str.end(), str.begin(), (int(*)(int))tolower);
Seřazení pole
#include <vector>
#include <algorithm>

bool CompareImages(const CImage& img1, const CImage& img2)
{
	return img1.GetPath() < img2.GetPath();
}

vector<CImage> v;
sort(v.begin(), v.end(), CompareImages);
Výpis souborů v adresáři
#include <dirent.h>

void ListDirectory(const string& path)
{
	DIR* handle = NULL;
	dirent* entry = NULL;

	if((handle = opendir(path.c_str())) == NULL)
		throw runtime_error(_("Couldn't open directory: ") + path);

	while((entry = readdir(handle)) != NULL)
		cout << entry->d_name << endl;

	closedir(handle);
}
Knihovny používané programem
[woq@woq sbkview]$ ldd sbkview
        linux-gate.so.1 =>  (0xffffe000)
        libSDL-1.2.so.0 => /usr/lib/libSDL-1.2.so.0 (0xb7ed1000)
        libSDL_image-1.2.so.0 => /usr/lib/libSDL_image-1.2.so.0 (0xb7eb6000)
        libSDL_ttf-2.0.so.0 => /usr/lib/libSDL_ttf-2.0.so.0 (0xb7eb1000)
        libSDL_gfx.so.4 => /usr/lib/libSDL_gfx.so.4 (0xb7e9f000)
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7dba000)
        libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0xb7d94000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7d89000)
        libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7c58000)
        libasound.so.2 => /usr/lib/libasound.so.2 (0xb7b97000)
        libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0xb7b93000)
        libdirectfb-0.9.so.25 => /usr/lib/libdirectfb-0.9.so.25 (0xb7b3c000)
        libfusion-0.9.so.25 => /usr/lib/libfusion-0.9.so.25 (0xb7b35000)
        libdirect-0.9.so.25 => /usr/lib/libdirect-0.9.so.25 (0xb7b26000)
        libvga.so.1 => /usr/lib/libvga.so.1 (0xb7ac6000)
        libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0xb7ab4000)
        libpng12.so.0 => /usr/lib/libpng12.so.0 (0xb7a91000)
        libz.so.1 => /usr/lib/libz.so.1 (0xb7a7d000)
        libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0xb7a12000)
        /lib/ld-linux.so.2 (0xb7f9f000)
[woq@woq sbkview]$
Tabulka symbolů programu
[woq@woq serialkas]$ nm kas
         U __assert_fail@@GLIBC_2.0
0804db08 A __bss_start
08049014 t call_gmon_start
0804dd00 b completed.5621
0804d96c d __CTOR_END__
0804d95c d __CTOR_LIST__
         U __cxa_atexit@@GLIBC_2.1.3
         U __cxa_begin_catch@@CXXABI_1.3
         U __cxa_call_unexpected@@CXXABI_1.3
         U __cxa_end_catch@@CXXABI_1.3
         U __cxa_rethrow@@CXXABI_1.3
0804dafc W data_start
0804dafc D __data_start
0804bd30 t __do_global_ctors_aux
08049040 t __do_global_dtors_aux
0804db00 D __dso_handle
0804d974 d __DTOR_END__
0804d970 d __DTOR_LIST__
0804d97c d _DYNAMIC
0804db08 A _edata
...
Memory leaks indicator
// Enable-disable the checking
#define CHECK_MEMORY_LEAKS

#ifdef CHECK_MEMORY_LEAKS
#include <set>
#include <typeinfo>
#endif // CHECK_MEMORY_LEAKS

// Base class of the class hierarchy
class BaseObject
{
public:
	BaseObject();
	virtual ~BaseObject();

	virtual string toString(void) const = 0;

	uint getID(void) const { return m_id; }
	static uint getMaxID(void) { return m_max_id; }

private:
	static uint m_max_id;
	uint m_id;

#ifdef CHECK_MEMORY_LEAKS
	static set<BaseObject*> m_allocated_objects;

public:
	static void printMemoryLeaks(void);
#endif // CHECK_MEMORY_LEAKS
};


/////////////////////////////////////////////////////////////////////////////
////

uint BaseObject::m_max_id = 0;

#ifdef CHECK_MEMORY_LEAKS
set<BaseObject*> BaseObject::m_allocated_objects = set<BaseObject*>();
#endif // CHECK_MEMORY_LEAKS


/////////////////////////////////////////////////////////////////////////////
////

BaseObject::BaseObject()
	: m_id(m_max_id++)
{
#ifdef CHECK_MEMORY_LEAKS
	m_allocated_objects.insert(this);
#endif // CHECK_MEMORY_LEAKS
}

BaseObject::~BaseObject()
{
#ifdef CHECK_MEMORY_LEAKS
	m_allocated_objects.erase(this);
#endif // CHECK_MEMORY_LEAKS
}


/////////////////////////////////////////////////////////////////////////////
////

#ifdef CHECK_MEMORY_LEAKS
void BaseObject::printMemoryLeaks(void)
{
	cerr << "================== BaseObject::printMemoryLeaks(void) ==================" << endl;

	set<BaseObject*>::const_iterator it;
	for(it = m_allocated_objects.begin(); it != m_allocated_objects.end(); it++)
		cerr << "id = " << (*it)->getID() << ", type = " << typeid(**it).name()
			<< ", tostring = " << (*it)->toString() << ", mem = " << *it << endl;

	cerr << endl;
	cerr << "Total number of memory leaks: " << m_allocated_objects.size() << endl;
}
#endif // CHECK_MEMORY_LEAKS



int main(int argc, char** argv)
{
	// ...

#ifdef CHECK_MEMORY_LEAKS
	BaseObject::printMemoryLeaks();
#endif // CHECK_MEMORY_LEAKS

	cout << "Total number of created objects: " << BaseObject::getMaxID() << endl;
	return 0;
}
Unit tests, verify macro
// TODO: check __STRING(expr) in non-Linux OS, see /usr/include/assert.h
// TODO: Try to use VERIFY() from MFC in MS Windows

// Verify macro, like assert but without exiting
#define verify(expr) \
	result = result && (expr); \
	if(!(expr)) \
		cerr << __FILE__ << ":" << __LINE__ \
		<< "   " << __STRING(expr) << endl


// Test template
bool Tests::test(void)
{
	bool result = true;

	// Add code here
	verify(true);

	return testResult(__FUNCTION__, result);
}


bool Tests::testResult(const string& testName, bool result)
{
	if(result)
		cout  << _("[ OK ]     ") << testName << endl;
	else
		cerr << _("[ FAILED ] ") << testName << endl;

	return result;
}


void Tests::run(void)
{
	uint failed = 0;

	failed += !test();

	cout << _("Number of failed tests: ") << failed << endl;
}
Paralelní build
# Dva procesory
alias make='colormake -j2'
Trace makro
#define TRACE(arg) cout << #arg << endl; arg
#define D(arg) cout << #arg " = [" << arg << "]" << endl;


// Použití
TRACE(for(int i = 0; i < 5; i++) cout << i << endl;);
D(1 + 2);

// Výstup programu
for(int i = 0; i < 5; i++) cout << i << endl;
0
1
2
3
4
1 + 2 = [3]

(Bruce Eckel: Thinking in C++ 2)
Doxygen
doxywizard

http://www-scf.usc.edu/~peterchd/doxygen/
Vyčištění kontejneru ukazatelů
struct DeleteObject
{
	template <typename T>
	void operator()(const T* ptr) const
	{
		delete ptr;
		ptr = NULL;
	}
};

for_each(v.begin(), v.end(), DeleteObject());

http://www-staff.it.uts.edu.au/~ypisan/programming/stl50.html
Mazání prvků z kontejneru
// Remove přesune hledaný prvek na konec
c.erase(remove(c.begin(), c.end(), 2004), c.end());

http://www-staff.it.uts.edu.au/~ypisan/programming/stl50.html
Kontejner ukazatelů s řazením
struct DereferenceLess
{
	template <typename PtrType>
	bool operator()(PtrType pT1, PtrType pT2) const
	{
		return *pT1 < *pT2;
	}
};

set<string*, DereferenceLess> ssp;

http://www-staff.it.uts.edu.au/~ypisan/programming/stl50.html
Dešifrování STL chyb z kompilátoru
http://www.bdsoft.com/tools/stlfilt.html
Detekce úniků paměti
valgrind --leak-check=yes <program>
Inicializace random generátoru
#include <time.h>
srand(time(NULL));
Copyright © 2001-2011 Michal Turek <WOQ (zavináč) seznam.cz>
Valid XHTML 1.0 Strict, Valid CSS