| ← knihovna string.h | C/C++ | knihovna math.h → |
Knihovna <time.h> umožňuje zjistit aktuální čas. Je třeba si uvědomit, že čas je pojem relativní. Ve vašem počítači existuje jednak čas lokální a také čas globální (krom toho je také letní a zimní). Globální čas se dříve označoval jako GMT (Greenwich Mean Time), dnes jako UTC (Coordinated Universal Time). Je otázkou, jak je čas na vašem počítači nastaven. Správně by jste měli mít nastaven čas globální a lokální čas přepočítávat. Mnohde je to však naopak.
Smutnou pravdou je, že mnoho potřebných informací o datu a času vám knihovna <time.h> nepoví. Buď si budete muset potřebné výpočty sestavit sami, nebo se budete muset poohlédnout po nějaké „nadstandardní“ knihovně. Tak třeba funkci na zjištění přestupného roku si můžete napsat takto:
1: /*---------------------------------------*/ 2: /* funkce vracejici 1 pro prestupny rok, */ 3: /* jinak 0. */ 4: int prestupny_rok(int rok) 5: { 6: return (((rok % 4 == 0) && (rok % 100 != 0)) || (rok % 400 == 0)); 7: } 9: /*---------------------------------------*/
Aby bylo možné čas uchovávat v co možná nejmenším počtu bitů, zaznamenává se jako počet sekund od určitého data. Například v Unixových systémech je to od 1. 1. 1970, v MS-DOSu je to 1. 1. 1980 atp. V dnešní době je to víceméně zátěž z historických důvodů. S časem uloženým v sekundách se pracuje pomocí předdefinovaného datového typu time_t. Je to celočíselný typ, například v Linuxu je to typ long. Vzhledem k tomu, že váš program může být přeložen ve více systémech, nemůžete podle tohoto čísla vědět, jaký že je to datum a čas. Pokud však v programu zaznamenáte dvě takovéto čísla a odečtete je od sebe, zjistíte, kolik sekund mezi jejich zaznamenáním uběhlo. Takovéto jednoduché odečtení však není dle normy ANSI, proto používejte funkci difftime(), která je k tomu určena (kvůli přenositelnosti na systémy, kde time_t není definován jako celé číslo).
Rozumněji se pracuje s dalším předdefinovaným typem – tentokrát se jedná o strukturu – tm. Její definice vypadá takto:
1: struct tm { 2: int tm_sec; /* vteřiny 0-61 */ 3: int tm_min; /* minuty 0-59 */ 4: int tm_hour; /* hodiny 0-23 */ 5: int tm_mday; /* dny v měsíci 1-31 */ 6: int tm_mon; /* měsíc 0-11 */ 7: int tm_year; /* rok od 1900 */ 8: int tm_wday; /* den v týdnu 0-6, 0 je nedele */ 9: int tm_yday; /* den v roce 0-365 */ 10: int tm_isdst; /* příznak letního času*/ 11: };
Možná vás překvapí, že vteřin může být 62, ale to vážně není moje vina. Prostě to tak bylo definováno, tak se s tím smiřte. Příznak tm_isdst je nulový, pokud není letní čas a záporný, pokud není informace o času dostupná. Pokud je letní čas, je kladný.
V tabulce jsou formátovací znaky v řetězci format funkce strftime().
| %a | zkrácený název dne v týdnu |
| %A | úplný název dne v týdnu |
| %b | zkrácený název měsíce |
| %B | úplný název měsíce |
| %c | datum a čas |
| %d | den v měsíci 01-31 |
| %H | hodina 00-23 |
| %I | hodina ve 12-ti hodinovém formátu 01-12 |
| %j | den v roce 001-366 |
| %m | měsíc 01-12 |
| %M | minuty 00-59 |
| %p | am pro dopoledne, pm pro odpoledne |
| %S | vteřiny 00-61 |
| %u | den v týdnu 1-7, 1 = pondělí |
| %U | týden v roce 01-53 (neděle je prvním dnem v týdnu) |
| %V | týden v roce 01-53 (pondělí je prvním dnem v týdnu) |
| %w | den v týdnu 0-6 (0 = neděle) |
| %x | datum v lokálním formátu |
| %X | čas v lokálním formátu |
| %y | poslední dvě číslice roku 00-99 |
| %Y | rok |
| %Z | název časového pásma |
Kromě těchto formátovacích znaků může formátovací řetězec obsahovat jakékoliv další písmena (včetně např. '%%' pro '%').
V prvním příkladu ukážeme, jak lze čas využít k inicializaci náhodných čísel (viz. funkce rand() a srand()). V příkladu simulujeme losování sportky. Je to spíš ukázka práce s náhodnými čísly než s časem. Ukázka práce s časem je v dalším příkladě.
1: /*------------------------------------------------*/ 2: /* sportka.c */ 4: #include <stdio.h> 5: #include <stdlib.h> /* zde jsou definovany funkce rand() a srand() */ 6: #include <time.h> 8: #define CENA 16 /* korun za vsazeni 1 sloupce */ 10: /* funkce uhodnuto zjisti, kolik cisel z pole cisla[6] je stejnych jako v poli 11: * prvnich 6 cisel v poli tah[7]. Posledni cislo v tomto poli je dodatkove! */ 13: unsigned int uhodnuto(unsigned int *cisla, unsigned int *tah) 14: { 15: unsigned int i, j, vyhra = 0; 17: for (j = 0; j < 6; j++) 18: for (i = 0; i < 6; i++) 19: if (cisla[j] == tah[i]) { 20: vyhra++; /* pocet uhadnutych cisel */ 21: break; /* ukonci vnitrni cyklus */ 22: } 23: return vyhra; 24: } 26: /* funkce vyhra_sportky urci na zaklade uhodnutych cisel co jste vyhrali. 27: * Pokud jste uhodli 5 cisel a 6te je stejne jako dodatkove, pak mate "druhou" */ 28: unsigned int vyhra_sportky(unsigned int uhodnute, unsigned int *cisla, 29: unsigned int *tah) 30: { 31: unsigned int i, vyhra = 0; 32: switch (uhodnute) { 33: case 6: 34: vyhra = 1; /* mate prvni */ 35: break; 36: case 5: 37: vyhra = 3; /* mate treti */ 38: /* ale mozna mame druhou */ 39: for (i = 0; i < 6; i++) 40: if (cisla[i] == tah[6]) { 41: vyhra = 2; /* mame druhou */ 42: break; 43: } 44: break; 45: case 4: 46: vyhra = 4; 47: break; 48: case 3: 49: vyhra = 5; /* mate patou */ 50: break; 51: default: /* to je tu trosku zbytecne, 52: protoze vyhra = 0 je jiz vyse, ale rozhodne to neni na 53: skodu uz kvuli srozumitelnosti kodu */ 54: vyhra = 0; /* nic jste nevyhrali */ 55: } 56: return vyhra; 57: } 59: /* tato funkce urci, kolik penez jste vyhrali */ 60: unsigned long penez(unsigned int vyhra) 61: { 62: switch (vyhra) { 63: case 5: 64: return rand() % 50 + 30; 65: case 4: 66: return rand() % 500 + 250; 67: case 3: 68: return rand() % 5000 + 1000; 69: case 2: 70: return rand() % 500000 + 50000; 71: case 1: 72: return (unsigned long) ((rand() % 1000000) + 1) * (rand() % 10) + 73: 1000000; 74: default: 75: return 0; 76: } 77: } 79: /* kontroluje, zda cislo exituje v poli zadane delky */ 80: int existuje(unsigned int cislo, unsigned int *pole, unsigned int delka) 81: { 82: unsigned int i; 83: for (i = 0; i < delka; i++) 84: if (cislo == pole[i]) 85: return 1; 86: return 0; /* cislo se nenaslo */ 87: } 89: int main(void) 90: { 91: unsigned int i, cisla[6], tah[7], vyhra, uhodnute, finance, vyhrano; 92: unsigned int chci_vyhrat; 93: unsigned long vyhry[] = { 0, 0, 0, 0, 0, 0 }; /* nic, prvni, druha, treti ... 94: vyhra "nic" bude zrejme velmi casto, proto je pole typu long int */ 95: unsigned long cyklus = 0; 96: time_t cas1, cas2; 98: (void) time(&cas1); /* navratovou hodnotu ignorujeme */ 99: srand((unsigned int) time(NULL)); /* vystupni hodnotu musime z formatu 100: time_t zkonvertovat na typ unsigned int */ 102: /* inicializace */ 103: vyhrano = 0; 105: printf("Zadejte poradi, ktere chcete vyhrat (0,1,2,3,4,5): "); 106: scanf("%u", &chci_vyhrat); 108: /* losovani vsazenych cisel do sportky */ 109: for (i = 0; i < 6; i++) { 110: cisla[i] = (rand() % 49) + 1; 111: if (existuje(cisla[i], cisla, i)) 112: i--; /* cislo jiz bylo vylosovano, 113: bude se losovat znovu */ 114: } 116: /* tisk */ 117: printf("Vsazena cisla:"); 118: for (i = 0; i < 6; i++) 119: printf("%3u", cisla[i]); 120: printf("|\n"); 122: printf("Cyklus :%-23s| Vyhrano Vyhry: 1 2 3 4 5 0\n", 123: " Vylosovane Cisla"); 125: /* cyklus, dokud nevyhraji co chci */ 126: do { 127: /* losovani sportky */ 128: for (i = 0; i < 7; i++) { 129: tah[i] = (rand() % 49) + 1; 130: if (existuje(tah[i], tah, i)) 131: i--; /* cislo jiz bylo vylosovano, 132: bude se losovat znovu */ 133: } 135: /* tisk vysledku */ 136: printf("\r%8ld:", ++cyklus); 138: for (i = 0; i < 6; i++) 139: printf("%3u", tah[i]); 140: printf(" /%3u", tah[6]); /* dodatkove cislo */ 142: uhodnute = uhodnuto(cisla, tah); /* pocet uhodnutych cisel */ 143: vyhra = vyhra_sportky(uhodnute, cisla, tah); /* prvni, druha atp. */ 144: finance = penez(vyhra); 145: vyhry[vyhra] += 1; /* vyhry[vyhra]++; */ 147: vyhrano += finance; 148: printf("|%10ld[Kc] ", (unsigned long) vyhrano - cyklus * CENA); 150: for (i = 1; i < 6; i++) 151: printf(" %2ld", vyhry[i]); 153: printf(" %2ld", vyhry[0]); 154: /* funkce fflush() zajisti, ze program nebude pokracovat dale, dokud se 155: * vystup skutecne nezobrazi v stdout (tj. na obrazovce) */ 156: fflush(stdout); 157: if (!chci_vyhrat) 158: break; /* nechci nic vyhrat, tj. chci_vyhrat == 0 */ 159: } while ((chci_vyhrat < vyhra) || (vyhra == 0)); 161: cas2 = time(NULL); /* ziskame totez jako (void) time(&cas2); */ 162: printf("\nZiskal jste %i - %i*%ld = %ld Kc\n", vyhrano, CENA, cyklus, 163: vyhrano - CENA * cyklus); 164: printf("Cele to trvalo %u vterin.\n", 165: (unsigned int) difftime(cas2, cas1)); 167: return 0; 168: } 170: /*------------------------------------------------*/
Možný výstup:
Zadejte poradi, ktere chcete vyhrat (0,1,2,3,4,5): 1 Vsazena cisla: 45 30 26 25 1 3| Cyklus : Vylosovane Cisla | Vyhrano Vyhry: 1 2 3 4 5 0 4843101: 1 26 30 3 45 25 / 49| -68238394[Kc] 1 1 77 4696 85315 4753011 Ziskal jste 9251222 - 16*4843101 = -68238394 Kc Cele to trvalo 968 vterin.
Doufám, že vás tento příklad odnaučí sázet :).
Ještě musím upozornit na jednu záludnost v programu. Týká se to velikosti datových typů. Vidíte, že například proměnná cyklus je typu long. Je to proto, protože při čekání na „první“ to může trvat velice dlouho. Hrozí tak, že kapacita této proměnné bude vyčerpána. Dojde tak k „přetečení“ a to může vést k chybnému chování programu (například skončí dřív, než je „první“ vyhrána). To se týká také sčítání výhry ...
Tento příklad už je poněkud klidnější a ukáže použití struktury tm.
1: /*------------------------------------------------*/ 2: /* tm1.c */ 4: #include <stdio.h> 5: #include <time.h> 6: #define MAX 80 8: int main(void) 9: { 10: time_t cas; 11: /* jestli pracujete se strukturou tm nebo ukazatelem na tuto strukturu, 12: * to je vcelku jedno, ukazu oboji. */ 13: struct tm gtmcas; 14: struct tm *ltmcas; 15: char retezec[MAX]; 17: cas = time(NULL); 19: gtmcas = *(gmtime(&cas)); 20: ltmcas = localtime(&cas); 22: /* vsimnete si, ze retezec vraceny funkcemi ctime a asctime je jednak 23: * v anglictine a take na konci ukoncen znakem '\n' (coz je v praxi tak 24: * trochu neprijemne, ze). Vyrazi LC a UTC nam kvuli tomu prejdou az na 25: * dalsi radek */ 26: printf("Je prave \"%s\" LC\n", ctime(&cas)); 27: printf("Je prave \"%s\" GMT\n", asctime(>mcas)); 28: printf("Je prave \"%s\" LC\n", asctime(ltmcas)); 30: strftime(retezec, MAX - 1, "Je prave %A %d.%m.%Y, %I:%M %p LC", 31: ltmcas); 32: printf("%s\n", retezec); 33: printf("Tm(LC): %02i.%02i.%04i\n", ltmcas->tm_wday, ltmcas->tm_mon, 34: ltmcas->tm_year + 1900); 35: cas = (time_t) 0; 36: printf("Pocatek vseho je %s", ctime(&cas)); 38: return 0; 39: } 41: /*------------------------------------------------*/
Možný výstup z programu:
Je prave "Fri Aug 29 15:31:04 2003 " LC Je prave "Fri Aug 29 13:31:04 2003 " GMT Je prave "Fri Aug 29 15:31:04 2003 " LC Je prave Friday 29.08.2003, 03:31 PM LC Tm(LC): 05.07.2003 Pocatek vseho je Thu Jan 1 01:00:00 1970
| ← knihovna string.h | C/C++ | knihovna math.h → |
