Кальдмееру бы утонуть в море сразу, но даже море его не брало. Море слишком его любило, оно было таким же глупым, как люди.(с)
очередной вoпрос
у меня есть кусок кода, где Person per - struct
void Print()
{
Person per;
ifstream f2;
f2.open("student.txt"
;
f2.read((unsigned char*)&per,sizeof(Person));
while(!f2.eof())
{
cout<<per.name<<" "<<per.number<<" "<<per.data<<" "<<per.pay<<endl;
}
f2.close();
}
почему-то он не принемает, unsigned
help!
у меня есть кусок кода, где Person per - struct
void Print()
{
Person per;
ifstream f2;
f2.open("student.txt"
;f2.read((unsigned char*)&per,sizeof(Person));
while(!f2.eof())
{
cout<<per.name<<" "<<per.number<<" "<<per.data<<" "<<per.pay<<endl;
}
f2.close();
}
почему-то он не принемает, unsigned

help!
-
-
29.06.2005 в 19:26Ааа... Это что, типа домашнее задание? тогда понятно. 8) Ну сделал бы тогда втоую структуру с массивом первых... Ой, что-то я повторяюсь 8) . Сорри.
черт, на счет сорта...я тормоз!
Ничего, бывает. Мы все через это прошли.
Может завтра тебе хорошую версию напишу. 8)
-
-
29.06.2005 в 19:48-
-
30.06.2005 в 13:01#include <iostream>
#include <fstream>
#include <stdio>
#include <conio>
#include <string>
#include <windows>
using namespace std;
/*здесь имя файла*/
const char FILE_NAME[]="DataBase.txt";
/*смени число для изм. макс. кол-ва записей*/
const int MAX_DATA=256;
/*смени число для изм. макс. кол-ва символов в имени*/
const int MAX_NAME=50;
/*смени число для изм. макс. кол-ва символов в дате*/
const int MAX_DATE=15;
void main_menu();
void new_data();
void sort();
void clear();
void pay();
void print();
void save();
void load();
struct Person
{
public:
char name[MAX_NAME];
int number;
char date[MAX_DATE];
bool pay ;
};
struct _base
{
public:
Person data[MAX_DATA];
int data_num;
}base;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
main()
{
base.data_num=0;
cout<<"Students database program.\t\t\t\t\tversion 0.7"<<endl<<endl;
cout<<"Do you want to load database from file(1-yes/2-no)? ";
int choice; cin>>choice; switch(choice)
{
case 1: load(); break;
case 2: break;
default: cout<<endl<<"1 OR 2 ONLY!!! FILE WILL NOT LOAD!"; getch();
}
main_menu();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void main_menu()
{
clrscr();
cout<<"Students database program.\t\t\t\t\tversion 0.7"<<endl<<endl;
cout<<"Choose an option:"<<endl;
cout<<"1 - to add a new name"<<endl;
cout<<"2 - pay to learn or not."<<endl;
cout<<"3 - delete all students, how did not pay."<<endl;
cout<<"4 - print all students."<<endl;
cout<<"5 - save base to file."<<endl;
cout<<"6 - load base from file."<<endl;
cout<<"7 - Exit."<<endl;
cout<<"Select: "; int choice; cin>>choice; switch(choice)
{
case 1: new_data(); break;
case 2: pay(); break;
case 3: clear(); break;
case 4: print(); break;
case 5: save(); break;
case 6: load(); break;
case 7: exit(0);
default: cout<<endl<<"FROM 1 TO 7!!!"; getch();
}
main_menu();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void new_data()
{
clrscr();
int temp;
cout<<"New data input."<<endl;
cout<<"Enter new name: "; gets(base.data[base.data_num].name);
cout<<"Enter number teudat zeut: "; cin>>base.data[base.data_num].number;
cout<<"Enter date today: "; gets(base.data[base.data_num].date);
cout<<"Enter pay or not: 1-true, 0 - false: "; cin>>temp; switch(temp)
{
case 0: base.data[base.data_num].pay=false; break;
case 1: base.data[base.data_num].pay=true; break;
default:
cout<<"Error! Only 0 or 1! Default (false) writing!"<<endl;
base.data[base.data_num].pay=false; getch();
break;
}
base.data_num++;
cout<<"OK!";
getch();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void sort()
{
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void pay()
{
clrscr();
if(base.data_num==0) { cout<<"There is no data in your base."; getch(); return; }
Person temp_person;
cout<<"Enter name: "; gets(temp_person.name);
for(int n=0;n<base.data_num;n++)
{
if(strcmp(base.data[n].name,temp_person.name)==0)
switch(base.data[n].pay)
{
case 0: cout<<"No, this girl did not pay."<<endl; getch(); return;
case 1: cout<<"Yes, this girl pay."<<endl; getch(); return;
default: cout<<"FATAL ERROR! DATA FAULT! BREAK!"; getch(); exit(0);
}
}
cout<<"Sorry, but there is no girl with this name in database."; getch();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void clear()
{
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void print()
{
clrscr();
if(base.data_num==0) { cout<<"There is no data in your base."; getch(); return; }
cout<<"Name\t\t\t| Number\t| Create Date\t| Pay or not"<<endl;
cout<<"________________________|_______________|_______________|___________"<<endl;
for(int n=0;n<base.data_num;n++)
{
if(strlen(base.data[n].name)<16)
cout<<base.data[n].name<<"\t\t| "<<base.data[n].number<<"\t\t| "<<base.data[n].date<<"\t| ";
else
cout<<base.data[n].name<<"\t| "<<base.data[n].number<<"\t\t| "<<base.data[n].date<<"\t| ";
if(base.data[n].pay) cout<<"Yes"<<endl; else cout<<"No"<<endl;
}
cout<<"________________________|_______________|_______________|___________"<<endl;
getch();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void save()
{
clrscr();
if(base.data_num==0) { cout<<"There is no data in your base."; getch(); return; }
cout<<"Begin saving..."<<endl;
ofstream file(FILE_NAME,ios::binary);
cout<<"File created!"<<endl;
file.write(reinterpret_cast<char*>(&base),sizeof(_base));
cout<<"File saved!"; getch();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void load()
{
clrscr();
cout<<"Begin loading..."<<endl;
if(base.data_num>0) { cout<<"Warning! All your data NOT in file will be deleted now!."<<endl; getch(); }
ifstream file(FILE_NAME,ios::binary);
cout<<"File opened!"<<endl;
file.read(reinterpret_cast<char*>(&base),sizeof(_base));
cout<<"File loaded!"; getch();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Вотъ. Классы я не использовал - не надо, так не надо. Функции sort и clear я ещё не трогал!!! Скоро доделаю и их 8) . Сохранение и загрузка, к моему удивлению, оказались очень простыми, НО файл нормально читать будет нельзя. Подключил ещё 3 библиотеки, надеюсь, в твоём компиляторе они есть - вроде они стандартные. Я очень много чего поменял, поэтому если что непонятно - спрашивай, подробно отвечу.
-
-
30.06.2005 в 13:31-
-
30.06.2005 в 13:57А прогу я тестил, много раз - все функции и сохранение нормально работают. НО, опять же, у меня древний компилятор, поэтому если у вас возникают ккакие-то ошибки, не факт, что это из-за меня.
Kalil, насчёт сортировки. Она у тебя была какая-то странная. С какими-то страшными и непонятными workers и ещё с чем-то, поэтому я проявил инициативу и написал весь сорт сам. Насчёт удаления: дабы не вызывать глюков, предлагаю ввести в Person переменную block, которая будет означать, что данные "удалены". Т.е. при выводе на экран они просчитываться не будут. И ещё: почему нет русского языка? Если его просто неправильно обрабатывает компилятор, могу предложить функцию для правильной его обработки.
Кстати, вот сорт и модифицированный main_menu:
void sort()
{
clrscr();
int n,m,j;
Person temp_person;
cout<<"How you want to sort students?\n1. By name\n2. By number\nSelect: ";
int choice; cin>>choice; switch(choice)
{
case 1:
cout<<"Begin sorting..."<<endl;
for(n=0;n<base.data_num;n++)
for(m=n;m<base.data_num;m++)
for(j=0;j<12;j++)
if(base.data[n].name[j]>base.data[m].name[j])
{
temp_person=base.data[m];
base.data[m]=base.data[n];
base.data[n]=temp_person;
j=12;
} else if(base.data[n].name[j]<base.data[m].name[j]) j=12;
cout<<"Sorting complite!"; getch(); break;
case 2:
cout<<"Begin sorting..."<<endl;
for(n=0;n<base.data_num;n++)
for(m=n;m<base.data_num;m++)
if(base.data[n].number>base.data[m].number)
{
temp_person=base.data[m];
base.data[m]=base.data[n];
base.data[n]=temp_person;
}
cout<<"Sorting complite!"; getch(); break;
default: cout<<endl<<"1 OR 2 ONLY!!! SORTING FAULT!"; getch();
}
}
void main_menu()
{
clrscr();
cout<<"Students database program.\t\t\t\t\tversion 0.7"<<endl<<endl;
cout<<"Choose an option:"<<endl;
cout<<"1 - to add a new name"<<endl;
cout<<"2 - pay to learn or not."<<endl;
cout<<"3 - sort all students."<<endl;
cout<<"4 - delete students, if they did not pay."<<endl;
cout<<"5 - print all students."<<endl;
cout<<"6 - save base to file."<<endl;
cout<<"7 - load base from file."<<endl;
cout<<"8 - Exit."<<endl;
cout<<"Select: "; int choice; cin>>choice; switch(choice)
{
case 1: new_data(); break;
case 2: pay(); break;
case 3: sort(); break;
case 4: clear(); break;
case 5: print(); break;
case 6: save(); break;
case 7: load(); break;
case 8: exit(0);
default: cout<<endl<<"FROM 1 TO 8!!!"; getch();
}
main_menu();
}
-
-
30.06.2005 в 14:47struct Person
{
public:
char name[MAX_NAME];
int number;
char date[MAX_DATE];
bool pay ;
int block;
};
void new_data()
{
clrscr();
int temp;
cout<<"New data input."<<endl;
cout<<"Enter new name: "; gets(base.data[base.data_num].name);
cout<<"Enter number: "; cin>>base.data[base.data_num].number;
cout<<"Enter date today: "; gets(base.data[base.data_num].date);
cout<<"Enter pay or not: 1-true, 0 - false: "; cin>>temp; switch(temp)
{
case 0: base.data[base.data_num].pay=false; break;
case 1: base.data[base.data_num].pay=true; break;
default:
cout<<"Error! Only 0 or 1! Default (false) writing!"<<endl;
base.data[base.data_num].pay=false; getch();
break;
}
base.data[base.data_num].block=0;
base.data_num++;
cout<<"OK!";
getch();
}
void clear()
{
clrscr(); int count=0;
if(base.data_num==0) { cout<<"There is no data in your base."; getch(); return; }
cout<<"Start deleting students, who didn't pay."<<endl;
for(int n=0;n<base.data_num;n++)
if(base.data[n].block==0&&base.data[n].pay==0)
{
base.data[n].block=1;
cout<<base.data[n].name<<" was deleted"<<endl;
count++;
}
if(count>0) cout<<"Delete complete!"<<endl<<count<<" students was deleted.";
else cout<<"All students payed.";
getch();
}
void print()
{
clrscr();
if(base.data_num==0) { cout<<"There is no data in your base."; getch(); return; }
cout<<"Name\t\t\t| Number\t| Create Date\t| Pay or not"<<endl;
cout<<"________________________|_______________|_______________|___________"<<endl;
for(int n=0;n<base.data_num;n++)
{
if(base.data[n].block==0)
{
if(strlen(base.data[n].name)<16)
cout<<base.data[n].name<<"\t\t| "<<base.data[n].number<<"\t\t| "<<base.data[n].date<<"\t| ";
else
cout<<base.data[n].name<<"\t| "<<base.data[n].number<<"\t\t| "<<base.data[n].date<<"\t| ";
if(base.data[n].pay) cout<<"Yes"<<endl; else cout<<"No"<<endl;
}
}
cout<<"________________________|_______________|_______________|___________"<<endl;
getch();
}
-
-
30.06.2005 в 14:57и вообще имхо моим способом лучше структуру записывать и работать везде будет..
з.ы. и дайти условие для сортировки.. что там отсортировать надо? а то я по коду не понял ничего...
-
-
30.06.2005 в 16:16Xanders а static_cast что не работал?
Хех... Хм... Нууу, ты сначала расскаажи мне, тёмному, чем они вообще различаются, а потом я может чё-нить умное и выдам
и вообще имхо моим способом лучше структуру записывать и работать везде будет..
На самом деле есть простейший 100%-ный способ: без всякий cast'ов, по-ломовому, с помощью file.put() и file.get() записывать/считывать каждый символ. гарантия работы, опять же, 100%, но есть большое НО: писать это настолько муторно... Что я такаой фигнёй даже за правой дело страдать не хочу 8) .
з.ы. и дайти условие для сортировки.. что там отсортировать надо? а то я по коду не понял ничего...
Собственно записи, по имени или по номемрам, я думаю. Хотя мне самому не очень ясно было, я сделал по-своему. В коде это тут:
cout<<"How you want to sort students?\n1. By name\n2. By number\nSelect: ";
-
-
30.06.2005 в 16:39З.Ы.: Ничего, что я пофлудил? Хотя у вас это, вроде, не возбраняется. 8)
-
-
30.06.2005 в 16:43dynamic_cast<тип> - явное преобразование в тип с проверкой при выполнении
static_cast<тип> - проверка во время компиляции
reinterprеt_cast<тип> - без проверки...
вот по идее и все различия...
посимвольно считывать конечно можно... там вроде и муторного немного.. всего-то два цикла вроде...
з.ы. лана... вообще, как я понял, изначалаьно у человека была проблема в одном unsigned, а мы тут развели)) весь код переписываем )))) ну да ладно))
-
-
30.06.2005 в 16:48фигня)) мы тут по 1000 сообщений флудили )) или не тут :o
-
-
30.06.2005 в 17:37dynamic_cast<тип> - явное преобразование в тип с проверкой при выполнении
static_cast<тип> - проверка во время компиляции
reinterprеt_cast<тип> - без проверки...
Даже так? Ну и? Тебе понравится, если налоговики прийдут к тебе в дом (dynamic_cast)? Или лучше ты сам к ним пойдёшь (static_cast)? А может лучше, чтобы их вообще не было (reinterprеt_cast)? Ну, это так, лирическое отступление. Вообще ИМХО лишние заморочки с компилятором...
посимвольно считывать конечно можно... там вроде и муторного немного.. всего-то два цикла вроде...
Да ну... Влом. Я пробовал. Моим способом в 100 раз проще и быстрее. Главное, работает.
з.ы. лана... вообще, как я понял, изначалаьно у человека была проблема в одном unsigned, а мы тут развели)) весь код переписываем )))) ну да ладно))
фигня)) мы тут по 1000 сообщений флудили )) или не тут :o
В смысле в одной запаси??? Или вообще везде? Лана, тогда я спокоен.
У меня такое чувство, что все темы, на которых я обитаю разрастаются до немыслимых размеров. Наверное, потому что я такие большие сообщения всегда пишу. 8) Я недавно какое-то время жил на одном форуме, так там один топ (с моим участием) разросся больше всех остальных - несколько сотен постов! Из них моих было 20% примерно...
-
-
30.06.2005 в 18:02/* Это чтоб никто не удивлялся, что я не отвечаю 8) */
Бывайте...
-
-
02.07.2005 в 09:13Я вернулся, а все уже умерли...
Где-то я уже всё это видел...
Kalil, ау...
-
-
03.07.2005 в 15:38так ой... ну и ну... пошел долго разбираться с кодом ибо тормоз
русского вообще не надо ибо учусь на иврите
спасибо всем!!!!
-
-
03.07.2005 в 15:45зачем нужно такое обявление?
void main_menu();
void new_data();
void sort();
void clear();
void pay();
void print();
void save();
void load();
потом зачем два стракта?
с main перемудрил, мне больше 5 не надо
так,
-
-
03.07.2005 в 16:39gets(base.data[base.data_num].name); cin>>base.data[base.data_num].name; -есть ли разница между ними и какая?
мне надо чтоб pay он из файла делал, можно ли просто load() подключить в начале?
компилятор выдает ошибку на #include <stdio>
#include <conio> О_о"
-
-
04.07.2005 в 16:18-
-
04.07.2005 в 20:50#include <conio.h>
-
-
05.07.2005 в 14:44-
-
05.07.2005 в 21:02и какое приложение создаёшь? там, по крайней мере у меня в .NET, есть консольное си-приложение.... и там все clrscr() работают...
-
-
05.07.2005 в 21:12-
-
05.07.2005 в 22:41просто экран очищает... она в паскале абсолютно такая же.. вообще борланд её для си из либы для паскаля вытащил...
-
-
05.07.2005 в 23:28Я тоже немного отсутствовал, ибо отрубили от инета.
Kalil
встречала...стукнутая
Ой, да вы девушка!
Лан, твои вопросы почитал, только сейчас уже поздно (по мнению моих родителей), поэтоку подробно всё напишу завтра с утра, ОК?
Пока коротко:
clrscr() - необязательная функция.
Кстати, значит и getch() тоже работать не будет - тоже необязательная.
#include <stdio> #include <conio> - можно не подключать - но это для clrscr(), getch() и gets() надо.
gets(base.data[base.data_num].name); cin>>base.data[base.data_num].name; -есть ли разница между ними и какая? - есть: gets()'ом можно пробелы записывать, а сin'ом - нельзя.
Пока всё, подробней - завтра.
-
-
06.07.2005 в 15:50<conio> я разобралась
а как ты сортируешь во втором case? по алфaвиту? и нельзя ли придумать с clear что-то кроме блоков? а то мне воображение отказывает
еще раз спасибо
-
-
06.07.2005 в 19:34я, конечно, девушка
Да, просто, как-то и ник и аваатр и подпись... как-то не подсказывают...
<conio> я разобралась спасибо
Значит clrscr() и прочее работают? Хорошо.
А, кстати, ты вообще код запускала в своём С++? В смысле, само приложение у тебя запустилось?
Ладно, что тут дальше...
а как ты сортируешь во втором case? по алфaвиту?
После запуска функции sort() программа спрашивает, как ты собираешься сортировать - по алфавиту (by name) или по номеру (by number). Я себе такую вольность позволил, потому что так и не понял, зачем нужен номер, если сортировка всё равно по именам?
Вот сорт только по алфавиту:
void sort()
{
clrscr();
int n,m,j;
Person temp_person;
cout<<"Begin sorting..."<<endl;
for(n=0;n<base.data_num;n++)
for(m=n;m<base.data_num;m++)
for(j=0;j<12;j++)
if(base.data[n].name[j]>base.data[m].name[j])
{
temp_person=base.data[m];
base.data[m]=base.data[n];
base.data[n]=temp_person;
j=12;
} else if(base.data[n].name[j]<base.data[m].name[j]) j=12;
cout<<"Sorting complite!"; getch();
}
и нельзя ли придумать с clear что-то кроме блоков? а то мне воображение отказывает
Хм, вообще блоки - вещь довольно удобная. Проблема в том, что если использовать смещение, то всё равно останется крайняя запись, на которую потом будет перезаписываться другая, что может привести к глюкам. Хотя, в принципе, можно создать "пустую" запись, которой заменять крайнюю... Вобщем, если очень надо, могу попробовать...
русского вообще не надо ибо учусь на иврите
Считай, что тебе безумно повезло. Уговорить С++ правильно воспринимать русский язык - сложнейшая и глупейшая задача. 8)
зачем нужно такое обявление?
void main_menu();
void new_data();
void sort();
void clear();
void pay();
void print();
void save();
void load();
Помнишь твою проблему с сортом, когда ты пыталась использовать её ещё до того как она первый раз появлялась в программе? Так вот, так же как и ты объявляешь переменные, которые будешь использовать в начале функции, так и функции принято объявлять в начале программы, дабы не возникало таких конфликтов.
потом зачем два стракта?
Первый - стракт для самой записи, он содержит одно имя, номер и т.д. Второй - стракт для самой базы, он содержит 256 первых структур, т.е. с помощью этого второго стракта ты можешь одновременно хранить 256 (или больше) имён, номеров и т.д. в памяти компьютера, и, соответственно, сохранять/загружать их все одновременно.
с main перемудрил, мне больше 5 не надо
А их 5 и есть, только ещё сохранение и загрузка.
clrscr(); default - что эти функции делают? я их никогда не встречала
Как уже было сказано, clrscr() - очистка экрана, просто так удобнее как-то. А default - это дополнение к switch()'у, например:
int x; cin>>x; switch(x) { case 1: break; case 2: break; }
Так ты ожидаешь, что пользователь введёт 1 или 2, НО если вдруг он введёт что-нибудь другое? Так вот, этот default как раз и срабатывает во всех остальных случаях, примерно так:
int x; cin>>x; switch(x) { case 1: break; case 2: break; default: cout<<"ONLY 1 OR 2, I SAY!!!"; break; }
gets(base.data[base.data_num].name); cin>>base.data[base.data_num].name; -есть ли разница между ними и какая?
Функция cin считывает стабильно всё, что ты пишешь до первого пробела. Если ты попытаешься ввести пробел и нажмёшь enter, то программу страшно проглючит - сам пробовал. С gets()'ом же никаких проблем не возникает.
мне надо чтоб pay он из файла делал, можно ли просто load() подключить в начале?
В начале программы задаётся вопрос, нужно ли загружать базу из файла. Это полезно, если, например, ты хочешь начать новую базу. Если хочешь, чтобы он всегда загружался вначале, измени main() так:
main()
{
base.data_num=0;
load(); main_menu();
}
Вот, пока всё. 8) Ещё раз извиняюсь за задержку.
-
-
07.07.2005 в 14:28со всем разобралась
просто сортировка по алфовиту глю чит я не могу понять где, он вроде считает по алфавиту, но первую запись оставляет как была.
а как сделать "пустую" запись?
сорри, что так в наглую загрузила
-
-
07.07.2005 в 17:21просто сортировка по алфовиту глю чит я не могу понять где, он вроде считает по алфавиту, но первую запись оставляет как была.
Даже не знаю...
Я сам, просто, сейчас не могу С++ включить ибо ставить заново его надо, а то я его в прошлый раз неправильно удалял...
а как сделать "пустую" запись?
Примерно так:
Person empty; empty.name="1"; empty.number=1; empty.date=1; empty.pay=1;
// а потом что-то вроде этого:
base.data_num--; base.data[base.data_num]=empty;
сорри, что так в наглую загрузила спасибо тебе большущее
Да ладно, если б не ты, я бы С++ снова на несколько месяцев забросил бы. 8) Так что, тебе спасибо.
-
-
07.07.2005 в 17:32*вспомнив насколько забросила яву и мипс - покраснела до кончиков волос
-
-
08.07.2005 в 19:04Новый ник?
*вспомнив насколько забросила яву и мипс - покраснела до кончиков волос *
Это ещё чего... Ты бы знала сколько я всего забрасывал за всю мою жизнь... Прям аж вспоминать стыдно... Попробую перечислить: примерно пять неоконченных игр, 3Ds MAX, Flash, HTML, Access, Dark Basic, RPG Maker, Photoshop, создание обоев, аваатров, настольных игр, ККИ, даже, писательство фанфиков
Мдя. Вотъ.