Příloha A. Řešení cvičení

A.1. Cvičení z kapitoly 2

Úkol k textu

Zadání 1)

Napište program, který načte dvě celá čísla a poté vytiskne jejich součet.
cvi/sum2num.c
Řešení
/******************************
*	sum2num.c
*	3.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 int a,b,c;
 
 printf("Zadej prvni cislo: ");
 scanf("%d", &a);
 printf("Zadej druhe cislo: ");
 scanf("%d", &b);
 c = a + b;
 printf("Soucet cisel %d + %d je %d",a,b,c);
 
 return 0;
} 

A.2. Cvičení z kapitoly 3

Úkol k textu

Zadání 1)

Co je chybné v těchto jménech proměnných?

  1. pocet-hodin
  2. $suma
  3. black+white
  4. 9krat

Řešení
Řešení
  1. Ve jménu proměnné nelze použít spojovník
  2. Ve jménu proměnné nelze použít znak $
  3. Ve jménu proměnné nelze použít znak +
  4. Jméno proměnné nesmí začínat číslicí
Úkol k textu

Zadání 2)

Co je chybně na této části programu?
/* timto se nacte cislo
scanf ("%d", &num);
Řešení
Řešení

Chybí ukončovací znak komentáře */.

Úkol k textu

Zadání 3)

Napište program, který vytiskne Mám rád jazyk C - pomocí tří konstantních řetězců.
cvi/i_love_c.c
Řešení
/******************************
*	i_love_c.c
*	4.4.2002
******************************/

#include <stdio.h>;

int main(void)
{
 const char *prvni = "Mam rad";
 const char *druhy = "jazyk";
 const char *treti = "C";

 printf("%s %s %s", prvni, druhy, treti);
 
 return 0;
} 
Úkol k textu

Zadání 4)

Napište program, který přečte a vytiskne hodnotu typu long int.

cvi/long_int.c
Řešení
/******************************
*	long_int.c
*	4.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 long int i;
 
 printf("Zadejte cislo: ");
 scanf ("%ld", &i);
 printf("%ld", i);
 
 return 0;
} 
Úkol k textu

Zadání 5)

Co je to ukazatel?
Řešení
Řešení

Ukazatel je proměnná, která obsahuje adresu jiné proměnné.

Úkol k textu

Zadání 6)

Jaké jsou ukazatelové operátory a jaká je jejich funkce?
Řešení
Řešení

Ukazatelové operátory jsou * a &. Operátor * vrací hodnotu objektu, na který ukazuje ukazatel, který před ním stojí. Operátor & vrací adresu proměnné, před kterou stojí.

A.3. Cvičení z kapitoly 4

Úkol k textu

Zadání 1)

Napište program, který načte dvě desetinná čísla (použijte typ float) a pak vytiskněte jejich součet.
cvi/2xfloat.c
Řešení
/******************************
*	2xfloat.c
*	4.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 float i,j;
 
 printf("Zadejte dve cisla: ");
 scanf("%f",&i);
 scanf("%f",&j);
 printf("Jejich soucet je: %f",i+j);
 
 return 0;
}
Úkol k textu

Zadání 2)

Napište program, který vypočte objem kvádru. Program se bude ptát uživatele na jednotlivé rozměry a pak vypíše objem.
cvi/kvadr.c
Řešení
/******************************
*	kvadr.c
*	4.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 float delka, sirka, vyska;
 
 printf("Zadej delku: ");
 scanf("%f",&delka);
 printf("Zadej sirku: ");
 scanf("%f",&sirka);
 printf("Zadej vysku: ");
 scanf("%f",&vyska);
 printf("Objem je %f ", delka*sirka*vyska);
 
 return 0;
}
Úkol k textu

Zadání 3)

Napište program, který vypočítá počet sekund v nepřestupném roce.
cvi/secs.c
Řešení
/******************************
*	secs.c
*	4.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 printf("Pocet sekund v roce: ");
 printf("%f", 60.0 * 60.0 * 24.0 * 365.0);
 
 return 0;
} 
Úkol k textu

Zadání 4)

Je tento výraz pravdivý?
!(10==9)
Řešení
Řešení
Ano
Úkol k textu

Zadání 5)

Dávají tyto dva výrazy stejný výsledek?
  1. 0&&1||1
  2. 0&&(1||1)
Řešení
Řešení
Ne, první je pravdivý, druhý je nepravdivý.
Úkol k textu

Zadání 6)

Jelikož hodnota v pohyblivé řádové čárce nemůže být použita spolu s operátorem %, jak můžete upravit tento příkaz?
x = 123.123 % 3 ;
Řešení
Řešení
x = (int) 123.123 % 3 ;
Úkol k textu

Zadání 7)

Jedním zvláště dobrým příkladem použití operátoru ? je ochrana před dělením nulou. Napište program, který přečte dvě celá čísla zadaná uživatelem a vypíše výsledek dělení prvního čísla druhým. Použijte ? abyste zabránili dělením nulou.
cvi/div_zero.c
Řešení
/******************************
*	div_zero.c
*	4.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 int i, j, vysledek;
 
 printf("Zadejte dve cela cisla: ");
 scanf("%d %d", &i, &j);
 
 vysledek = j ? i/j : 0;   /*pravda je jakakoliv nenulova hodnota */
 printf("%d", vysledek);
 
 return 0;
}
Úkol k textu

