Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Вот интересные задачки по С++


Автор: Nastya 9.10.2003, 10:49
Вот тут случайно наткнулась.
Ну, кто смог решить ?
http://v.psiola.ru/cpp/task.htm

Автор: Fantasist 10.10.2003, 19:30
Да.... Ну первая очень классическая, ее решений уже множество приводилось. Снова ее решать лень.

Во - второй знать различия С и С++. Не знаем.

Третья интересная, но довольно простая. Достадочно вспомнить, что число в степени двойки всегда имеет в одном из 1 битов еденицу, а во всех остальных нули. А число меньшее числа в степени 2 на один все старшие нули до бита степени двойки и все младшие - еденицы.

Вот четвертая! Это монстр. Я долго думал, и в конце пришел вот к такому решению:

Код

template <class T,int nm>
int sz(T arg[nm])
{
return nm;
}


Только оно не компилилось. Я понимаю, что нужно как-то так - компилятор знает размер массива на этапе компиляции и с помощью шаблона можно из него эту информацию вытянуть, но вот как это провернуть синтаксически я не как догнать не мог.

Потом полез в инет, и нашел:

Код

template <class T,int size>
int sz(T (&)[size])
{
  return size;
}


До такого я бы не додумался в ближайшие года два.

Автор: mike_prog 11.10.2003, 15:30
Вот вам еще задачки. Известны вершины треугольника (x1, y1), (x2, y2), (x3, y3). Внимание вопрос!
Цитата
Как определить, принадлежит ли точка (x, y) этому треугольнику.

Автор: maxim1000 11.10.2003, 17:09
Цитата
Как определить, принадлежит ли точка (x, y) этому треугольнику.

1. записать три уравнения прямых в виде ax+by+c=0
потом для каждой вершины проделать такую операцию:
подставить ее координаты в уравнение прямой через две остальные вершины
подставить значение указанной точки в то же уравнение
если знаки разные => точка за границей треугольника
если все три проверки прошли => точка внутри
2. посчитать площади треугольников
пусть вершины - A, B, C, а выбранная точка - D
D внутри ABC <=> S(ABC)=S(ABD)+S(ACD)+S(BCD)
S - площадь
3. пусть L - угол
D внутри ABC <=> L(ADC)+L(BDC)+L(ADB)=360
Цитата
Во - второй знать различия С и С++.

ну вот, например, одно: наличие bool
если немного поухитряться, можно прити к некоторым результатам:
Код
#include "stdio.h"
void func(bool)
{
 printf("%d",sizeof(bool));
};
void main()
{
 func(0);
};

тестировал я это в VC (++) 6.0
если сохранить файл с расширением c => выведет 4
если с расширением cpp => 1
конечно, если не менялись настройки компилятора в зависимости от расширений файлов

Автор: Dov 11.10.2003, 22:44
Цитата
template <class T,int size>
int sz(T (&)[size])
{
  return size;
}

error C2265: '<Unknown>' : reference to a zero-sized array is illegal
error C2266: '<Unknown>' : reference to a non-constant bounded array is illegal

ПОЧЕМУ confused.gif

Автор: setq 12.10.2003, 15:58
задача #2 <<Написать программу, которая, будучи откомпилированной компилятором языка "C", выводит на экран lang=C. А будучи откомпилированной компилятором языка "C++", выводит на экран lang=C++. При решении нельзя использовать макросы, и из операторов предкомпиляции можно использовать только #include. >>

я знаю как написать программу, которая будет работать правильно в 50% случаев :-))))))))))))))))

Автор: Fantasist 13.10.2003, 18:01
Цитата
error C2265: '<Unknown>' : reference to a zero-sized array is illegal
error C2266: '<Unknown>' : reference to a non-constant bounded array is illegal


Покажи как используешь.

Автор: Dov 13.10.2003, 20:57
Цитата(Fantasist @ 13.10.2003, 18:01)
Покажи как используешь.

Я просто в задаче заменил звёздочки на этот код.
А как нужно использовать?

Автор: Fantasist 13.10.2003, 23:38
Вообще-то да. У меня так компилится и выполняется:

Код
template <class T,int size>
int sz(T (&)[size])
{
 return size;
}

int main()
{
int x[5] = {1,2,3,4,5};
char y[] = "123456789";
std::cout << sz(x) << " " << sz(y);
return 0;
}


Некоторые компиляторы плохо шаблоны обрабатывают.

