Просмотр полной версии : [C/C++] ЗАДАНИЯ
По аналогии с темой (http://forum.antichat.ru/thread126194.html) Krist_ALL'a решил создать отдельный топик с заданиями по С/С++. Надеюсь что вы enjoy it ;)
Задание 1.
int a, sum=0; char buf[4096];
printf("Tell me your name:"); gets(buf);
for(a=0; a<100; a++) sum+=0;
//(с) мыщьх
Как оптимизировать программу с точки зрения использования ею оперативной памяти? И что в ней не так?
Верное решение (http://forum.antichat.ru/showpost.php?p=1345045&postcount=5)
Задание 2.
Мы создаем класс без конструкторов. Что сгенерирует компилятор дополнительно?
Мы создаем класс, в котором есть только конструктор без аргументов. Что сгенерирует компилятор дополнительно?
Мы создаем класс, в котором есть только конструктор копии. Что сгенерирует компилятор дополнительно?
Задание 3.
class SimpleClass {
private:
int a;
int b;
public:
SimpleClass(int x) : b(x), a(b) {}
void print() {
std::cout << "a=" << a << " b=" << b << std::endl;
}
};
int main() {
SimpleClass a(42);
a.print();
return 0;
}
Что здесь не так?
Верное решение (http://forum.antichat.ru/showpost.php?p=1346178&postcount=29)
Задание 4.
class A {
public:
virtual void Foo (int n = 10) {
cout << "A::Foo, n = " << n << endl;
}
};
class B : public A {
public:
virtual void Foo (int n = 20) {
cout << "B::Foo, n = " << n << endl;
}
};
int main() {
A * pa = new B ();
pa->Foo ();
return 0;
}
//(c) habrahabr//h1ppo
Что выведет программа и почему?
Верное решение (http://forum.antichat.ru/showpost.php?p=1345980&postcount=24)
Задание 5.
foo() {
char a;
char b;
char c;
char d[5];
}
(c) мыщьх
Сколько байт локальной памяти мы израсходовали? Почему? Как оптимизировать эту "оптимизированную"(здесь подсказка;)) программу?
Верное решение (http://forum.antichat.ru/showpost.php?p=1345457&postcount=8)
Задание 6.
void display(int in) {
// What im doing here????????/
cout << ++in;
}
void foo() {
int a=10;
display(a);
}
Что выведет программа?
Верное решение (http://forum.antichat.ru/showpost.php?p=1346176&postcount=28)
Задание 7. (by slesh)
struct _REC {
unsigned char data1;
unsigned short data2;
bool data3;
bool data4;
bool data5;
bool data6;
bool data7;
unsigned short data8;
} REC;
Как оптимизировать данную структуру чтобы она занимала в памяти 6 байта, то есть sizeof(REC) = 6
В таком виде структура занимает 12 байт.
При этом не был потерян функционал!!!
Верное решение (http://forum.antichat.ru/showpost.php?p=1345788&postcount=10)
Верное решение (http://forum.antichat.ru/showpost.php?p=1345981&postcount=25)
Задание 8. (by slesh)
Необходимо откомпилить консольную прожку. Я тестил на VC++ 2008
ПРИМЕЧАНИЯ:
1) в коде нельзя ничего удалять!!
2) нельзя подключать новые хидеры!!
#include "stdio.h"
void _stdcall Sleep(unsigned long dwMilliseconds);
int main(int argc, char* argv[]) {
printf("START PAUSE");
Sleep(2000);
printf("STOP PAUSE");
return 0;
}
ПОДСКАЗКА: решение требует дописания одной строки.
Верное решение (http://forum.antichat.ru/showpost.php?p=1345862&postcount=17)
Задание 9. (by slesh)
#include "stdio.h"
#include "windows.h"
int main(int argc, char* argv[]) {
printf("SRART\n");
__asm
{
hlt
}
return 0;
}
При выполнении появляется ошибка из-за того, что команда hlt является привилегированной и недоступной из пользовательского режима.
Необходимо обработать это исключение, выдать на экран сообщение об ошибке и завершить работу программы.
И Главное - решение не должно использовать конструкцию try except и должно иметь глобальные характер. т.е. даже если это исключение появится в отдельном потоке, то действия программы должны быть такими же.
P.S. Решение требует примерно 5 строчек кода.
Верное решение (http://forum.antichat.ru/showpost.php?p=1352055&postcount=77)
Задание 10.
Создать динамический двумерный массив размерностью N. Заполнить его значениями. Вывести значения массива на экран. Запрещается использовать символы '[' и ']'.
Верное решение (http://forum.antichat.ru/showpost.php?p=1351452&postcount=68)
Верное решение (http://forum.antichat.ru/showpost.php?p=1351598&postcount=71)
Задание 11.
Как можно выполнить эффективное побайтовое сравнение структур, не используя прагмы компилятора и группировку членов?
Верное решение (http://forum.antichat.ru/showpost.php?p=1348763&postcount=57)
Задание 12.
for (int k=0, int A=0; k < strlen(str); k++)
A+=str[k];
Оптимизировать код.
Верное решение (http://forum.antichat.ru/showpost.php?p=1348067&postcount=43)
Особое решение slesh'a (http://forum.antichat.ru/showpost.php?p=1348033&postcount=39) :)
Задание 13.
Что эффективней использовать и почему:
strcpy(str, "bytes "); strcat(str, very_long_string);
или
strcpy(str, "bytes: "); strcat(str, very_long_string);
?
Верное решение (http://forum.antichat.ru/showpost.php?p=1353540&postcount=85)
Задание 14.
Создать массив, начальный индекс которого есть произвольное число (например, 1, а не с 0).
Верное решение (http://forum.antichat.ru/showpost.php?p=1353102&postcount=83)
Задание 15.
const int x = 1; {
enum { x = x + 1, y, z = x };
std::cout << x << ' ' << y << ' ' << z << std::endl;
}
Что выведет программа и почему? Без компиляции, пожалуйста )
Верное решение (http://forum.antichat.ru/showpost.php?p=1348165&postcount=51)
Задание 16. (by desTiny)
Что будет в переменной после выполнения кода (не компилить!)
/*very very long not ever overflowable*/ int a = 5+765432l;
?
Верное решение (http://forum.antichat.ru/showpost.php?p=1358618&postcount=90)
Задание 17. (by fker)
Ввести число n, и заполнить двухмерный массив размерностью n числами от 1 до n*n по спирали.
Верное решение (http://forum.antichat.ru/showpost.php?p=1376678&postcount=103)
Задание 18.
Привести три эффективных варианта выхода из большого количества вложенных циклов без использования операторов break.
Верное решение (Part 1) (http://forum.antichat.ru/showpost.php?p=1376663&postcount=101) + Верное решение (Part 2) (http://forum.antichat.ru/showpost.php?p=1376923&postcount=115)
################################################## ###########################
Пока все ) Каждый может добавлять свои задания отдельным постом, я же по возможности буду их добавлять сюда.
Просьба к авторам задач: после того, как вашу задачу решили, напишите, что это верное решение.
Еще хочу добавить: если вам интересны интересные(оО) и нестандартные задачи по С/С++, вам понравится книги
Г. Саттер - Решение сложных задач C++
Г. Саттер - Новые сложные задачи C++
М.В. Мозговой - 85 нетривиальных проектов, решений и задач
задание одын
int sum=0; char buf[]="Tell me your name:";
puts(buf); fgets(buf, sizeof(buf), stdin);
??
Нет, имелось в виду несколько не это ) Присмотрись к циклу, к порядку появления переменных.
PS Переполнение здесь роли не играет.
nemaniak
21.06.2009, 21:22
может быть так?
int a, sum=0; char buf[4096];
printf("Tell me your name:"); gets(buf);
for(a=0; a<100; a++, sum++);
jawbreaker
21.06.2009, 21:37
В первой задаче для локальных переменных будет использовано слишком много стековой памяти (8 килобайт вместо 4). Бороться с этим можно если запихать данные в структурку
FireFenix
22.06.2009, 01:04
foo() {
char a;
char b;
char c;
char d[5];
}
За счёт выравнивания будет 20 байт (3[a,b,c] по 4 байта, d выравняет на 8 байт = 20 байт)
Если всё запихнуть в структуру, то будет оптимизированно
void display(int in) {
// What im doing here????????/
cout << ++in;
}
void foo() {
int a=10;
display(a);
}
Поидее должно вывести 11, т.е. вначале выполнится инкремент (т.к. знак инкремента стоит слева, если справа - то после вывода), птом вывод
А вот задачка от меня
struct _REC
{
unsigned char data1;
unsigned short data2;
bool data3;
bool data4;
bool data5;
bool data6;
bool data7;
unsigned short data8;
} REC;
Как оптимизировать данную структуру чтобы она занимала в памяти 6 байта. т.е. sizeof(REC) = 6
В таком виде структура занимает 12 байт.
При этом небыл потерян функционал!!!
struct _REC
{
unsigned short data2;
unsigned short data8;
unsigned char data1;
bool data3:1;
bool data4:1;
bool data5:1;
bool data6:1;
bool data7:1;
} REC;
=)
Практически правильно, но есть способо без изменения позиции переменных
Его необходимо применить чтобы данная структура стала 7 байт и не потерялся функционал
struct _REC
{
struct
{
unsigned char data1;
unsigned short data2;
bool data3;
bool data4;
bool data5;
} first_rec;
bool data6;
bool data7;
unsigned short data8;
} REC;
Также более наглядно будет в этом примере:
Размер должен быть 7 байт!!
struct _REC
{
unsigned short data1;
unsigned short data2;
unsigned short data3;
bool data4;
bool data5;
bool data6;
bool data7;
bool data8;
} REC;
P.S. Существуют 2 решения, оба сводятся к одному и томуже, но реализуются соверщенно по разному
FireFenix
22.06.2009, 10:13
Практически правильно, но есть способо без изменения позиции переменных
Использовать вместо структуры - объединения (union)?
А вот еще одно задание довольно интерестное, если сразу задуматься, то быстро можно решить.
ЗАДАЧА: необходимо откомпилить консольную прожку. Я тестил на VC++ 2008
ПРИМЕЧАНИЯ:
1) в коде нельзя ничего удалять!!
2) нельзя подключать новые хидеры!!
#include "stdio.h"
void _stdcall Sleep(unsigned long dwMilliseconds);
int main(int argc, char* argv[])
{
printf("START PAUSE");
Sleep(2000);
printf("STOP PAUSE");
return 0;
}
ПОДСКАЗКА: решение требует дописания одной строки.
вот вам моя задачка. есть класс с перегруженным оператором <. есть вектор, который хранит shared_ptr'ы на объекты этого класса. задача - поюзать std::sort не создавая левые функции, только при помощи stl b boost::bind. второй день не могу понять в чем дело =\ был бы вектор чистых объектов - можно было отсортировать строкой
std::sort(state_lines.begin(), state_lines.end());
а я уже опустился до дублирования сравнения в статик методе less
std::sort(state_lines.begin(), state_lines.end(),
boost::bind<bool>(&HorizontalStateLine::less, _1, _2));
все равно не компилится =\
e:\Program Files\boost\boost_1_38\boost\bind.hpp(282): error C2664: 'bool (const geometry::HorizontalStateLine &,const geometry::HorizontalStateLine &)' : cannot convert parameter 2 from 'std::allocator<_Ty>::value_type' to 'const geometry::HorizontalStateLine &'
with
[
_Ty=geometry::HORIZONTALSTATELINE_PTR
]
e:\Program Files\boost\boost_1_38\boost\bind.hpp(282): error C2664: 'bool (const geometry::HorizontalStateLine &,const geometry::HorizontalStateLine &)' : cannot convert parameter 1 from 'std::allocator<_Ty>::value_type' to 'const geometry::HorizontalStateLine &'
with
[
_Ty=geometry::HORIZONTALSTATELINE_PTR
]
Reason: cannot convert from 'std::allocator<_Ty>::value_type' to 'const geometry::HorizontalStateLine'
with
[
_Ty=geometry::HORIZONTALSTATELINE_PTR
]
No constructor could take the source type, or constructor overload resolution was ambiguous
люто бешено не понимаю почему от простого изменения типа элемента с объекта на указатель творится такая жопа
[ADDED]
сцуко скомпилелось =\\\ пришлось сделать внутри класса такое вот
static bool less (const HORIZONTALSTATELINE_PTR& left, const HORIZONTALSTATELINE_PTR& right);
FireFenix
22.06.2009, 10:37
А вот еще одно задание довольно интерестное, если сразу задуматься, то быстро можно решить.
ЗАДАЧА: необходимо откомпилить консольную прожку. Я тестил на VC++ 2008
ПРИМЕЧАНИЯ:
1) в коде нельзя ничего удалять!!
2) нельзя подключать новые хидеры!!
#include "stdio.h"
void _stdcall Sleep(unsigned long dwMilliseconds);
int main(int argc, char* argv[])
{
printf("START PAUSE");
Sleep(2000);
printf("STOP PAUSE");
return 0;
}
ПОДСКАЗКА: решение требует дописания одной строки.
extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long dwMilliseconds);
Ну и вот еще одна задачка от меня, если заюзать поиск то можно быстро решить её.
ЗАДАЧА: существует програмка
#include "stdio.h"
#include "windows.h"
int main(int argc, char* argv[])
{
printf("SRART\n");
__asm
{
hlt
}
return 0;
}
При выполненни вылезит ошибка из-за того что команда hlt является привелегированной и недоступной и пользопательноского режима.
Необходи обработать это исключение и выдать на экран сообщение об ошибке и завершить работу программы.
И Главное - решение не долно использовать конструкцию try except и должно иметь глобальные характер. т.е. даже если это исключение появится в отдельном потоке, то действия программы должны быть такимиже.
P.S. Решение требует примерно 5 строчек кода.
Практически правильно, но есть способо без изменения позиции переменных
Его необходимо применить чтобы данная структура стала 7 байт и не потерялся функционал
Размер должен быть 7 байт!!
[code]
struct _REC
{
unsigned short data1;
unsigned short data2;
unsigned short data3;
struct{
unsigned data4:1;
unsigned data5:1;
unsigned data6:1;
unsigned data7:1;
unsigned data8:1;
} noch_eine_struktur;
} REC;
неявное преобразование типа должно сжевать.
только чушь это всё конечно)
2 desTiny всё делает намного проще )
И то что ты показал, то 12 байт вообще )
Извиняюсь за глупый вопрос, но что делает эта единица в конце? bool data7:1;
Ведь таким же образом наследуют структуры и классы, а тут мистическая цифра "1" =/
это значит что ты эта переменная будит занимать 1 бит.
И по этому конструкция в структуре типа
bool data1:1;
bool data2:1;
bool data3:1;
bool data4:1;
bool data5:1;
bool data6:1;
bool data7:1;
bool data8:1;
тудет занимать 1 байт
jawbreaker
22.06.2009, 12:13
Задание 4.
class A {
public:
virtual void Foo (int n = 10) {
cout << "A::Foo, n = " << n << endl;
}
};
class B : public A {
public:
virtual void Foo (int n = 20) {
cout << "B::Foo, n = " << n << endl;
}
};
int main() {
A * pa = new B ();
pa->Foo ();
return 0;
}
//(c) habrahabr//h1ppo
Что выведет программа и почему?
Ну видимо B::Foo, n = 10 потому что значение по умолчанию будет взято из другой функции?
ок, так: struct _REC
{
unsigned data1:16;
unsigned data2:16;
unsigned data3:16;
unsigned data4:1;
unsigned data5:1;
unsigned data6:1;
unsigned data7:1;
unsigned data8:1;
} REC;
//его почему-то short смущал
2 desTiny Это правильный, но некрасивый способо. Есть более красивый и удобный)
Спасибо всем, кто поддержал тред. Обновил первый пост: есть нерешенные задачи!
void display(int in) {
// What im doing here????????/
cout << ++in;
}
void foo() {
int a=10;
display(a);
}
Ничего не выведет, ??/ - триграф = \(конкатенация), в итоге получится функция void display(int in) {}
class SimpleClass {
private:
int a;
int b;
public:
SimpleClass(int x) : b(x), a(b) {}
void print() {
std::cout << "a=" << a << " b=" << b << std::endl;
}
};
int main() {
SimpleClass a(42);
a.print();
return 0;
}
Насколько помню тут первой инициализируется переменная a, так как стоит первая в объявлении в private и инициализируется соответственно мусором из b. Короче SimpleClass(int x) : b(x), a(b), порядок b(x), a(b) или a(b), b(x) не важен.
Немного поправлю:
Списки инициализаторов инициализируют члены данных в порядке их следования в определении класса. Отсюда проблемы = )
Решения приняты )
2 desTiny Это правильный, но некрасивый способо. Есть более красивый и удобный)
разумеется, он убогий) как и вся идея сожрать 4 байта
Кстати, мой VS сказал про него "8 байт". и про такое тоже:
struct _REC
{
unsigned short a,b,z;
bool c:1,d:1,e:1,f:1,g:1;
} REC;
Вижу что мало кто юзает данный способ по этому напишу правильный ответ сам )
Это директивы компилятора, которые на время могут менять выравнение структур.
Подефолту выравнение идет на 4 байта. т.е. если структура будет 9 байт, то выравнеется на 12.
#pragma pack(1) - выравнение 1 байт
#pragma pack() - дефолтовое выранение. вот и выходит код типа
#pragma pack(1)
struct .....
#pragma pack()
Кстати, одним из решений другого задания (5) тоже были директивы и никто не написал :(
Забыли их, бедняжек (
Added: перечитал пару статей: действительно, скорость при использовании прагм компилятора падает. Иногда значительно.
А вешь очень удобная для оптимизации работы программы.
А если писать свой клиент-сервер которые общаются по своему протоколу, то такое просто необходимо юзать для снижения трафа
Вообще это можно использовать не только в сетевых приложениях, а везде ) Лишних пару сэкономленных байт еще никому не мешали.
Added: перечитал пару статей: действительно, скорость при использовании прагм компилятора падает. Иногда значительно.
Кстати не всегда это делать желательно, потому как бываются случае что
адрес переменной должен быть выравнен на 4 байта иначе будет ошибка.
Такое встречается в некоторых WinAPI функцих которые просто убивают приложение если адрес буфера не выравненн на 4 байта
это еще приводит к замедлению работы, ибо обращение к невыравненной ячейке памяти дает штраф
При этом различные процессоры по-разному подходят к адресации слов.
Во-первых, некоторые процессоры (PDP-11, SPARC) запрещают обращения к словам, адрес которых не кратен размеру слова, и генерируют при попытках такого обращения исключительную ситуацию ошибки шины. Другие процессоры, например VAX и х86 такие обращения разрешают, но в документации есть честное предупреждение, что обращения к невыровненным словам будут минимум в два раза медленнее, чем к выровненным (рис. 2.4).
Добавил несколько несложных задачек. Не решены задания 2, 9, 10, 11, 12, 13, 14.
С радостью выслушаю любые ваши предложения и замечания )
здание 12 хочу решить так ))
int a = 0;
char * k = str;
while (k[0])
{
a += k[0];
k++;
}
Нужно отредактировать исходный код )) Хотя твоя версия, безусловно, верна.
14) не совсем понял но всё же можно так
srand(time(NULL));
for(i=0;i<n;i++)
a[i]=random(20)+1;
/*random(20) будет делать рендом от 0 до 19 а так если прибавить единицу то от 1 до 20*/
Отредактировал условие 14 задания, спасибо )
12)
в цикле каждый раз идет обьявление и каждый раз считаеться размер str
моя версия
int k=0,A=0,n=strlen(str);
for(k=0;k<n;k++)
A+=str[k];
З.Ы. Заметь у тя счётчик масива k а ты в условии сколько выполнять цикл поставил i=)
Совершенно верно )
Баг со счетчиком был already героически пофикшен :)
Хочу добавить, что добавил(оО) слишком много репутации в за последние пару часов, поэтому дополнительное вознаграждение за участие будет позже = )
в 13) вся заковиренка в символе :?
Странный вопрос. Разумеется да, потому что это единственное, чем отличаются два случая.
тогда мой окончательный ответ что использовать
strcpy(str, "bytes "); strcat(str, very_long_string);
чем
strcpy(str, "bytes: "); strcat(str, very_long_string);
Главным является вопрос "почему?" )
Добавил задачку.
оно занимает на один байт больше
Нет, имелось в виду не это )
15)
2 3 2
Обьяснение:
перечисления... если б Х ничего не присваивалось тогда бы вывод значения был бы в зависимости от расположения переменной и каждое следуещее значение инкрементировалось на 1, тобишь если б
enum {x,y,z}
cout<<x<<" "<<y<<" "<<z;
то результат быд 0 1 2
а так Х=1+1, тогда Y=x+1=3; z=x=2
Fata1ex в моё случае экономия времяни идет раза в 2 потому как strlen - проходит и сравнивате каждый символ с нулем. Так что если юзать strlen то это двойной проход строки. Для доказательства всег овышеслудующего приведу ассемблерный код который созддает компилятор MS
случай
int a = 0;
char * k = str;
while (k[0])
{
a += k[0];
k++;
}
; int a = 0;
xor edx, edx
mov BYTE PTR _str$[esp+10], cl
mov WORD PTR _str$[esp+8], ax
; char * k = str;
lea ecx, DWORD PTR _str$[esp+8]
; while (k[0])
test al, al
je SHORT $LN1@main
$LL2@main:
; a += k[0];
movsx eax, al
; 24 : k++;
inc ecx
add edx, eax
mov al, BYTE PTR [ecx]
test al, al
jne SHORT $LL2@main
$LN1@main:
Итого 31 байт.
А теперь рассмотрим код в случае
int k=0,A=0,n=strlen(str);
for(k=0;k<n;k++)
A+=str[k];
выходит
00024 8d 44 24 10 lea eax, DWORD PTR _str$[esp+20]
00028 83 c4 04 add esp, 4
0002b 88 4c 24 0e mov BYTE PTR _str$[esp+18], cl
0002f 33 db xor ebx, ebx
00031 8d 50 01 lea edx, DWORD PTR [eax+1]
$LL11@main: /// <== вот это типа код strlen==========
00034 8a 08 mov cl, BYTE PTR [eax]
00036 40 inc eax
00037 84 c9 test cl, cl
00039 75 f9 jne SHORT $LL11@main
/// <=========================================
0003b 2b c2 sub eax, edx
0003d 8b d0 mov edx, eax
; 23 :
; 24 : for(k=0;k<n;k++)
0003f 33 c0 xor eax, eax
00041 83 fa 02 cmp edx, 2
00044 7c 20 jl SHORT $LC9@main
00046 8d 4a ff lea ecx, DWORD PTR [edx-1]
00049 55 push ebp
0004a 8d 9b 00 00 00
00 npad 6
$LL10@main:
; 25 : A+=str[k];
00050 0f be 6c 04 10 movsx ebp, BYTE PTR _str$[esp+eax+20]
00055 03 f5 add esi, ebp
00057 0f be 6c 04 11 movsx ebp, BYTE PTR _str$[esp+eax+21]
0005c 83 c0 02 add eax, 2
0005f 03 fd add edi, ebp
00061 3b c1 cmp eax, ecx
00063 7c eb jl SHORT $LL10@main
00065 5d pop ebp
$LC9@main:
; 23 :
; 24 : for(k=0;k<n;k++)
00066 3b c2 cmp eax, edx
00068 7d 05 jge SHORT $LN8@main
; 25 : A+=str[k];
0006a 0f be 5c 04 0c movsx ebx, BYTE PTR _str$[esp+eax+16]
$LN8@main:
0006f 03 fe add edi, esi
выходит 77 байт.
что выходит почти в 2,5 раза больше по коду и следовательно по скорости.
Из этого можно сказать что при работе со строковыми функциями лучше использоват собственные методы
Как можно выполнить эффективное побайтовое сравнение структур, не используя прагмы компилятора и группировку членов?
memset, memcmp?
что выходит почти в 2,5 раза больше по коду и следовательно по скорости.
следование неверно)
@here: mov ecx, 10;
loop @here;
вообще несколько байт) а time = \infty
struct A {
int x;
char y;
};
int main() {
A a, b;
memset(&a, NULL, sizeof(a));
memset(&b, NULL, sizeof(b));
a.x = 10; a.y = 'q';
a.x = 10; a.y = 'q';
if(memcmp(&a, &b, sizeof(a)))
cout << "!=";
else
cout << "=";
return 0;
}
sizeof(a) и sizeof(b) - 12 байт, хотя int+char = 5 => остальные 7 занимает мусор, его и заNULLяем и сравниваем.
Точно )
Нерешенные задачи: 2 9 10 13 14
Мне вот еще нравилась старая задачка одна, которая даже не зависела от языка программирования.
А Задачка такая:
Есть 2 числа
int a = 12;
int b = 7;
необходимо обменять значения между этими переменными при этом нельзя использовать третью переменную.
P.S. числа роли не играют.
[n]-c0der
23.06.2009, 22:34
Мне вот еще нравилась старая задачка одна, которая даже не зависела от языка программирования.
А Задачка такая:
Есть 2 числа
int a = 12;
int b = 7;
необходимо обменять значения между этими переменными при этом нельзя использовать третью переменную.
P.S. числа роли не играют.
ASM xchg...
Ну и собсна алгоритм:
a = a - b;
b = b + a;
a = b - a;
Реализация :):
procedure _XCHG(var a,b:integer);
Begin
a:= a - b;
b:=b + a;
a:=b - a;
End;
void _XCHG(int a, int b){
a = a - b;
b = b + a;
a = b - a;
};
Правильно.
Хотя красивее будет
void _XCHG(int a, int b)
{
a -= b;
b += a;
a = b - a;
};
а над этими сложениями и вычитаниями правда ещё кто-то задумывается? кстати ещё хорошо бы по ссылке передавать аргументы
void _XCHG(int& a, int& b)
{
a ^= b;
b ^= a;
a ^= b;
};
2 9 10 13 14
Каждое решенное задание это:
+1 mind (intelligence)
+1 carma
+1 experience
+5 reputation
work it!
а в 10 при обьявлении можно использовать [ и ]???
нет, от тебя зачем-то(зачем?) хотят всяких maloc'ов и указателей
согласен десятое задание по сути не очень хорошее. суть задания - сделать решение через жопу в стиле асма, с арифметикой указателей и разыменовывниями. не очень понимаю смысл
нет, от тебя зачем-то(зачем?) хотят всяких maloc'ов и указателей
совсем не понял твоего поста
эх.. чтото все заглохли с 10м заданием. Так уж и быть покажу сам )
Я сделал по хитрее. у меня так называемый массив состоит не из 8 битных элементов(байт), а из 32-х битный (ulong) что дает его спокойно юзать даже при значение N = 20
#define N 10
int main(int argc, char* argv[])
{
char * mas = (char*)malloc(N*N*4);
char * tmp = mas;
int x;
for (x = 1; x < N*N+1; x++, tmp += 4)
{
*(unsigned long *)tmp = x;
}
tmp = mas;
for (x = 1; x < N*N+1; x++, tmp += 4)
{
printf("%i\t",*(unsigned long*) tmp);
if (x % N == 0) printf("\n");
}
return 0;
}
Я сделал по хитрее
м? а в чём хитрость и хитрее чего?)
видимо задача была перехитрить себя, чтобы потом ломать голову над кодом =)
Насчет 10-ой задачи:
цель этих заданий, по-моему, состоит в том, чтобы показать решающим нечто, чего они раньше не видели, о чем не задумывались и что, возможно (!=точно), поможет им в дальнейшем.
Ай-ай! Я перепутал 10 и 14 задания ) Сорри
const int N = 3;
int** buf = new int*;
int z = 0;
for (int i=0; i<N; i++) {
*(buf + i) = new int;
for (int k=0; k<N; k++) {
*(*(buf + i) + k) = z++;
std::cout << *(*(buf + i) + k) << std::endl;
}
}
ну хзхз. тут не вижу ничего интересного. все итак очевидно - юзать сишный способ работы с памятью + арифметика указателей. это как раз то, что должен обходить за километр программист на с++.
[C/C++] ЗАДАНИЯ
Я не очень верно выразился: чтобы показать решающим нечто, чего они, по-моему, раньше не видели, о чем не задумывались и что, возможно (!=точно), поможет им в дальнейшем.
Кстати, чтото пока никто не решил мою задачку с обработкой исключений
Кстати, чтото пока никто не решил мою задачку с обработкой исключений
а одна строчка "VEH" тебя устроит?) //add: кстати, ты ведь не хотел застаить людей хучить KiUserExceptionDispatcher?
просто все чего-нть интересного ждут - вдруг появится?
кстати - скопипастю задачку из того, что я зачем-то в задания по пхп кинул:
что будет в переменной после выполнения кода (не компилить!)
/*very very long not ever overflowable*/ int a = 5+765432l;
2 desTiny вообще это решается без ассемблера и без разного рода ядерных функций.
Чисто только API функции (даже одна функция)
т.к. судя по всему мало кто это использует или комуто неинтерестно это придется рассказать самому )
Есть такая апишка - SetUnhandledExceptionFilter. Через неё можно устанавливать собственный обработчик исключений для процесса.
Т.е. даже если ошибка произошла в каком либо потоке приложения, то всё равно будет вызван этот обработчик. Дригими словами это типа try except но в глобальном масштабе всего приложения. Вообще эта функция какбы заменяет обработчик ошибок который есть в винде (который показывает сообщение что прога выполнила некорректрую операцию итд).
Использовать его очень удобно для создания стабильных приложений. К примеру если в приложенни появится ошибка, то с помошью этой технологии её можно перехватить (даже без показа на экран) и запустить приложение заново или даже для удобства скинуть отладочный дамп на винт.
Использование очень просто:
// наш фильтр
LONG MyExceptHandle(struct _EXCEPTION_POINTERS *pExceptionInfo)
{
char buf[256];
GetModuleFileNameA(0,buf,256); // получим имя нашей проги
printf("ERROR\n");
WinExec(buf,SW_SHOW); // запустим заново её
ExitProcess(0); // завершим процесс
return 0;
}
int main(int argc, char* argv[])
{
printf("SRART\n");
// ставим свой фильтр исключений
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION _FILTER)&MyExceptHandle);
__asm
{
hlt // делаем ошибку
}
return 0;
}
Хоть перезапуск лучше делать с следящем процесс.
Лично я иногда использую слудующего рода конструкцию
LONG MyExceptHandle(struct _EXCEPTION_POINTERS *pExceptionInfo)
{
_MINIDUMP_EXCEPTION_INFORMATION ExInfo;
SYSTEMTIME lt;
char NAME[512];
GetModuleFileNameA(0, NAME, 512); // получим имя нашей проги
GetLocalTime(<); // получим системное время
sprintf(NAME, "%s_%i-%i-%i_%i-%i-%i.dmp", NAME, lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute, lt.wSecond);
ExInfo.ThreadId = GetCurrentThreadId(); // зададим ID потока
ExInfo.ExceptionPointers = pExceptionInfo; // зададим исключение
ExInfo.ClientPointers = 0;
// создадим файл для дампа
HANDLE hFile = CreateFileA(NAME, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL );
// скинем дамп в файл
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),hFile,MiniDumpNormal,&ExInfo,0,0);
// закроем файл
CloseHandle(hFile);
// завершим процес с кодом появившейся ошибки
ExitProcess(pExceptionInfo->ExceptionRecord->ExceptionCode);
return 0;
}
В этоге при ошибке в прогамме, в папке с прогой появится файл
имяпроги_дата_время.dmp в котором будет содержаться дамп программы на момент ошибки.
Далее этот файл можно свободно подгрузить в отладчик или даже в VC++ 2008 открыть и подробно изучить причину ошибки (при наличии исходников вообще можно видеть строку где произошла ошибка итд итп) Очень удобная вешь для отладки больших проектов.
2 desTiny какой пакостник, людей дурить нехорошо. Ониже голову сломают без капса )
Обновил задания ) Обновил решение 10 задания ( теперь это решение 10 задания, а не другого (: ).
2 13 14 16
slesh, SetUnhandledExceptionFilter делает не то, что ты просил. он добавит обработчик в самый низ, а ты, как я понял, просил добавить его наверх. И, к тому же, твой код трёт уже установленный exceptionfilter.
а
LONG NTAPI VEHproc(PEXCEPTION_POINTERS param){
printf("error!!");
return EXCEPTION_CONTINUE_EXECUTION;
}
...
AddVectoredExceptionHandler(1, VEHProc);
...
должен вполне нормально справляться со всем.
задание 14
char data[]={1,2,3,4,5,6};
char *mas=&data[2]; // массив начинающийся с произвольного числа ))
ну блин, ведь уже написали даже - неужели трудно переписать
int a[100];
a-=10;
задание 13:
так и не понял, в чём суть
char str[100], very_long_string[] = "helllllllllooolllloollollooll";
for (int i=0; i<10000000; i++)
strcpy(str, "bytes "); strcat(str, very_long_string);
работает 5512мс, а с ":" 5544мс. Так что, если разница и есть, то только в памяти, но понятия не имею, с чего бы.
2 desTiny
Наиболее эффективно обрабатываются строки, начинающиеся с адреса, кратного четырем. Именно так компилятор размещает их в стеке и статической памяти. отсюда функция strlen(s) выполняются эффективно, а вот strlen(s+1) — не очень. Тоже самое относится и ко всем остальным функциям. Поэтому, всегда стремитесь выравнивать строки, когда это только возможно. Скажем, "strcpy(s, "bytes "); strcat(s, very_long_string);" выполняется неэффективно, но если переписать код так: "strcpy(s, "bytes: "); strcat(s, very_long_string);", то скорость его выполнения значительно возрастет, за счет того, что адрес конца строки s станет кратен 4 байтам.
очень спорно. некоторые компиляторы делают оптимизированное копирование числа байтов, кратных четырем, а остаток спокойно ифом и выбором из 3х условий - длина = 1, 2, 3. Все очень сильно зависит от компилятора и его настроек. Вот мсный компиль практически всегда дает while(*dst++ = *src++) и ему глубоко чихать на выравнивание =)
2 16
Всем желающим написать задание писать мне в ПМ или прямо сюда.
2 desTiny
по-моему 30 миллисекунд за +миллион символов (вроде в дизасме без всяких доп. выравниваний) - это по-моему достаточно, чтобы оспорить это утверждение:)
и к тому же в первом случае (если обозначить адрес начала за 0) конец на позиции 6, а во втором 7 - то есть тут вроде нет никакого выравнивания. Но если даже добавить ещё один символ - получаем 5614мс - и никакого выигрыша.
Busted :)
desTiny, наверно, как и сказал Ra$cal, все зависит от реализации )
Busted :)
:(
#16 будем считать, что слеш написал решение)
утверждение l != 1 - там в один пиксель разница:) Поэтому a=765437
чё больше не будет заданий?
Не помню где нашёл... было сохранено в txt файле:
Что выведет данная программа?(Не hello, world точно...)
/*
* HELLO WORLD program
* by Jack Applin and Robert Heckendorn, 1985
*/
main(v,c)char**c;{for(v[c++]="Hello, world!\n)";
(!!c)[*c]&&(v--||--c&&execlp(*c,*c,c[!!c]+!!c,!c));
**c=!c)write(!!*c,*c,!!**c);}
P.S Tckb не в тему удалите пост...
Roston, тема к сожалению не пользуется большой популярностью ( поэтому и нет.
Ch3ck, это ацкей изврат :(
Я постоянно эту темку читаю) вот тока у самого опыта маловато => интересных задачек нет. =\
Я думаю, что, наверное, можно постить сюда не только интересные задания, но и просто обычные задания, так как не у всех есть желание и возможность покупать и читать практикумы и задачники. Как вам такая идея? Например, задание написать парсер небольшой или создать эффективную функцию? Если есть предложения по развитию треда вы пишите: все пожелания учитываются, а то тема увядает, так как никакой инициативы со стороны нет :(
Задачка не сложная, для начинающих типа Balvan-а . (циклы и масиивы)
1.
Ввести число n и заполнить 2мерный массив размеров n*n числами 1,2,3 по спирали.
Например n=4
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
fker Спасибо! =D
int SpiralArray (int n)
{
int k = 1;
int j;
int m;
for (int i=1; i==n; i++) {
if (i%2<>0 and j<=n)
for (j=m; j==1; i--){
int a[i][j]=k++;};
else for (j=1; j==n; j++) {
int[i][j]=k++
};
for (i=1;i==n;i++) {
for (j=1;j==n;j++){
cout << a[i][j] << " ";
}
}
}
return 0;
}
Удивительно... а как это может скомпилироваться? %)
Задание 18.
Привести два эффективных варианта выхода из большого количества вложенных циклов без использования операторов break.
1. использовать метки и оператор goto
2. создать переменную-флаг и проверять в каждом цикле не равна ли она значению, для выхода из цикла
например:
int flag=0;
for(i=z; i<n && flag!=1; i++){
blabla;
for( ; df!=n && flag!=1;)
if(что то)
flag=1;
}
}
Ладно :)
Есть третий вариант.
\\ChaOs//
09.07.2009, 13:31
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
#include <iostream>
#include <fstream>
using namespace std;
void Array(int num)
{
int **arr,i=0,j=0,n=1,d=1;
arr=new int*[num];
for(int a=0;a<num;a++)
arr[a]=new int[num];
while(d!=((num/2)+1))
{
for(;i<(num-d);i++,n++)
{
arr[i][j]=n;
}
for(;j<(num-d);j++,n++)
{
arr[i][j]=n;
}
for(;i!=(-1+d);i--,n++)
{
arr[i][j]=n;
}
for(;j!=d;j--,n++)
{
arr[i][j]=n;
}
d++;
if(d==(num/2+1))
{
arr[i][j]=n;
if(num & 1)
{
i++;
n++;
arr[i][j]=n;
}
}
}
char name[80];
up:
cout<<"Вывод в файл. Введите имя\n";
cin>>name;
ofstream file(name);
if(!file) goto up;
for(int a=0;a<num;a++)
{
for(int b=0;b<num;b++)
{
file<<arr[b][a]<<"\t";
}
file<<endl;
}
delete arr;
}
int _tmain()
{
setlocale(0,".1251");
int n;
begin:
cout<<"Введите размерность массива n*n"<<endl;
try{
cin>>n;
Array(n);
}
catch(...){cin.clear(); _flushall();cout<<"Ошибко!!! ):\n"; goto begin;}
system("pause");
return 0;
}
\\ChaOs//, размерность нужно ввести, а не задать изначально.
мой вариант про спираль на поцкале:
program spiral;
const n = 5;
type matrix = array of array of cardinal;
//----------------------------------------------------------------------
procedure fill_spiral(var m : matrix; n : cardinal);
var i, num_circle, start: integer;
begin
start := 1;
for num_circle := 0 to n div 2 -1 do begin
for i := num_circle to n - num_circle - 1 do begin
m[num_circle, i] := start + i;
m[n - num_circle - 1, n - i - 1] := 2 * n - num_circle * 4 - 2 + start + i;
end;
for i := num_circle + 1 to n - num_circle - 2 do begin
m[i, n - num_circle - 1] := start + n - num_circle * 2 + i - 1;
m[n - i - 1, num_circle] := start + 3 * n - num_circle * 6 - 3 + i;
end;
start := start + 4 * n - num_circle * 7 - 5;
end;
if n mod 2 <> 0 then m[n div 2, n div 2] := start + 1;
end;
//----------------------------------------------------------------------
var i, j: integer;
s: matrix;
BEGIN
SetLength(s, n, n);
fill_spiral(s, n);
for i := 0 to n - 1 do begin
for j := 0 to n - 1 do
write(s[i, j] : 4, ' ');
writeln;
end;
END.
bons, это, конечно, замечательно, что ты знаешь паскаль, но, к сожалению, тема называется [C/C++] ЗАДАНИЯ :(
Тем более, что решение все равно не верное. Повторяю: размерность нужно ввести с клавиатуры!
\\ChaOs//
решение верно
моё
#include<stdio.h>
#include<conio.h>
void main()
{
clrscr();
int n;
int **a;
int v,g,j,i=1;
printf("BBegu n -> ");
scanf("%d",&n);
a=new int*[n];
for(v=0; v<n; v++)
a[v]=new int[n];
g=n/2+1;
for(v=1; v<=g; v++){
for(j=v-1; j<n-v+1; a[v-1][j]=i++, j++);
for(j=v; j<n-v+1; a[j][n-v]=i++, j++);
for(j=n-v-1; j>=v-1; a[n-v][j]=i++, --j);
for(j=n-v-1; j>=v; a[j][v-1]=i++, --j);
}
for(i=0; i<n; i++){
for(j=0; j<n; j++)
printf("%3d",a[i][j]);
printf("\n\n");
}
getch();
}
\\fixed =)
fker, омг, а если число будет больше 100? Это детский сад, а не решение ) Или уже делать размерность константой изначально или вводить с клавиатуры и использовать динамический массив или векторы.
bons, это, конечно, замечательно, что ты знаешь паскаль, но, к сожалению, тема называется [C/C++] ЗАДАНИЯ :(
Тем более, что решение все равно не верное. Повторяю: размерность нужно ввести с клавиатуры!
и правда, не заметил )) ну и пусть, алгоритм все равно верный хоть и не лаконичный
\\ChaOs//
09.07.2009, 14:51
моё(со статич массивом)
Если n - нечетное, то массив заполнится не до конца
\\ChaOs//, верное решение, молодец :)
2 18
в задании 18 осталось указать еще один вариант решения
Если n - нечетное, то массив заполнится не до конца
тоже верно, не учел..
вопросик возник:
можно ли с помощью cout<< делать форматный вывод, типа printf("%3d",a) ?
\\ChaOs//
09.07.2009, 15:05
2 18
в задании 18 осталось указать еще один вариант решения
Если действия выполняются в функции, то можно просто возвратить значение
Пример:
int Func()
{
while(true)
{
...//Что-то
if(что-то==чему-то)
return что-то;
}
}
А если нам нужно продолжить выполнение функции после выхода из циклов? Не пойдет.
вопросик возник:
можно ли с помощью cout<< делать форматный вывод, типа printf("%3d",a) ?
Для таких вопросов существует отдельная тема.
\\ChaOs//
09.07.2009, 15:14
А если нам нужно продолжить выполнение функции после выхода из циклов? Не пойдет.
Ну тогда можно сгенерировать исключение.
Объясните мне, почему никто не делает задание 2? ))
jawbreaker
25.08.2009, 20:24
Задание 2.
Мы создаем класс без конструкторов. Что сгенерирует компилятор дополнительно?
Мы создаем класс, в котором есть только конструктор без аргументов. Что сгенерирует компилятор дополнительно?
Мы создаем класс, в котором есть только конструктор копии. Что сгенерирует компилятор дополнительно?
Если вы написали
class Empty {};
то, знайте, что на самом деле вы создали примерно вот такой класс:
class Empty {
public:
// Конструктор без параметров
Empty();
// Копирующий конструктор
Empty(const Empty &);
// Деструктор
~Empty();
// Оператор присвоения
Empty& operator=(const Empty &);
// Оператор получения адреса
Empty * operator&();
// Оператор получения адреса константного объекта
const Empty * operator&() const;
};
ну и дальше понятно
Отличный раздел, только вот неплохо было бы не использовать WinAPI. Или, как минимум, делать задания и с POSIX-функциями.
Хм, почему задание 6 такое лёгкое сделали, там же gcc ругается при -Wall, даже думать не надо?
P.S.: да, предлагаю задачку (на чистом C!) - как за любое кол-во проходов определить, что мы находимся в кольцевом списке? Список односвязный. Если честно, я и сам хреново представляю, как это сделать, задачу предложил мой гуру :)
P.P.S.: пожалуйста, добавьте ещё заданий, а то я, как человек корыстный и решивший получить репутацию и похвалиться своими знаниями, был неприятно удивлён тем, что все задания на сях уже решены...
Вот ещё попалось. Найти ошибку в коде, который должен прочитать число из файла как 4 байта по смещению 0x123:
FILE *f;
fopen_s(&f, szFileName, "r+");
if (f){
int offset = 0x123;
fseek(f, offset, SEEK_SET);
int num;
fread(&num, 4, 1, f);
printf("%d\n", num);
fclose(f);
}
P.S.: да, предлагаю задачку (на чистом C!) - как за любое кол-во проходов определить, что мы находимся в кольцевом списке? Список односвязный. Если честно, я и сам хреново представляю, как это сделать, задачу предложил мой гуру
Известная задачка - запускаем 2 указатаеля, один будет просматривать все записи подряд, второй - через одну. Если они когда-то совпадут, то зациклились, если пройдём до конца и не совпадут, то не зациклились. Работает за O(размер списка) времени и O(1) памяти
Интересную задачу недавно встретил.
с++
Напечатать кол-во * при типе.
т.е.
int*** <=> 3
char***** <=> 5
Чем оптимальней тем лучше =)
vBulletin® v3.8.14, Copyright ©2000-2026, vBulletin Solutions, Inc. Перевод: zCarot