Zadání 8)

Převeďte následující příkaz na jeho ekvivalentní příkaz pomocí operátoru ?.
if(a>b) pocet = 5;
else pocet = 10;
Řešení
Řešení
pocet = a>b ? 5 : 10:
Úkol k textu

Zadání 9)

Jaký je výsledek těchto operací?
  1. 10100011 & 01011101
  2. 01011101 | 11111011
  3. 01010110 ^ 10101011
Řešení
Řešení
  1. 00000001
  2. 11111111
  3. 11111101

A.4. Cvičení z kapitoly 5

Úkol k textu

Zadání 1)

Je tento úsek programu správný?
if(pocet < 100)
   printf("Cislo je mensi nez 100.\n");
   printf("Jeho druha mocnina je: %d", pocet * pocet);
}
Řešení
Řešení
Ne, chybí otevírací složená závorka.
Úkol k textu

Zadání 2)

Napište program, který uživatele požádá o zadání celého čísla a pak vypíše zda je číslo liché nebo sudé. (Rada: použijte operátor modulo %).
cvi/even_odd.c
Řešení
/******************************
*	even_odd.c
*	4.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 int i;
 
 printf("Zadejte cislo: ");
 scanf("%d",&i);
 if((i%2)==0) printf("Sude cislo");
 if((i%2)==1) printf("Liche cislo");
 
 return 0;
}
Úkol k textu

Zadání 3)

Napište program, který si vyžádá dvě celá čísla a pak zobrazí podle volby uživatele buď součin nebo součet.
cvi/add_mul.c
Řešení
/******************************
*	add_mul.c
*	4.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 int a,b,c;

 printf("Zadejte prvni cislo: ");
 scanf("%d",&a);
 printf("Zadejte druhe cislo: ");
 scanf("%d",&b);
 printf("Zadejte 0 pro secteni, 1 pro vynasobeni: ");
 scanf("%d",&c);
 switch(c)
 {
	case 0: printf("Soucet cisel %d a %d je %d",a,b,a+b);
				 break;

	case 1: printf("Soucin cisel %d a %d je %d",a,b,a*b);
				 break;

	default: printf("Stisknuta jina klavesa nez 0 nebo 1");
 }

 return 0;
}
Úkol k textu

Zadání 4)

Co je špatně na této části programu?
float f;

scanf("%f",&f);

switch(f):
{
 case 10.05:
 .
 .
 .
}
Řešení
Řešení
Pro řízení příkazu switch nelze použít hodnoty s pohyblivou řádovou čárkou.
Úkol k textu

Zadání 5)

Napište program, který načte zadaný znak a rozhodne zda je souhláska či samohláska.
cvi/sou_samo.c
Řešení
/******************************
*	sou_samo.c
*	4.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 char c;

 printf("Zadejte znak: ");
 scanf("%c",&c);

 switch(c)
 {
	case 'a':
	case 'e':
	case 'i':
	case 'o':
	case 'u':
	case 'y': printf("Samohlaska");
				 break;
	default: printf("Souhlaska");
 }
 return 0;
}
Úkol k textu

Zadání 6)

Napište program, který vytiskne čísla mezi 17 a 100, která budou beze zbytku dělitelná 17.
cvi/div17.c
Řešení
/******************************
*	div17.c
*	4.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 int i;

 for(i=17;i<101; i++)
 {
	if((i%17)==0) printf("\n%d",i);
 }
 return 0;
}
Úkol k textu

Zadání 7)

Napište program, který převádí galony na litry. Použijte cyklus do, aby mohl uživatel převody opakovat. (Jeden galon je asi 3,7854 litrů).
cvi/galons.c
Řešení
/******************************
*	galons.c
*	4.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 float galony;

 printf("Zadejte galony: ");
 scanf("%f",&galony);

 do
 {
	printf("Litry: %f\n", galony * 3.7854);
	printf("Zadejte galony nebo 0 pro ukonceni: ");
	scanf("%f",&galony);
 }
 while(galony != 0);

 return 0;
}

A.5. Cvičení z kapitoly 6

Úkol k textu

Zadání 1)

Napište program, který bude mít alespoň dvě funkce a vytiskne Co se v mládí naučíš, ve stáří zapomeneš.
cvi/mladi.c
Řešení
/******************************
*	mladi.c
*	16.4.2002
******************************/