Автор: Dov 14.10.2003, 01:05
2Fantasist: Вот мой срр-файл:
Код
#include <iostream>
using namespace std;

template <class T,int size>
int sz(T (&)[size])
{
   return size;
}

int main()
{
   int x[5] = {1,2,3,4,5};
   char y[] = "123456789";

   cout << sz(x) << " " << sz(y);

   return 0;
}


А вот список ошибок:
--------------------Configuration: T1 - Win32 Debug--------------------
Compiling...

error C2265: '<Unknown>' : reference to a zero-sized array is illegal
error C2266: '<Unknown>' : reference to a non-constant bounded array is illegal
error C2784: 'int __cdecl sz(T (&)[1])' : could not deduce template argument for ' (&)[1]' from 'int [5]'
error C2784: 'int __cdecl sz(T (&)[1])' : could not deduce template argument for ' (&)[1]' from 'char [10]'
---------------------------------------------------------------------------------
VC++ 6.0
Что это может быть?

Автор: gray_k 14.10.2003, 08:34
Цитата
template <class T,int size>
int sz(T (&)[size])
{
  return size;
}

А я по причине собственной тупости так и не понял, почему это работает.
Понял только, что этот код подразумевает статическое расположение переменных относительно друг-друга.

Автор: Fantasist 14.10.2003, 19:17
Цитата
VC++ 6.0
Что это может быть?


Это не может быть, а есть - слабость VC60. VC70 это компилит.


Цитата
А я по причине собственной тупости так и не понял, почему это работает.


В этой шаблонной функции ты указываешь, что у тебя параметром идет ссылка на массив из элементов T размером size (имя формального параметра просто опущено, так как он нам не нужен. Можно написать и так:
Код

template <class T,int size>
int sz(T (&array)[size])
{
 return size;
}

cмысл от этого не измениться.) Так как и size и T параметры шаблона, то для функции компилятор может автоматически вывести эти параметры. То есть:

int x[5] = {1,2,3,4,5};
char y[] = "123456789";

sz(x) - здесь x имеет тип int[5] и компилятор делает инстасирования функции где T=int, size=5.
sz(y) - здесь char[10] - T=char, size=10


Почему обязательно объявлять ссылку? Почему нельзя сделать просто:
Код

template <class T,int size>
int sz(T array[size])
{
 return size;
}



Когда мы объявляем функцию: void fn(char array[10]), то для компилятора переменная array имеет тип char[], а не char[10]. Так как в функцию передается только указатель, то для компилятора не имеет значения какого размера ты объявляешь массив в формальном аргументе, поэтому для него этого числа 10 не существует. То есть вот так вполне легально:
Код

void fn(int arr[3])
{...}

{
  int x[5] = {1,2,3,4,5};
  fn(x);
}



Следовательно, в выше приведенном объявлении функции sz параметр функции имеет тип T[]. Параметр шаблона size игнорируется в этом аргументе, потому когда приходит пора инстанцировать функцию компилятор не может вывести этот параметр из фактического типа аргумента, так как для него нет разницы между char[10] и, допустим, char[3].
Когда же ты передаешь ссылку, то это число имеет значение. То есть:
Код

void fn(int (&arr)[3])
{...}
{
  int x[5] = {1,2,3,4,5};
  int y[3] = {1,2,3};

  fn(x);  //error! Incompatible types int[5] и int(&)[3]
  fn(y);  //OK

}


Значит в случае:

Код

template <class T,int size>
int sz(T (&array)[size])
{
 return size;
}


size является полноценным аргументом типа, и компилято выводит его из фактического параметра.



Автор: Nastya 14.10.2003, 20:45
Цитата
Это не может быть, а есть - слабость VC60. VC70 это компилит.


Красивое решение, но мне кажеться задачи были разработанны так, что бы не зависить от компилятора.
Есть другие варианты?

Автор: Fantasist 14.10.2003, 21:56
Цитата
Красивое решение, но мне кажеться задачи были разработанны так, что бы не зависить от компилятора.


Это решение полностью соответсвует стандарту. То что VC60 его не компилирует - это проблема VC60. Задача, как мне кажется, была созданна именно в расчете на страндартный С++, а не возможные проблемы компилятора.

Eще решение. Идею услышал - реализация моя:


template <class T>
int sz(T &)
{
struct szarr
{
T a;
char flg;
};

szarr arr;
return ((int)(&arr.flg)-(int)(&arr))/((int)(&arr.a[1])-(int)(&arr.a[0]));
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)