программы-шутки/головоломки (C/C++)
просто тесты на знание языка C/C++. Какие-то были взяты из книг, другие из собственной практики.
Хотелось бы поделиться некоторыми и попросить других участников форума прислать свои.
Для упрощения кода можно считать, что все необходимые заголовочные файлы подключены.
Вот некоторые из моих:
1. Что будет выведено на экран?
std::cout << b;
2.Чему равны переменные a и b после выполнения следующего кода:
int b = 2;
b = a+++1;
3.Чему равна вложенная переменная x?
{
int x = x;
}
4. Чему равны значения N::x и N::y?
namespace N {
enum { x = x+1, y = x };
}
5. Корректен ли код?
{
int x[x];
}
6. Корректен ли код?
X<T*> p;
};
...
X<int> x;
7. Корректен ли код? Если да, то что будет выведено на экран?
struct S {};
void f(void (*)(S)) { std::cout << "N1::f"; }
}
namespace N2 {
void f(void (*)(N1::S)) { std::cout << "N2::f"; }
void g(N1::S)
{
f(g);
}
}
...
N2::g(N1::S());
8.Что будет выведено на экран?
public:
A() { std::cout << "default" << std::endl; }
A(long) { std::cout << "long" << std::endl; }
explicit A(int) { std::cout << "int" << std::endl; }
A(const A&) { std::cout << "copy" << std::endl; }
A &operator=(const A&) { std::cout << "operator=" << std::endl; return *this; }
};
...
const int i = 0;
A a1();
A a2 = i;
A a3(i);
A a4 = A(i);
A a5 = (A) i;
A a6 = static_cast<A>(i);
вторая тоже понятно.
вот третье - вот я не угадал.
int b = 2;
b = a+++1;
a=2,b=3
{
int x = x;
}
x=<неизвестно что>,ибо
Мальвина дала Буратино 3 яблока,потом забрала назад 1
Впорос:Сколько яблок осталось у Буратино?
Ответ:ХЗ.Никто не знает сколько у него яблок было до того
Мораль:ВСЕГДА инициализируйте переменные
Прошу поправить меня,если неправильно(конечно,неправильно!Я ж вообще не знаю Си…)
Я надеюсь вы пробовали ее запускать? Прикол состоит не во вложенных выражениях <A>?<B>:<C>, а в комментарии
А 3-я и 4-я подобраны на одну тему - понятие точки определения.
2@pixo $oft:
1. a=2,b=2.
2. верно, но здесь опять таки фокус в точке определения. Если теоретически допустить, что она была бы за равенством, то было бы значение 1...
{
int x = x;
}
я сам не врубился, откуда там 1 получится в vcl приложении и... вроде 255 или 256, когда выполняешь этот код в консоли...
при компиляции и выводе получилось 0, что равнозначно false. тупо..
что за компилятор?
Видимо триграфы он не поддерживает, а следовательно не соответствует стандарту ISO/IEC 9899...
Если использовать "стандартный" компилятор, то вывода не будет никакого
я же не говорил, что будет 1, а только сделал гипотетическое допущение. Будет мусорное значение, зависящее от реализации компилятора. Не исключено даже, что это может быть и 0
А вот решение:
int main() {
const char *p_str;
printf(p_str,10,10,10,34,p_str="#include <stdio.h>%cint main() {%c const char *p_str;%c printf(p_str,10,10,10,34,p_str=%c%s%c,34,10);%c}",34,10);
}
Только для наглядности нужно расширить область вывода консоли)
Чему равны переменные a,b,c после выполнения следующего кода:
int b = 1;
int c = a+++b++;
норм. правда с небольшими опечатками.. :D
k = k++;
#define _ 0xF<00? --F<00||--F-OO--:-F<00||--F-OO--;
int F=00,OO=00;
main()
{
F_OO();printf("%1.3f\n",4.*-F/OO/OO);
}
F_OO()
{
_-_-_-_
_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_
_-_-_-_
}
Ну видимо обсуждать, предлагать свои, не очевидные или не тривиальные куски кода на C++, коих может быть на самом деле довольно много.
k = k++;
Любое. Ну что за банальности. =)
Ну это уже С а не С++ даже. Не мне в уме что то считать лень - подожду ответа. :D
Любое. Ну что за банальности. =)
Причем, даже не любое значение, а вообще непредсказуемый результат, вплоть до конца Света.
[/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]class[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] X {
[/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]public[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]:
X() { X<T *> t; }
};
X<[/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]int[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]> x;
[/SIZE]
Все компиляторы которые у меня есть уходят далеко и надолго. Только gcc и vc6.0 выводят что-то на консоль
Боюсь, что баян...Пример на неправильное проектирование предикатов:
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]#include [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#a31515][SIZE=2][COLOR=#a31515]<vector>[/COLOR][/SIZE]
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]#include [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#a31515][SIZE=2][COLOR=#a31515]<algorithm>[/COLOR][/SIZE]
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]class [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]Selector[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] {[/SIZE]
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]public[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]:[/SIZE]
[SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001] Selector[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]([COLOR=#0000ff]int [/COLOR][/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]selection[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2])[/SIZE]
[SIZE=2] : [/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]selection_[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]([/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]selection[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]),[/SIZE]
[SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001] count_[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2](0)[/SIZE]
[SIZE=2] {[/SIZE]
[SIZE=2] }[/SIZE]
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff] bool [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]operator[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]()([SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]int[/COLOR][/SIZE][/COLOR][/SIZE][/SIZE][SIZE=2])[/SIZE]
[SIZE=2] {[/SIZE]
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff] return[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] ++[/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]count_[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] == [/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]selection_[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2];[/SIZE]
[SIZE=2] }[/SIZE]
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]private[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]:[/SIZE]
[SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff] int [/COLOR][/SIZE][/COLOR][/SIZE][/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]selection_[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2];[/SIZE]
[SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001] [COLOR=#0000ff]int [/COLOR][/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]count_[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2];[/SIZE]
[SIZE=2]};[/SIZE]
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]int [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]main[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]()[/SIZE]
[SIZE=2]{[/SIZE]
[SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]std[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]::[/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]vector[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]<[/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]int[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]> [/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]v[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2];[/SIZE]
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]for[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] ([/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]size_t [/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]ind[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] = 0; [/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]ind[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] < 10; ++[/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]ind[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2])[/SIZE]
[SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]v[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2].[/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]push_back[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]([/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]ind[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]);[/SIZE]
[SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]v[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2].[/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]erase[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]([/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]std[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]::[/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]remove_if[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]([/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]v[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2].[/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]begin[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2](), [/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]v[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2].[/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]end[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2](), [/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]Selector[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2](5)), [/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]v[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2].[/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]end[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]());[/SIZE]
[SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]std[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]::[/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]copy[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]([/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]v[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2].[/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]begin[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2](), [/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]v[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2].[/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]end[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2](), [/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]std[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]::[/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]ostream_iterator[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]<[/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]int[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]>([/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]std[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]::[/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]cout[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2], [/SIZE][SIZE=2][COLOR=#a31515][SIZE=2][COLOR=#a31515]" "[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]));[/SIZE]
[SIZE=2]}[/SIZE]
Собственно, что будет выведено на экран?
Думаю, проектирование предикатов ту не при чем.
IMHO, это некоторая корявость STL связанная с повсеместной передачей аргументов по значению.
мда... куда-то девятка делась. Хотя в следующем, измененном примере, она есть:
#include <iterator>
#include <vector>
#include <algorithm>
template < class ForwardIterator, class Predicate >
ForwardIterator my_remove_if ( ForwardIterator first, ForwardIterator last,
Predicate pred )
{
ForwardIterator result = first;
for ( ; first != last; ++first)
if (!pred(*first)) *result++ = *first;
return result;
}
class Selector
{
public:
Selector(int selection)
: selection_(selection),
count_(0)
{
}
bool operator()(int)
{
return ++count_ == selection_;
}
private:
int selection_;
int count_;
};
int main()
{
std::vector<int> v;
for (size_t ind = 0; ind < 10; ++ind)
v.push_back(ind);
v.erase(my_remove_if(v.begin(), v.end(), Selector(5)), v.end());
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
}
Функция взята отсюда:
http://www.cplusplus.com/reference/algorithm/remove_if/
> IMHO, это некоторая корявость STL связанная с повсеместной передачей аргументов по значению.
Ну если придерживаться стандарта, то предикаты рекомендуется проектировать таким образом, чтобы их результат не зависил от состояния объекта. В данном случае эта рекомендация нарушена, а стандарт не гарантирует того, что не будут создаваться и использоваться копий предиката.
Поэтому, не считаю, что кривость в STL. Нужно исправлять стандарт и накладывать дополнительные условия...
Поэтому, не считаю, что кривость в STL. Нужно исправлять стандарт и накладывать дополнительные условия...
Ну это как раз таки кривость STL (не конкретной реализации, а в ообщем).
Это же не специально придуманная для удобства фича, а как раз таки наоборот - неудобное ограничение вызванное др. особенностями STL (передачей по значению).
P.S. Кстати, где в стандарте рекомендации к предикатам? (нет стандарта под рукой)
Кстати, есть еще пример, который якобы обходит этот недостаток, но в студии он все равно не работает:
#include <vector>
#include <algorithm>
using namespace std;
class Generator {
public:
Generator()
: i_(0)
{
}
int operator()()
{
return i_++;
}
private:
int i_;
};
int main()
{
typedef vector<int>::iterator iterator_t;
vector<int> v1(10), v2(10);
Generator gen;
generate<iterator_t, Generator &>(v1.begin(), v1.end(), gen);
generate<iterator_t, Generator &>(v2.begin(), v2.end(), gen);
copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " "));
cout << endl;
copy(v2.begin(), v2.end(), ostream_iterator<int>(cout, " "));
}
Происходит это из-за неявного указания параметров шаблона в функции-обертке.
Это же не специально придуманная для удобства фича, а как раз таки наоборот - неудобное ограничение вызванное др. особенностями STL (передачей по значению).
P.S. Кстати, где в стандарте рекомендации к предикатам? (нет стандарта под рукой)
В самом стандарте рекомендации конечно нет, она так сказать из него вытекает.
А в примере с предикатом проблема не в передаче по значению, а в том, что создается копия предиката.
А в примере с предикатом проблема не в передаче по значению, а в том, что создается копия предиката.
Собственно копия предиката и создается при передаче его по значению. :)
Да, все так и происходит. Но "фатальное" копирование происходит не при передаче в remove_if, а внутри нее, при вызове find_if после которого состояние предиката не изменится.
void redir(T t)
{
++t;
}
template<typename T>
void inc(T t)
{
redir(t);
}
#include <iostream>
using std::cout;
int main()
{
int i = 0;
inc<int &>(i);
cout << i; // по-прежнему 0
}
Требуется не изменяя inc и redir заставить работать код так, как ожидалось.
умные ссылки рулят... Хотя за надежность не ручаюсь:
void redir(T t)
{
++t;
}
template<typename T>
void inc(T t)
{
redir(t);
}
#include <iostream>
using std::cout;
struct Ptr
{
int &p;
Ptr(int &pp):p(pp){}
void operator++()
{
++p;
}
};
int main()
{
int i = 0;
inc<Ptr>(Ptr(i));
cout << i; // по-прежнему 0?
}
Я только идею показал - потому без шаблонов. Как сделать без определения оператора пока не вижу.
Добавлено позже: если только извратиться типа:
void redir(T t)
{
++t;
}
template<typename T>
void inc(T t)
{
redir(t);
}
#include <iostream>
using std::cout;
template<typename T>
struct Ptr
{
T &p;
Ptr(T &pp):p(pp){}
};
template<typename T>
struct PtrInc: public Ptr<T>
{
PtrInc(T &pp): Ptr<T>(pp){}
void operator++()
{
++Ptr<T>::p;
}
};
int main()
{
int i = 0;
inc<PtrInc<int> >(PtrInc<int>(i));
cout << i; // по-прежнему 0
}
void redir(T t)
{
++t;
}
template<typename T>
void inc(T t)
{
redir(t);
}
#include <iostream>
using namespace std;
template<typename T>
class Ref
{
public:
Ref(int& ref) :_ref(ref) {}
operator T&() {
return _ref;
}
private:
T& _ref;
};
template<typename T>
Ref<T> Reff(T& ref) {
return ref;
}
int main()
{
int i = 0;
inc( Reff(i) );
cout << i << endl; // по-прежнему 0?
}
В функции redir и inc копируется обертка (объект класса Ref), к которой функция пытается применить операции, которые не определены в классе. Тогда происходит преобразование типа в ссылку типа T с помощью оператора operator T&(). С полученной ссылкой уже можно проводить операции типа инкремента, декремента и пр.
Функция Reff нужна для красоты. Можно обойтись без нее, воспользовавшись конструктором типа Ref<int>(i).
На счет нейминга - вылетело из головы, как будет ссылка по английски. Заменил на указатель.
template<typename T>
void redir(T & t)
{
++t;
}
template<typename T>
void inc(T & t)
{
redir(t);
}
void main()
{
int i=0;
inc(i);
cout << i << endl; // теперь i == 1
inc(i);
cout << i << endl; // а теперь i == 2
}
2Kogrom: да, все так. Но такой фокус работает только со встроенными типами.