#include <stdio.h>

void cast1(void);
void cast2(void);

int main(void)
{
	cast1();
	cast2();

	return 0;
}

void cast1(void)
{
 printf("Co se v mladi naucis, ");
}

void cast2(void)
{
 printf("ve stari zapomenes.");
}
Úkol k textu

Zadání 2)

Napište program, který použije funkci convert(), která vyzve uživatele k zadání částky v korunách a převede ji na dolary (Použijte směnný kurs např. 40 Kč za dolar). Vypište převedenou částku v dolarech.
cvi/dolary.c
Řešení
/******************************
*	dolary.c
*	16.4.2002
******************************/

#include <stdio.h>

int convert();

int main(void)
{
 printf("Dolary: %d", convert());

 return 0;
}

int convert()
{
 int koruny;

 printf("Zadejte castku v korunach: ");
 scanf("%d", &koruny);
 return koruny/40;
}
Úkol k textu

Zadání 3)

Co je v tomto programu chybné?
#include <stdio.h>

int f1(void);

int main(void)
{
 double odpoved;
 
 odpoved = f1();
 printf("%f",odpoved);
 
 return 0;
}

void f1(void)
{
 return 100;
}
Řešení
Řešení
Program je teoreticky v pořádku. Funkce f1() však vrací celočíselnou hodnotu, ale ta se přiřazuje proměnné typu double.
Úkol k textu

Zadání 4)

Co je chybné v této funkci?
void func(void)
{
 int i;
 printf("Zadejte cislo: ");
 scanf("%d", &i);
 
 return i;
}
Řešení
Řešení
Funkce je deklarována s návratovým typem void a nemůže tudíž vracet žádnou hodnotu.
Úkol k textu

Zadání 5)

Je tento program správný? Pokud ne, proč?
#include <stdio.h>

myfunc(int num, int min, int max);

int main(void)
{
 int i;
 
 printf("Zadejte cislo mezi 1 a 10: ");
 myfunc(&i, 1, 10);
 
 return 0;
}

void myfunc(int num, int min, int max)
{
 do
 { 
   scanf("%d", num);
 }
 while(*num<min || *num>max);
}
Řešení
Řešení
Ne, funkce myfunc() se volá s ukazatelem na první argument místo se samotným argumentem.
Úkol k textu

Zadání 6)

Vysvětlete rozdíl mezi voláním funkce hodnotou a voláním funkce odkazem.
Řešení
Řešení
Při volání hodnotou se funkci předává hodnota argumentu. Při volání odkazem se funkci předává adresa argumentu.
Úkol k textu

