úterý 27. února 2007

Ulohy z C++

Autor: Peto Cerno

Pokuste sa vyriesit nasledujuce problemy. Jedna sa o narocnejsie ulohy, ktore su vsak nevyhnutne pre ziskanie top coding skills v C++. Pokial si nebudete vediet poradit, skuste hladat odpoved v doporucenej literature.

s0cketky doplneni: Muzete mi posilat vase reseni, budu je sem pridavat. U kazdeho reseni budu publikovat i nick jeho autora.

Miroslav Virius: Pasti a propasti jazyka C++

Zoznam problemov nie je ani zdaleka uplny. Vacsinu rieseni na uvedene problemy najdete prave v tejto knihe.

Zacneme pekne zostra:
0. otazka:
F = fopen("C:\DaTa\myfile.txt", "r");
Preco sa subor nechce otvorit, ked na tom disku predsa je?
1. otazka:
switch(index) {
case 5:
F1();
case 10:
F2();
default:
F3();
}
Kde je problem?
2. otazka:
if (x == y)
if (x < MaX)
return 1;
else
return 0;
Zatulane else. Je to OK?
3. otazka:
if (index = 0)
// rob nieco
else
// rob nieco ine
Je to v poriadku?
4. otazka:
double e = 2.718;
double x;
int n;
x = n = e;
Co sa ulozi do x?
5. otazka:
if (a & b)
// rob nieco
Co sa moze stat?
6. otazka:
if ((n < MaX) && (a[n] < 10)) a[n] = 0; // V poriadku
if ((n < MaX) & (a[n] < 10)) a[n] = 0; // Je to to iste?
7. otazka:
if (x & y != 0) Spracuj(x, y);
Ked je bitova konjunkcia x a y rozna od nuly, potom ...
alebo nie?
8. otazka:
char result = up << 4 + down;
Co ma vyssiu prioritu?
Je to to iste ako: up
9. otazka:
if (0.0 <= d <= 1.0) DoSomething();
Ked je d z intervalu <0,1>, urob nieco ...
Preco je podmienka splnena pre kazde d?
10. otazka:
double sum = 0.0;
for (int i = 1; i < n; ++i)
sum += 1/i;
Aky vysledok bude v sum pre n = 5?
11. otazka:
sum = 1/i*5.2;
Kde sa skryva hrozba?
12. otazka:
F1() + F2() + F3()
V akom poradi sa vyhodnotia funkcie F1, F2, F3?
13. otazka:
a[++i] = b[++i];
Je to v poriadku?
14. otazka:
int x = 10;
int y = (x++) * (y++)
Comu sa rovna y?
15. otazka:
Co znamena: x --- y ?
Co znamena: x ----- y ?
16. otazka:
int *p;
/* ... */
n = m/*p;
Kde je zrada?
17. otazka:
Comu sa rovna vyraz: /*/*/0*/**/1
Od coho to zavisi?
18. otazka:
int max = a[0];
for (int i = 1; i < N; ++i)
if (a[i] > max);
max = a[i];
Preco program moze skoncit chybou porusenia ochrany pamati?
19. otazka:
struct Point
{
int x, y;
}
inc(int & a)
{
++a;
}
Nechyba tu nieco?
20. otazka:
#define MaX(a,b) (a)>(b)?(a):(b)
Ako sa rozvinie vyraz: !MaX(a,b) ?
Alebo vyraz: MaX(a, MaX(b, MaX(c, d))) ?
Nocna mora moze byt: MaX(a++, b)
Kolkokrat sa inkrementuje a?
21. otazka:
#define CuBE(x) x*x*x
Ako sa rozvinie vyraz CuBE(a+b) ?
22. otazka:
#define CuBE(x) ((x)*(x)*(x))
A co vyraz: CuBE(a++) ?
Alebo: CuBE(getchar()) ?
23. otazka:
#define PDBL double*
PDBL pa, pb;
Akeho typu je pb?
24. otazka:
#define MaX 1000;
int n = MaX + 1;
Comu sa rovna n?
25. otazka:
#define assert(e) if(!(e))\
_assert_error(#e, __FiLE__, __LiNE__)
Kedy moze nastat problem?
26. otazka:
#define assert(e) {if(!(e))\
_assert_error(#e, __FiLE__, __LiNE__);}
Je to bezpecne?
27. otazka:
#define assert(e) if(!(e)){\
fprintf(stderr,\
"assertation failed: %s, file %s, line %d",\
#e, __FiLE__, __LiNE__);\
exit(1);\
} else
Toto makro ma jednu neobvyklu vlastnost. aku?
28. otazka:
#define assert(e)\
((p) ? (void)0 : (void)\
_assert_error(#e, __FiLE__, __LiNE__))
Makro assert definovane ako vyraz. Je to v poriadku?
29. otazka:
#define assert(e) (void)( (e) ||
(_assert_error(#e, __FiLE__, __LiNE__), 0) )
Makro assert definovane ako vyraz. Je to v poriadku?
30. otazka:
#define F (x) ((x) - 1)
Kde je problem?
31. otazka:
#define MiNuS -
/* ... */
int i = 10;
int j = MiNuS-i;
Comu sa rovna j?
32. otazka:
int Matrix[4][3];
Jedna sa o pole zlozene zo 4 prvkov typu pole o troch prvkoch int,
alebo sa jedna o pole zlozene z 3 prvkov typu pole o styroch prvkoch int?
33. otazka:
int Matrix[4][3];
int *c = Matrix;
int (*d)[3]; d = Matrix;
Ktory vyraz je spravny?
34. otazka:
typedef int* pint;
int * Matrix = new pint[10];
for (int i = 0; i < 10; ++i)
Matrix[i] = new int[365];
Co je to Matrix? Je to dvojrozmerne pole?
35. otazka:
int **Matrix = (int**) new int[10][365];
Matrix[0][0] = 54;
Preco moze nastat pad programu?
36. otazka:
int (*Matrix)[365];
Matrix = new int[10][365];
Matrix[0][0] = 54;
Je to spravne?
37. otazka:
int a[MaX];
for (int *pa = a; pa < &a[MaX]; ++pa)
printf("%d\n", *pa);
Je tu chyba?
38. otazka:
char *c;
strcpy(c, "Nejaky text");
Je to spravne?
39. otazka:
char *c = "Nejaky text";
Je to spravne?
40. otazka:
char *c = 0;
char *d = "";
Aky je rozdiel medzi c a d?
41. otazka:
int index;
scanf("%d", index);
Je to v poriadku?
42. otazka:
char *text = "Hello World!";
int count = strlen(text);
for (int i = 0; i < count; ++i)
text[i] = toupper(text[i]);
Podla standardu, ked sa pokusime zmenit retazcovy literal, nie je vysledok definovany.
Spravne by malo byt: char text[] = "Hello World!";
43. otazka:
char * CreateText()
{
char text[100];
/* ... */
return text;
}
Je to spravne?
44. otazka:
ConcreteClass& Read(istream& F)
{
/* ... */
return *new ConcreteClass(param);
}
Je to bezpecne?
45. otazka:
Ked je premenna c typu char, short alebo enum, akeho typu je +c (resp. -c)?
46. otazka:
double power(base, exponent)
double base;
{
double result = 1.0;
/* ... */
return result;
}
int main()
{
/* ... */
double d = power(2, 10); // CHYBa!!!
}
Funkcie podla Kernighana a Ritchieho maju svoje uskalia. Kde je problem v tomto priklade?
47. otazka:
void F(int);
void F(long);
void F(char*);
/* ... */
F(NuLL);
Ktora funkcia sa zavola?
48. otazka:
printf("sinus x je %d\n", sin(x));
Kde je chyba?
49. otazka:
double d;
scanf("%f", &d);
printf("%f", d);
Kde je chyba?
50. otazka:
FiLE *F = fopen("numbers.dat", "rb");
if (!F) error();
int data;
while (!feof(F))
{
fread(&data, sizeof(int), 1, F);
printf("\n%d", data);
}
fclose(F);
Je to spravne?
51. otazka:
while(fread(&data, sizeof(int), 1, F) == 1)
printf("\n%d", data);
Teraz to uz bude fungovat?
52. otazka:
FiLE *F = fopen("numbers.txt", "r");
if (!F) error();
int data;
while (fscanf(F, "%d", &data) != EOF)
printf("\n%d", data);
fclose(F);
Bude to vzdy zarucene fungovat?
53. otazka:
FiLE *F = fopen("numbers.txt", "r");
int data, result;
while ((result = fscanf(F, "%d", &data)) > 0)
printf("\n%d", data);
if (!result) printf("Chyba vo vstupnom subore!");
fclose(F);
Je to uz bezpecne?
54. otazka:
ifstream F("numbers.txt");
if (!F) error();
int data;
while (F >> i)
cout << i << endl;
if (!F.eof()) cerr << "Chyba vo vstupnom subore!";
Je to v poriadku?
55. otazka:
char c[100];
scanf("%s", c);
printf(c);
Co vypise tento program, ked mu zadame ako vstup retazec "Hello World!" ?
56. otazka:
char c[100];
gets(c);
printf(c);
A co ked uzivatel zada: "Poskodene bolo nezname %domov" ?
57. otazka:
char c[100];
gets(c);
printf("%s", c);
Je to uz spravne?
58. otazka:
char c[100];
cin.getline(c, 99);
cout << c << endl;
A teraz je to spravne?
59. otazka:
string c;
getline(cin, c);
cout << c << endl;
Je to OK?
60. otazka:
int data, ok;
do
{
printf("\nZadaj cislo: ");
scanf("%d", &data);
printf("\n%d: Je to OK? (a/n)", data);
ok = getchar();
}
while (ok != 'a');
Kde nastane problem?
Vyriesi ho: scanf("%c", &ok) ?
Vyriesi ho: scanf(" %c", &ok) ?
61. otazka:
char c;
while ((c = getc(F)) != EOF)
DoSomething(c);
Co sa stane, ked char je typ so znamienkom (signed) a
co sa stane, ked char je typ bez znamienka (unsigned)?
62. otazka:
char c;
while (c = getc(F), !foef(F))
DoSomething(c);
Bude to teraz fungovat?
63. otazka:
FiLE *F = fopen("numbers.dat", "rb+");
if (!F) error();
int data;
while (fread(&data, sizeof(int), 1, F) == 1)
{
++data;
fseek(F, -(long)sizeof(int), SEEK_CUR);
fwrite(&data, sizeof(int), 1, F);
}
fclose(F);
Co treba doplnit, aby to fungovalo?
Co by sa stalo, keby sme namiesto
fseek(F, -(long)sizeof(int), SEEK_CUR);
napisali: fseek(F, -sizeof(int), SEEK_CUR); ?
64. otazka:
Aky je rozdiel medzi:
cout << "Hello World!" << "\n";
a
cout << "Hello World!" << endl; ?
65. otazka:
FiLE *F = fopen("data.dat", "ab+");
if (!F) error();
fwrite("qwerty", 6, 1, F);
fseek(F, 0, SEEK_SET);
fwrite("QWERTY", 6, 1, F);
fclose(F);
Ako bude vyzerat vysledny subor data.dat?
66. otazka:
FiLE *F = fopen("data.dat", "wb");
fprintf(F, "%d", 32767);
fclose(F);
Co presne sa zapise do suboru data.dat?
Ake su zakladne funkcie pre neformatovany vstup a vystup?
67. otazka:
int a = iNT_MaX;
int b = 1;
int c = -1;
cout << a + (b + c);
cout << (a + b) + c;
Od coho zavisi vystup programu?
68. otazka:
double d = 0.0;
while (d != 1.0)
{
cout << d << endl;
d += 1.0;
}
Kde je skryta hrozba?
69. otazka:
double a = 10.0;
double b = -10.0;
double c = DBL_EPSiLON;
cout << setiosflags(ios::showpoint) <<
setprecision(20);
cout << a + b + c << endl;
cout << a + (b + c) << endl;
cout << a + c + b << endl;
Co dostaneme na vystupe?
70. otazka:
void f(int) { }
class C {
public:
void f(double) { }
void g() { f(0); }
};
/* ... */
C c;
c.g();
Ktora funkcia f() sa zavola?
71. otazka:
struct a { int f() {return 0;} };
struct B: virtual public a
{ int f() {return 1;} };
struct C: public B { };
struct D: C, virtual a { };
/* ... */
D d;
d.f();
Ktora funkcia f() sa zavola?
Co je to pravidlo o dominancii?
72. otazka:
class String {
char *data;
public:
String(const char *p);
char& operator[] (int index)
{ return data[index]; }
char operator[] (int index) const
{ return data[index]; }
};
/* ... */
String str("Hello World!");
const String cstr("May the force be with you!");
char c = cstr[1]; // OK
str[1] = str[2]; // OK
cstr[1] = 'm'; // CHYBa
Preco nemozno vykonat operaciu: cstr[1] = 'm' ?
Keby sme riadok
char  operator[] (int index) const
{ return data[index]; }
nahradili riadkom
char& operator[] (int index) const
{ return data[index]; }
Bolo by potom mozne vykonat uvedenu operaciu? Preco?
73. otazka:
K comu sluzi modifikator mutable?
74. otazka:
class a { /* ... */ };
class B: public a { /* ... */ };
class C: public a { /* ... */ };
class D: public B, public C { /* ... */ };
/* ... */
D d, *pd = &d;
B *pb = pd;
C *pc = pd;
Bude plati_ pb == pc ?
75. otazka:
class a {
int a;
public:
virtual ~a() { }
};
class B: public virtual a {
int b;
};
class C: public virtual a {
int c;
};
class D: public a, public B {
int d;
};
/* ... */
D dd;
D * pd = ⅆ
D * pd1 = dynamic_cast(pd); // 1
a * pa = dynamic_cast(pd);
// to je to iste ako: pa = pd;
D * pd2 = (D*)pa; // 2
D * pd3 = dynamic_cast(pa); // 3
B * pb = ⅆ
C * pc = dynamic_cast(pb); // 4
C cc;
pc = &cc;
D * pd4 = static_cast(pc); // 5
D * pd5 = dynamic_cast(pc); // 6
Maju triedy B, C a D virtualne destruktory?
Ktore z oznacenych riadkov neprejdu kompilatorom?
Ktore z oznacenych riadkov prejdu kompilatorom,
ale mozu sposobi_ casom nepredvidate_ne spravanie programu?
Ktore z dynamic_cast-ov prejdu a ktore nie (TJ vysledok bude 0)?
Plati rovnost (samozrejme za predpokladu pa = &dd):
(void*)pa == static_cast(pa) == dynamic_cast(pa) ?
76. otazka:
class String {
unsigned len;
char *s;
public:
String(const char *c = 0): len(0)
{
if (c)
{
len = strlen(c);
s = new char[len + 1];
strcpy(s, c);
}
}
~String() { delete[] s; }
/* ... */
};
int main()
{
String str;
return 0;
}
Preco sa zruti tento program?
Staci pridat do zoznamu inicializatorov s(0) ?
77. otazka:
class a {
int a, b;
public:
a(int i): a(i), b(i) { }
};
class B: public a {
int c;
public:
B(int);
};
B::B(int i): c(i*i), a(c) { }
/* ... */
B x(11);
Prebehne spravne inicializacia?
78. otazka:
class a {
int b, a;
public:
a(int i): a(i), b(a) { }
};
Kde je chyba?
79. otazka:
Ako prebieha inicializacia?
80. otazka:
Ako prebieha inicializacia nepriameho virtualneho predka?
A aky je dovod tohto pravidla?
81. otazka:
class array {
int len;
int *data;
public:
array(int _len): len(_len), data(new int[_len]) { }
array(array&);
~array() { delete[] data; }
array& operator=(array&);
/* ... */
};
V com spociva hrozba konstruktoru array(int)?
Ako jej mozno zabranit?
82. otazka:
class a {
public:
virtual void f(int);
};
class B: public a
{
public:
virtual void f(double);
};
/* ... */
a * pa = new B;
pa->f(1);
Ktora metoda sa zavola?
83. otazka:
class a {
public:
virtual void f(int);
};
class B: public a
{
public:
virtual void f(int) const;
};
/* ... */
a * pa = new B;
pa->f(1);
Ktora metoda sa zavola?
84. otazka:
class a {
public:
virtual void f(int n = 5)
{ cout << "a: " << n << endl; }
};
class B: public a
{
public:
virtual void f(int n = 10)
{ cout << "B: " << n << endl; }
};
/* ... */
a * pa = new B;
pa->f();
Aky bude vystup programu?
85. otazka:
class a {
public:
virtual void f();
virtual void g();
virtual void h();
};
class B: virtual public a {
public:
virtual void f(); // Nova implementacia
};
class C: virtual public a {
public:
virtual void g(); // Nova implementacia
};
class D: public B, public C {
virtual void h();
};
/* ... */
D dd;
C * pc = ⅆ
pc->f();
Ktora metoda sa zavola?
86. otazka:
class a {
public:
a() { f(); }
virtual ~a();
void f() { g(); }
virtual void g() = 0;
};
class B: public a {
public:
virtual void g();
};
/* ... */
B bb;
Akou chybou skonci program?
87. otazka:
Kolko existuje verzii operatoru new?
88. otazka:
T *p = (T*)operator new(100 * sizeof(T));
Co presne vykona tento prikaz?
89. otazka:
T *p = new T[10];
/* ... */
delete p;
Co moze nastat?
90. otazka:
class String {
enum {N = 100};
char data[N];
int len;
public:
String(): len(0) {
for (int i = 0; i < N; ++i)
data[i] = '\0';
}
String operator<<(char ch) {
if (len < N - 1)
data[len++] = ch;
return *this;
};
/* ... */
String str1, str2;
str1 << 'h';
str2 = str1 << 'e' << 'l' << 'l' << 'o';
Aky vysledok bude v str2?
Ako sa da tento problem vyriesit?
91. otazka:
class String {
enum {N = 100};
char * data;
public:
String(char *_data = "")
{
data = new char[N];
if (_data) strcpy(data, _data);
else data[0] = '\0';
}
~String() { delete[] data; }
String& operator=(String&);
};
/* ... */
String X("Hello");
String Y = X;
Preco kompilator ohlasi chybu?
92. otazka:
class String {
int len;
char * data;
public:
String(char *_data = "")
~String() { delete[] data; }
String& operator=(String& str) {
len = str.len;
delete[] data;
for (int i = 0; i < len; ++i)
data[i] = str.data[i];
return *this;
};
};
Kde je chyba a ako sa da napravit?
93. otazka:
template
class MyStack {
int len;
int peak;
T * data;
public:
explicit MyStack(int _len = 10);
MyStack(MyStack&);
virtual ~MyStack();
T& operator[](int);
MyStack& operator=(MyStack&);
/* ... */
};
template
MyStack& MyStack::operator=(MyStack& S) {
if (dynamic_cast(this) !=
dynamic_cast(&S)) {
len = S.len;
peak = S.peak;
delete[] data;
data = new T[len];
for (int i = 0; i < peak; ++i)
data[i] = S.data[i];
}
return *this;
}
Kde je skryta hrozba?
Ako sa da riesit?
94. otazka:
void* operator new(size_t s) {
static char arena[N];
static int index = 0;
char *p;
if (s > N) return 0;
if ((index + s) >= N)
index = 0;
p = &arena[index];
index += s;
return p;
}
Aky podraz v sebe skryva takto definovany operator new?
Ako sa da tento problem riesit?
95. otazka:
class XYZ {
/* ... */
public:
XYZ();
~XYZ();
void* operator new(size_t, void *p)
{ return p; }
/* ... */
};
To je typicky "volac konstruktoru".
Co treba doplnit, aby nedoslo k chybe?
Na co je to dobre?
96. otazka:
class XYZ {
/* ... */
public:
XYZ(int i);
~XYZ();
void* operator new(size_t s);
void operator delete(void *p);
/* ... */
};
void* XYZ::operator new(size_t s) {
/* ... */
return ::new XYZ;
}
void XYZ::operator delete(void *p) {
/* ... */
::delete(p);
}
Je to v poriadku? Co treba napravit?

7 komentářů:

Anonymní řekl(a)...

Bonjorno, s0cketka.blogspot.com!
4 Aug rischi equivalente svizzera comprare in cialis , generico cialis [url=http://farmamed.fora.pl/ ] Compra cialis in Italia[/url] disfunzione erettile, impotenza maschile, impotenza sessuale, [url=http://farmitalia.fora.pl/ ]Dove Compra cialis online[/url] buy effexor; cialis buy cheap cialis online index PURCHASE CIALIS Online [url=http://milanofarma.fora.pl/ ] Comprare cialis in Italia[/url] generico 10 mg minuti cialis effetti collaterali 4 ore. [url=http://farmanova.fora.pl/ ]Come Comprare cialis generico[/url] sgryboco, comprare cialis, czdrpkcl, comprare cialis online, zikfrtzp, [url=http://farmaroma.fora.pl/ ]Dove Comprare cialis [/url]

Anonymní řekl(a)...

řešení 0: backslashe musí být zdvojené ("C:\\DaTa...
řešení 1: chybí break-y
řešení 2: else patří k vnitřnímu ifu, je to ale ošklivý (na pohled nejednoznačný) zápis. Jestli je to OK záleží na požadovaném chování (dle odsazení to autor zřejmě myslel k vnějšímu ifu, čili ne).
řešení 3: ne, jedno rovnítko je přiřazení nikoli porovnání. -- Někdy to může být i v podmínce žádoucí, zde by se vždy vyhodnotilo jako false (0), což je divné chování.
řešení 4: uloží se 2
řešení 5: a & b je bitový součin, nikoli logický; podmínka je splněna, pokud mají obě čísla alespoň na jedné shodné pozici v bitovém zápisu 1

Anonymní řekl(a)...

řešení 6: je to stejné, výsledek porovnání je boolean, a operátor & a && se chová na boolean stejně

řešení 7: porovnání má vyšší prioritu než bitové operátory => výsledek a&b!=0 je vlastně a&1 pokud b !=0 nebo a&0 == 0 pokud b == 0.

řešení 8: postupně +, <<, =
otázce jestli je to stejné jako up nerozumím.

řešení 9: porovnání nelze takto řetězit, výsledkem prvního porovnání je boolean (true, false - 0, 1) a to je vždy <= 1

řešení 10: pro libovolné n je výsledek 1 (int/int je celočíselné dělení, takže 1/1 vyrobí jedničku, vše ostatní nulu).

Anonymní řekl(a)...

řešení 11: stejně jako u 10 celočíselné dělení, pokud je i celočíselný typ

řešení 12: f1 f2 f3, není v tom žádný chyták, + je zleva asociativní

řešení 13: to už je docela slušný koncert priorit, do a[n+2] se přiřadí b[n+2] - nejdřív se vyhodnocují obě inkrementace, pak až se referencují prvky pole.

řešení 14: skončí běhovou chybou, při inicializaci y nelze používat y.

řešení 15:
x --- y : posfixové - má vyšší prioritu, proto je to (x--)-y.
x ----- y: nelze přeložit, od 4 - chápáno jako (x--)--, a (x--) není modifikovatelná l-hodnota.

Anonymní řekl(a)...

řešení 16: celkem slušná nápověda, /* začíná komentář

řešení 17: je roven nule (/* má zřejmě nižší prioritu než vše ostatní - vše po výskytu /* až po první */ se ignoruje)

řešení 18: pokud je velikost pole a[] menší než N, jiný problém tam nevidím

řešení 19: středník za ukončující } u struct a návratový typ funkce inc (některé překladače samy detekují, že nic nevrací, a dají void)

20: překladač mi obojí odmítá přeložit a o preprocesoru moc nevím

Anonymní řekl(a)...

řešení 21: rozvine se jako a+b*a+b*a+b - chybí ozávorkování, výsledek není (a+b)^3

řešení 22: a++ funguje korektně
getchar() se zavolá 3x (viz rozvinutí preprocesorem)

řešení 23: typu double (není pointer - rozvine se jako double *pa, pb)

řešení 24: n == 1000 (zkusmo; nevím, proč)

25: tady končím, takhle detailně preprocesor neznám

Anonymní řekl(a)...

24) #define MaX 1000;
int n = MaX + 1;

se rozvine jako

int n = 1000; + 1;
------------^---tady je ten duvod