Zadání 7)

Co je špatně v této rekurzivní funkci?
void f(void)
{
 int i;
 
 printf("in f() \n");
 
 /* volani f() 10krat */
 for(i=0; i<10; i++) f();
}
Řešení
Řešení
Funkce volá sama sebe, dokud program nezhavaruje, protože zde není žádná podmínka, která zabraňuje neustálému opakování rekurze.
Úkol k textu

Zadání 8)

Napište program, který vypisuje na obrazovku řetězec znak po znaku pomocí rekurzivní funkce.
cvi/rekurze.c
Řešení
/******************************
*	rekurze.c
*	16.4.2002
******************************/

#include <stdio.h>

void display(char *p);

int main(void)
{
 display("Zobraz tento text");

 return 0;
}

void display(char *p)
{
 if (*p)
 {
  printf("%c", *p);
  display(p+1);
 }
}

A.6. Cvičení z kapitoly 7

Úkol k textu

Zadání 1)

Napište program, který zobrazí ASCII kódy znaků AZ a az. Jak se od sebe liší kódy velkých a malých písmen?
cvi/ascii.c
Řešení
/******************************
*	ascii.c
*	16.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 char ch;
 
 for(ch='A'; ch<='Z'; ch++)
	 printf("%d ", ch);
 
 printf("\n");
 
 for(ch='a'; ch<='z'; ch++)
	 printf("%d ", ch);

 return 0;
}
Úkol k textu

Zadání 2)

Je tento program správný? Pokud ne, proč?
#include <stdio.h>

int main(void)
{
 char p, *q;
 
 printf("Zadejte retezec: ");
 p = gets(q);
 printf(p);
 
 return 0;
}
Řešení
Řešení
Ne. Program je chybný, protože p musí být pointer.
Úkol k textu

Zadání 3)

Napište program, který vypisuje tabulku čísel. Každý řádek obsahuje číslo a jeho druhou a třetí mocninu. Tabulka začíná číslem 2 a končí číslem 100.
cvi/tab_num.c
Řešení
/******************************
*	tab_num.c
*	16.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 unsigned long i;
 
 for(i=2; i<=100; i++)
    printf("%-10lu %-10lu %-10lu\n", i, i*i, i*i*i);
	
 return 0;
} 	
Úkol k textu

Zadání 4)

Jak byste vypsali tento řádek pomocí funkce printf()?
Sleva: 40% puvodni ceny
Řešení
Řešení
printf("Sleva: 40%% puvodni ceny");
Úkol k textu

Zadání 5)

Ukažte jak zobrazit číslo 1023.231 tak aby se vypisovala jen dvě desetinná čísla.
Řešení
Řešení
printf("%.2f", 1023.231);
Úkol k textu

Zadání 6)

Napište program, který načte desetinné číslo a pak zvlášť zobrazí jeho celou a desetinnou část.
cvi/des_cisl.c
Řešení
/******************************
*	des_cisl.c
*	16.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 int i,j;
 
 printf("Zadejte desitinne cislo: ");
 scanf("%d.%d",&i,&j);
 printf("Cela cast: %d, desetinna cast: %d",i,j);
 
 return 0;
}
Úkol k textu

Zadání 7)

Je tento úsek správný? Pokud ne, proč?
char ch;
scanf("%2c", &ch);
Řešení
Řešení
Ne. Znak může mít maximální výstupní délku 1.

A.7. Cvičení z kapitoly 8

Úkol k textu

Zadání 1)

Co je __FILE__ a co představuje?
Řešení
Řešení
__FILE__ je předdefinované makro, které obsahuje jméno právě překládaného souboru.
Úkol k textu

Zadání 2)

Pomocí #ifdef ukažte, jak podmíněně přeložit tento úsek programu v závislosti na tom, zda je nebo není definováno DEBUG.
if(!(j%2))
{
 printf("j = %d\n",j);
 j = 0;
}
Řešení
Řešení
#ifdef DEBUG
if(!(j%2))
{
 printf("j = %d\n",j);
 j = 0;
}
#endif
Úkol k textu

Zadání 3)

Je tento úsek správný? Pokud ne, ukažte jak jej opravit.
#define NUMBER

#ifdef !NUMBER
.
.
.
#endif
Řešení
Řešení
Ne. U #ifdef nelze použít výraz jako je !NUMBER. Musíme tuto část opravit, například takto:
#ifndef NUMBER
.
.
.
#endif
Úkol k textu

Zadání 4)

Jaký je rozdíl mezi použitím uvozovek a úhlových závorek u direktivy #include?
Řešení
Řešení
Když zadáme jméno souboru v úhlových závorkách, překladač hledá soubor způsobem, který je závislý na implementaci - ve standardním adresáři pro include. Když uzavřeme jméno souboru do dvojitých uvozovek, překladač se nejprve snaží nalézt soubor jiným způsobem, který je opět závislý na implementaci - v aktivním, pracovním adresáři. Pokud se mu to nepodaří, začne jej hledat, jako bychom jméno souboru zadali v úhlových závorkách.

A.8. Cvičení z kapitoly 9

Úkol k textu

Zadání 1)

Napište program s cyklem for, který počítá od 0 do 9 a vypisuje čísla na obrazovku. Čísla vypisujte pomocí ukazatele.
cvi/num_0-9.c
Řešení
/******************************
*	num_0-9.c
*	16.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 int i, *p;
 
 p = &i;
 
 for(i=0; i<10; i++)
    printf("%d ",*p);

 return 0;
} 
Úkol k textu

Zadání 2)

Ukažte jak deklarovat ukazatel na double
Řešení
Řešení
double *p;
Úkol k textu

Zadání 3)

Napište program, který přiřazuje hodnotu proměnné nepřímo, pomocí ukazatele na tuto proměnnou.
cvi/poi2var.c
Řešení
/******************************
*	poi2var.c
*	16.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 int i, *p;
 
 p = &i;
 *p = 10;
 printf("%d",i);
 
 return 0;
}
Úkol k textu

Zadání 4)

Co je špatně na tomto úseku programu?
#include <stdio.h>

int main(void)
{
 int i, count[10];
 
 for(i=0; i<100; i++)
 {
  printf("Zadejte cislo: ");
  scanf("%d",&count[i]);
 }
.
.
.
}
Řešení
Program překračuje meze pole count. To má pouze 10 prvků, ale program s ním pracuje, jako by mělo prvků 100.
Úkol k textu

Zadání 5)

Napište program, který načte deset čísel zadaných uživatelem a ohlásí zda jsou některá z nich shodná.
cvi/10_cisel.c
Řešení
/******************************
*	10_cisel.c
*	14.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 int i[10], j, k, souhlas;
 
 printf("Zadejte 10 cisel: \n");
 for(j=0; j<10; j++)
    scanf("%d", &i[j]);
	
 /* kontrola shody */
 for(j=0; j<10; j++)
 {
  souhlas = i[j];
  for(k=j+1; k<10; k++)
  {
   if(souhlas == i[k])
	 printf("Nalezena shoda v cisle %d\n",souhlas);
  }
 }
   
 return 0;
}
Úkol k textu

Zadání 6)

Co je špatně na tomto úseku programu?
int *p, i;
p = &i;
p = p * 8;
Řešení
Řešení
Ukazatel nelze násobit.
Úkol k textu

Zadání 7)

Můžete k ukazateli přičíst neceločíselnou hodnotu?
Řešení
Řešení
Ne, můžete přičítat a odečítat pouze celočíselné hodnoty.
Úkol k textu

Zadání 8)

Napište program, který přečte řetězec a pak jej vypíše na obrazovku pozpátku.
cvi/inv_strn.c
Řešení
/******************************
*	inv_strn.c
*	16.4.2002
******************************/

#include <stdio.h>
#include <string.h>

int main(void)
{
 char str[80];
 int i;
 
 printf("Zadejte retezec: ");
 gets(str);
 
 for(i=strlen(str-1); i>=0; i--)
    printf("%c", str[i]);
	
 return 0;
}
Úkol k textu

Zadání 9)

Co je špatně na tomto programu?
#include <stdio.h>
#include <string.h>

int main(void)
{
 char str[5];
 
 strcpy(str, "tento text");
 printf(str);
 
 return 0;
}
Řešení
Řešení
Řetězec str není dost dlouhý, aby se do něj vešel řetězec "tento text".
Úkol k textu

Zadání 10)

Napište program, který přečte řetězec a pak jej vypíše na obrazovku pozpátku.
cvi/arr3x3x3.c
Řešení
/******************************
*	arr3x3x3.c
*	16.4.2002
******************************/

#include <stdio.h>

int main(void)
{
 int tri[3][3][3];
 int i, j, k, x;
 
 x = 1;
 for(i=0; i<3; i++)
    for(j=0; j<3; j++)
	   for(k=0; k<3; k++)
	   {
	   	tri[i][j][k] = x;
		x++;
		printf("%d ", tri[i][j][k]);
	   }
	   
 return 0;
}
Úkol k textu

Zadání 11)

Napište program, který přebírá dva argumenty z příkazového řádku a zobrazte jejich součet.
cvi/sum2args.c
Řešení
/******************************
*	sum2args.c
*	16.4.2002
******************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
 if(argc != 3)
 {
  printf("Musite zadat dve cisla!");
  exit(1);
 }
 printf("%f", atof(argv[1]) + atof(argv[2]));
 
 return 0;
}  

A.9. Cvičení z kapitoly 10

Úkol k textu

Zadání 1)

Napište program, který vypíše obsah textového souboru, zadaného jako argument příkazové řádky, na obrazovku.
cvi/file2prn.c
Řešení
/******************************
*	file2prn.c
*	16.4.2002
******************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
 char ch;
 FILE *soubor;

 /* kontrola argumentu prikazoveho radku */
 if(argc != 2)
 {
  printf("Chyba je nutne zadat jmeno souboru");
  exit(1);
 }

 /* otevreni souboru pro cteni */
 if((soubor = fopen(argv[1], "r")) == NULL)
 {
  printf("Soubor nelze otevrit\n");
  exit(1);
 }

 while((ch=fgetc(soubor)) != EOF)
	 putchar(ch);


 fclose(soubor);

 return 0;
}
Úkol k textu

Zadání 2)

Napište program, který kopíruje textový soubor. Jméno zdrojového a cílového souboru se zadává na příkazovém řádku. Pro kopírování souborů použijte funkce fgets() a fputs(). Proveďte úplnou kontrolu chyb.
cvi/filecopy.c
Řešení
/******************************
*	filecopy.c
*	16.4.2002
******************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
 char str[128];
 FILE *zdroj, *cil;

 /* kontrola argumentu prikazoveho radku */
 if(argc < 3)
 {
  printf("Pouziti: cvi10_2 <zdroj> <cil>\n");
  exit(1);
 }

 /* otevreni zdrojoveho souboru */
 if((zdroj = fopen(argv[1], "r")) == NULL)
 {
  printf("Zdrojovy soubor nelze otevrit.\n");
  exit(1);
 }

 /* otevreni ciloveho souboru */
 if((cil = fopen(argv[2], "w")) == NULL)
 {
  printf("Cilovy soubor nelze otevrit.\n");
  exit(1);
 }

 while(!feof(zdroj))
 {
  fgets(str, 127, zdroj);
  if(ferror(zdroj))
  {
	printf("Chyba pri cteni.\n");
	break;
  }
  if(!feof(zdroj))
	fputs(str, cil);
  if(ferror(cil))
  {
	printf("Chyba pri zapisu.\n");
	break;
  }
 }

 if(fclose(zdroj) == EOF)
 {
  printf("Chyba pri zavirani zdrojoveho souboru.\n");
  exit(1);
 }

 if(fclose(cil) == EOF)
 {
  printf("Chyba pri zavirani ciloveho souboru.\n");
  exit(1);
 }

 return 0;
}
Úkol k textu

Zadání 3)

Napište program, který umožňuje uživateli zadat libovolný počet hodnot double (max 32 767) a zapsat je do souboru tak, jak jsou zadávány. Tento soubor pojmenujte VALUES. Počet zadaných hodnot zapište do souboru COUNT.
cvi/double.c
Řešení
/******************************
*	double.c
*	16.4.2002
******************************/

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
 FILE *soubor1, *soubor2;
 double d;
 int i;

 if((soubor1 = fopen("values", "wb")) == NULL)
 {
  printf("Nelze otevrit soubor.\n");
  exit(1);
 }

 if((soubor2 = fopen("count", "wb")) == NULL)
 {
  printf("Nelze otevrit soubor.\n");
  exit(1);
 }

 d = 1.0
 for(i=0; d!=0.0 && i<32767; i++)
 {
  printf("Zadejte cislo (0 = konec): ");
  scanf("%lf", &d);
  fwrite(&d, sizeof d, 1, soubor1);
 }

 fwrite(&i, sizeof i, 1, soubor2);

 fclose(soubor1);
 fclose(soubor2);

 return 0;
}
Úkol k textu

Zadání 4)

Napište program, který používá soubory ze zadání 3). Program nejprve přečte ze souboru COUNT počet prvků v souboru VALUES. Poté čte a vypisuje hodnoty ze souboru VALUES.
cvi/readwrit.c
Řešení
/******************************
*	readwrit.c
*	16.4.2002
******************************/

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
 FILE *soubor1, *soubor2;
 double d;
 int i;

 if((soubor1 = fopen("values", "rb")) == NULL)
 {
  printf("Nelze otevrit soubor.\n");
  exit(1);
 }

 if((soubor2 = fopen("count", "rb")) == NULL)
 {
  printf("Nelze otevrit soubor.\n");
  exit(1);
 }

 fread(&i, sizeof i, 1, soubor2);

 for(; i>0; i--)
 {
  fread(&d, sizeof d, 1, soubor1);
  printf("%f\n",d);
 }

 fclose(soubor1);
 fclose(soubor2);

 return 0;

}
Úkol k textu

Zadání 5)

Napište program, který vyhledává v souboru zadaném jako argument příkazového řádku určitou celočíselnou hodnotu zadanou také jako argument příkazového řádku. Je-li hodnota nalezena, nechejte program vypsat její bytovou pozici od začátku souboru.
cvi/search.c
Řešení
/******************************
*	search.c
*	16.4.2002
******************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
 unsigned char ch, val;
 FILE *soubor;

 /* kontrola argumentu prikazoveho radku */
 if(argc < 3)
 {
  printf("Pouziti: cvi10_5 <soubor> <hodnota>\n");
  exit(1);
 }

 if((soubor = fopen(argv[1], "rb")) == NULL)
 {
  printf("Soubor nelze otevrit.\n");
  exit(1);
 }

 val = atoi(argv[2]);

 while(!feof(soubor))
 {
  ch = fgetc(soubor);
  if(ch == val)
	printf("Hodnota nalezena na %ld\n", ftell(soubor));
 }

 fclose(soubor);

 return 0;
}
Úkol k textu

Zadání 6)

Napište program, který spočítá počet bytů v souboru (textovém nebo binárním) a zobrazí výsledek. Jméno souboru zadá uživatel jako argument příkazové řádky.
cvi/b_infile.c
Řešení
/******************************
*	b_infile.c
*	16.4.2002
******************************/

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
 FILE *soubor;
 unsigned velikost;

 if(argc!=2)
 {
  printf("Chyba je nutne zadat jmeno souboru.\n");
  exit(1);
 }

 if((soubor = fopen(argv[1], "rb")) == NULL)
 {
  printf("Soubor nelze otevrit.\n");
  exit(1);
 }

 velikost = 0;
 while(!feof(soubor))
 {
  fgetc(soubor);
  if(ferror(soubor))
  {
	printf("Chyba souboru.\n");
	exit(1);
  }
  velikost++;
 }

 printf("Velikost souboru je %u bytu.",velikost-1);
 fclose(soubor);

 return 0;
}

A.10. Cvičení z kapitoly 11

Úkol k textu

Zadání 1)

Ukažte jak udělat u UL nové jméno pro unsigned long. Napište krátký program, který deklaruje proměnnou pomocí UL, přiřadí jí hodnotu a vypíše hodnotu proměnné na obrazovku.
cvi/ul.c
Řešení
/******************************
*	ul.c
*	16.4.2002
******************************/

#include <stdio.h>

typedef unsigned long UL;

int main(void)
{
 UL cislo;
 
 cislo = 123;
 printf("%lu", cislo);
 
 return 0;
}
Úkol k textu

Zadání 2)

Co je špatně na tomto zápisu?
typedef balance float;
Řešení
Řešení
Příkaz typedef má nesprávné pořadí argumentů. Správný formát typedef je:
typedef staré-jméno nové-jméno;
Úkol k textu

Zadání 3)

Vytvořte výčtový typ obsahující dny v týdnu.
Řešení
Řešení
enum {pondeli, utery, streda, ctvrtek, patek, sobota, nedele} dny_tydne;
Úkol k textu

Zadání 4)

Je tento úsek programu správný? Pokud ne, proč?
enum auta {Ford, Chrysler, GM} vyrobce;

vyrobce = GM;
printf("Auto vyrobil: %s",vyrobce);
Řešení
Řešení
Ne, protože výčtovou konstantu nelze vypisovat jako řetězec.
Úkol k textu

Zadání 5)

Co je špatně na tomto kousku programu?
stuct 
{
 int i;
 long l;
 char str[80];
} s;
.
.
.
i = 10;
.
Řešení
Řešení
Proměnná i je prvkem struktury s. Proto ji nelze použít samotnou. Musí být zpřístupněna pomocí s a tečkového operátoru takto:
s.i = 10;
Úkol k textu

Zadání 6)

Co je struktura a co je unie?
Řešení
Řešení
Struktura je pojmenovaná skupina proměnných, které spolu nějak souvisejí. Unie definuje paměťovou oblast, která je sdílena dvěmi nebo více proměnnými různých typů.
Úkol k textu

Zadání 7)

Co je špatně na tomto úseku programu?
struct
{
 int a;
 char b;
 float c;
} myvar, *p;

p = &myvar;
p.a = 10;
Řešení
Řešení
Jelikož je p ukazatel na strukturu, musíte pro odkaz na prvek použít šipkový a ne tečkový operátor.

A.11. Cvičení z kapitoly 12

Úkol k textu

Zadání 1)

Napište program, který oznámí, kolik paměti je pro váš program přibližně k dispozici. (Rada: alokujte malé kousky paměti do té doby, dokud požadavek na alokaci neselže)
cvi/memory.c
Řešení
/******************************
*	memory.c
*	16.4.2002
******************************/

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
 char *p;
 long l = 0;
 
 do
 {
  p = malloc(1000);
  if(p) l+=1000;
 }
 while(p);
 
 printf("Priblizna hodnota volne pameti je: %ld bytu", l);
 
 return 0;
}
Úkol k textu

Zadání 2)

Co je špatně na této části programu?
char *p;

*p = malloc(10);

gets(p);
Řešení
Řešení
Příkaz
*p = malloc(10);
By měl správně být
p = malloc(10);
Chybí také kontrola, zda je hodnota vrácená funkcí malloc() platný ukazatel.
Úkol k textu

Zadání 3)

Napište program, který dynamicky alokuje paměť pro jedno číslo double. Přiřaďte tomuto číslu hodnotu 99.01, vypište je a paměť uvolněte.
cvi/dyn_aloc.c
Řešení
/******************************
*	dyn_aloc.c
*	16.4.2002
******************************/

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
 double *p;
 
 p = malloc(sizeof(double));
 if(!p)
 {
  printf("Chyba pri alokaci pameti");
  exit(1);
 }
 
 *p = 99.01;
 printf("%f", *p);
 free(p);
 
 return 0;
}