Ru-MaNGOS

Вернуться   Ru-MaNGOS > Документация > Языки программирования

Важная информация

Языки программирования Изучаем С++, Sql, php, Lua, Python

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
Старый 13.08.2011, 07:01   #1
nexen
Новичок
 
Регистрация: 05.07.2010
Сообщений: 12
Сказал(а) спасибо: 13
Поблагодарили 0 раз(а) в 0 сообщениях
nexen На верном пути
По умолчанию Использование разыменования в C++

Недавно начал читать книгу Джеффа Кента "C++ : Основы программирования". Сложностей, как мне кажется, нет никаких, однако когда я дошел до главы указателей, я понял, что все-таки есть что-то сложное... В конце концов с указателями я разобрался, но встал вопрос о разыменовании при использовании указателей в параметрах при передачи из функции, а так же при использовании их при динамическом распределении памяти.
1) Пример использования указателя без разыменования :
Код:
#include <iostream>
using namespace std;
char*setName();
int main(void)
{
char*str=setName();
cout << str;  // Почему работает без разыменования?
return 0;
}
char*setName(void)
{
static char name[80];
cout << "Enter your name: ";
cin.getline(name,80);
return name;
}
2) Пример использования указателя при динамеческом распределении памяти (часть кода) :
Код:
cin << x;
int*userMassiv=new int[x];
userMassiv[x]=0;
userMassiv[x]+=2;
cout >> userMassiv[x]; // Почему работает без разыменования?
Как я понял, разыменование используется для того, чтобы по указателю можно было получить значение по заданному ранее адресу, а так же изменить его, но в примерах выше значения выводятся и изменяются без разыменования, т.е используется адрес...
Вообщем я запутался в том, что написал ;/
nexen вне форума   Ответить с цитированием
Старый 13.08.2011, 07:23   #2
LordJZ
Супер-модератор
 
Аватар для LordJZ
 
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
LordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранита
По умолчанию

Код:
cout << str;  // Почему работает без разыменования?
Оператор << класса std::cout принимает const char* (у данном случае автоматически кастуется из char*) для вывода строки. Например, std::cout << "Hello World";

Код:
cin.getline(name,80);
Тип char[80] автоматически кастуется в char*.

Код:
cin << x;
int*userMassiv=new int[x];
userMassiv[x]=0;
userMassiv[x]+=2;
cout >> userMassiv[x]; // Почему работает без разыменования?
Не понятно, что вы хотели сказать этими операторами.

Вообще:
Код:
const char* str = "my string"; // Тип — строка
std::cout << str; // Выведет "my string"
printf("%s", str); // Выведет "my string"
char c = str[0]; // c == 'm'
c = *str; // c == 'm'
c = *(str + 1); // c == 'y';
c = *str + 1; // c == 'n'
std::cout << str[0]; // Выведет один символ 'm'
printf("%c", str[0]); // Выведет один символ 'm'
LordJZ вне форума   Ответить с цитированием
Пользователь сказал cпасибо:
nexen (13.08.2011)
Старый 13.08.2011, 08:24   #3
nexen
Новичок
 
Регистрация: 05.07.2010
Сообщений: 12
Сказал(а) спасибо: 13
Поблагодарили 0 раз(а) в 0 сообщениях
nexen На верном пути
По умолчанию

Перепутал операторы потокового ввода и вывода, извиняюсь.
Не понимаю значение слова "кастуется" Но если я правильно понял, то первое ваше замечание насчет std::cout было о том, что строка будет выводить без разыменования? Если да, то тогда для каких вообще переменных нужно разыменование при выводе? Я уверен на 100% только в том, что разыменование нужно для одиночной переменной.
nexen вне форума   Ответить с цитированием
Старый 13.08.2011, 08:44   #4
LordJZ
Супер-модератор
 
Аватар для LordJZ
 
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
LordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранита
По умолчанию

Каст (cast) — преобразование типа, в С++ const_cast, reinterpret_cast, static_cast, dynamic_type.

Разыменование — процесс получения данных под указателем.
Код:
const char* str = "string";
char c = *str; // Получаем символ, на который указывает указатель str
Или
Код:
const char* str1 = "1111";
const char* str2 = "2222";
char const* const* strs = { str1, str2 };
printf("%s", *strs); // Выведет "1111"
LordJZ вне форума   Ответить с цитированием
Пользователь сказал cпасибо:
nexen (13.08.2011)
Старый 13.08.2011, 19:59   #5
Йоха
Умный
 
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
Йоха Скоро придёт к известности
По умолчанию

Цитата:
Сообщение от nexen Посмотреть сообщение
Недавно начал читать книгу Джеффа Кента "C++ : Основы программирования". Сложностей, как мне кажется, нет никаких
Хех, сложностей в с++ вагон и маленькая тележка!
Конечно в программе типа:
Код:
int a = 1;
printf(a);
трудно обнаружить сложности, но когда ты начнешь использовать наследование, виртуальные функции, перегрузку операторов, шаблоны... поверь, сложностей будет море.
Йоха вне форума   Ответить с цитированием
Старый 13.08.2011, 20:38   #6
Deamon
WowCore Dev
 
Регистрация: 11.03.2010
Сообщений: 112
Сказал(а) спасибо: 10
Поблагодарили 51 раз(а) в 25 сообщениях
Deamon Скоро придёт к известности
По умолчанию

Цитата:
Сообщение от Йоха Посмотреть сообщение
трудно обнаружить сложности, но когда ты начнешь использовать наследование, виртуальные функции, перегрузку операторов, шаблоны... поверь, сложностей будет море.
+1.

Например вот небольшой mindfuck в С++: http://codepad.org/jO9y9T5j
И таких mindfuck'ов в С++...
Deamon вне форума   Ответить с цитированием
Старый 13.08.2011, 21:08   #7
LordJZ
Супер-модератор
 
Аватар для LordJZ
 
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
LordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранита
По умолчанию

Пришли да напугали...

Deamon, пояснение к коду? У меня все отрабатывает корректно.
LordJZ вне форума   Ответить с цитированием
Старый 13.08.2011, 21:32   #8
Deamon
WowCore Dev
 
Регистрация: 11.03.2010
Сообщений: 112
Сказал(а) спасибо: 10
Поблагодарили 51 раз(а) в 25 сообщениях
Deamon Скоро придёт к известности
По умолчанию

Цитата:
Сообщение от LordJZ Посмотреть сообщение
Пришли да напугали...

Deamon, пояснение к коду? У меня все отрабатывает корректно.
Майдфак в том, что у функции формальный параметр - класс, а фактический - число. Этот пример демонстрирует автоматическое преведение типов в С++: перед вызовом функции f неявно вызывается конструктор класса A.
Deamon вне форума   Ответить с цитированием
Старый 13.08.2011, 21:43   #9
LordJZ
Супер-модератор
 
Аватар для LordJZ
 
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
LordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранита
По умолчанию

Цитата:
Сообщение от Deamon Посмотреть сообщение
Майдфак в том, что у функции формальный параметр - класс, а фактический - число. Этот пример демонстрирует автоматическое преведение типов в С++: перед вызовом функции f неявно вызывается конструктор класса A.
С++ — статически типизированный язык. Всё верно. Не хотите неявность — укажите это! http://codepad.org/5WMSbjLr

Таким же образом можно выстрелить себе в ногу в, скажем, строго-типизированном C#:
Код:
    public class MainClass
    {
        struct A
        {
            public int i;

            public static implicit operator A(int a)
            {
                return new A { i = a };
            }
        }

        static void f(A a)
        {
            Console.WriteLine("{0}", a.i);
        }

        public static void Main()
        {
            f(15);
            Console.ReadLine();
        }
    }

Последний раз редактировалось LordJZ; 13.08.2011 в 21:55.
LordJZ вне форума   Ответить с цитированием
Старый 13.08.2011, 23:15   #10
Forgotten
Новичок
 
Регистрация: 07.04.2010
Сообщений: 25
Сказал(а) спасибо: 1
Поблагодарили 2 раз(а) в 2 сообщениях
Forgotten На верном пути
По умолчанию

Можно, но, судя по коду, намного сложнее
Forgotten вне форума   Ответить с цитированием
Старый 13.08.2011, 23:24   #11
rsa
Почетный флудер
Старожил
 
Аватар для rsa
 
Регистрация: 08.03.2010
Адрес: Мурманск, Россия
Сообщений: 788
Сказал(а) спасибо: 55
Поблагодарили 333 раз(а) в 151 сообщениях
Записей в дневнике: 1
rsa Как самоцвет среди гранитаrsa Как самоцвет среди гранитаrsa Как самоцвет среди гранитаrsa Как самоцвет среди гранита
По умолчанию

Цитата:
Сообщение от Forgotten Посмотреть сообщение
Можно, но, судя по коду, намного сложнее
хех. будем спорить на каком языке проще отстрелить себе все ненужные части тела? ставлю 10 баксов на асм
rsa вне форума   Ответить с цитированием
Старый 14.08.2011, 04:33   #12
LordJZ
Супер-модератор
 
Аватар для LordJZ
 
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
LordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранита
По умолчанию

Цитата:
Сообщение от Forgotten Посмотреть сообщение
Можно, но, судя по коду, намного сложнее
Только в данном конкретном примере, т.к. C# — строго типизированный язык, а C++ — нет.
LordJZ вне форума   Ответить с цитированием
Старый 14.08.2011, 14:42   #13
nexen
Новичок
 
Регистрация: 05.07.2010
Сообщений: 12
Сказал(а) спасибо: 13
Поблагодарили 0 раз(а) в 0 сообщениях
nexen На верном пути
По умолчанию

Раз уж отошли от темы, тогда поясните, пожалуйста, что значит оператор " -> "?
nexen вне форума   Ответить с цитированием
Старый 14.08.2011, 14:53   #14
Den
Ученый
 
Регистрация: 10.03.2010
Адрес: Бобруйск
Сообщений: 284
Сказал(а) спасибо: 213
Поблагодарили 98 раз(а) в 84 сообщениях
Den Скоро придёт к известностиDen Скоро придёт к известности
По умолчанию

Для выбора объекта.
Den вне форума   Ответить с цитированием
Старый 14.08.2011, 14:59   #15
LordJZ
Супер-модератор
 
Аватар для LordJZ
 
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
LordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранита
По умолчанию

Цитата:
Сообщение от nexen Посмотреть сообщение
Раз уж отошли от темы, тогда поясните, пожалуйста, что значит оператор " -> "?
Обращение к первому объекту по указателю.
Код:
class A
{
public:
    void f();
};

A* a = ...;
a->f();
(*a).f(); // То же самое
a[0].f(); // То же самое
LordJZ вне форума   Ответить с цитированием
Пользователь сказал cпасибо:
nexen (14.08.2011)
Старый 14.08.2011, 15:37   #16
rsa
Почетный флудер
Старожил
 
Аватар для rsa
 
Регистрация: 08.03.2010
Адрес: Мурманск, Россия
Сообщений: 788
Сказал(а) спасибо: 55
Поблагодарили 333 раз(а) в 151 сообщениях
Записей в дневнике: 1
rsa Как самоцвет среди гранитаrsa Как самоцвет среди гранитаrsa Как самоцвет среди гранитаrsa Как самоцвет среди гранита
По умолчанию

Цитата:
Сообщение от LordJZ Посмотреть сообщение
Обращение к первому объекту по указателю.
только не забудьте ремарку - "если этот оператор никто не перегрузил раньше". а то бывает иногда
rsa вне форума   Ответить с цитированием
Старый 14.08.2011, 16:27   #17
LordJZ
Супер-модератор
 
Аватар для LordJZ
 
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
LordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранита
По умолчанию

Цитата:
Сообщение от rsa Посмотреть сообщение
только не забудьте ремарку - "если этот оператор никто не перегрузил раньше". а то бывает иногда
Ну это к любому оператору относится... опять же, стрельба в ноги
LordJZ вне форума   Ответить с цитированием
Старый 15.08.2011, 09:36   #18
nexen
Новичок
 
Регистрация: 05.07.2010
Сообщений: 12
Сказал(а) спасибо: 13
Поблагодарили 0 раз(а) в 0 сообщениях
nexen На верном пути
По умолчанию

Дочитал книжку, однако там так и не были описаны операторы для работы с символьными строками и символьными массивами. Нашел в интернете, что следующая функция-член работает и с С-строками и классой С++ строк : str.erase(i,k) - где i - № символа, с которого удалется k-символов. Так ли это?

Так же я не нашел оператора, функции-члена или библиотеки для поиска нужных символов в строке. Допустим, дана строка :
str="lol what.wtf.12"
Мне из неё нужно получить число 12. Конечно, можно проверять каждый символ isdigit'том, но если мне известно, что в строке есть число, которое хранится в переменной X, не проще ли будет найти первое вхождение строки X в строку STR?.. В Turbo Pascal'е есть такая хорошая команда : pos(str,x). Однако гугл трубит в рог с заявлением, что такой команды нет Так есть или нет? А если нет, то мне придется перебирать все символы до тех пор, пока не наткнусь на тот же, с которого начинается строка X, затем пройтись с помощью x.length() по строке STR, копировать все символы оттуда по длине X и записать их в STR2, а затем сравнить эти две строки? D:
p.s Или может у вас есть ссылка, где описаны операторы и функции-члены для работы с классой С++ строк и С-строк?
p.p.s Можно ли задать динамический массив, а затем его использовать таким образом :
int x;
int*massiv=new int[x];
x=2;
// а затем, если мне понадобится более 2ух элементов сделать следующее
x++; // станет ли массив из трех элементов, если я переназначу переменную по ходу дела и что будет с массивом из трех элементов с УЖЕ ПРИСОВЕННЫМИ ЗНАЧЕНИЯМИ если сделать следующее
x--;
p.p.p.s И да, если я вдруг задал ну о-о-о-очень тупой вопрос, пожалуйста, не высылайте за мной 03

Последний раз редактировалось nexen; 15.08.2011 в 10:15.
nexen вне форума   Ответить с цитированием
Старый 15.08.2011, 12:33   #19
Йоха
Умный
 
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
Йоха Скоро придёт к известности
По умолчанию

Цитата:
Сообщение от nexen Посмотреть сообщение
Дочитал книжку, однако там так и не были описаны операторы для работы с символьными строками и символьными массивами. Нашел в интернете, что следующая функция-член работает и с С-строками и классой С++ строк : str.erase(i,k) - где i - № символа, с которого удалется k-символов. Так ли это?

Так же я не нашел оператора, функции-члена или библиотеки для поиска нужных символов в строке. Допустим, дана строка :
str="lol what.wtf.12"
Мне из неё нужно получить число 12. Конечно, можно проверять каждый символ isdigit'том, но если мне известно, что в строке есть число, которое хранится в переменной X, не проще ли будет найти первое вхождение строки X в строку STR?.. В Turbo Pascal'е есть такая хорошая команда : pos(str,x). Однако гугл трубит в рог с заявлением, что такой команды нет Так есть или нет? А если нет, то мне придется перебирать все символы до тех пор, пока не наткнусь на тот же, с которого начинается строка X, затем пройтись с помощью x.length() по строке STR, копировать все символы оттуда по длине X и записать их в STR2, а затем сравнить эти две строки? D:
p.s Или может у вас есть ссылка, где описаны операторы и функции-члены для работы с классой С++ строк и С-строк?
практически все функции для работы со строками в CRT начинаются с str.

собственно функция для поиска подстроки внутри строки называется strstr()

Раздел MSDN описывающий работу со строками
http://msdn.microsoft.com/ru-ru/library/f0151s4x.aspx

или тут
http://www.cplusplus.com/reference/c...string/strstr/

Так же можно использовать класс std::string из STL

Ну и в любом фреймворке есть свои реализации класса строки, например CString в ATL\MFC.

Цитата:
Сообщение от nexen Посмотреть сообщение
p.p.s Можно ли задать динамический массив, а затем его использовать таким образом :
int x;
int*massiv=new int[x];
x=2;
// а затем, если мне понадобится более 2ух элементов сделать следующее
x++; // станет ли массив из трех элементов, если я переназначу переменную по ходу дела и что будет с массивом из трех элементов с УЖЕ ПРИСОВЕННЫМИ ЗНАЧЕНИЯМИ если сделать следующее
x--;
p.p.p.s И да, если я вдруг задал ну о-о-о-очень тупой вопрос, пожалуйста, не высылайте за мной 03
Нет конечно.
В твоем примере переменная x и massiv никак не связаны, и изменение x ни коим образом не влияет на massiv.
Более того это ошибка - использование переменной без инициализации.
если нужен массив из двух int то пишем
Код:
int *array = new int[2];
если руками надо сделать увеличение массива до 3 элементов, то пишем следующее:
Код:
int *tmp = new int[3]; // выделяем память под новый массив из 3 элементов
memcpy(tmp, array, 2*sizeof(int)); // копируем туда данные из нашего массива
delete[] array; // освобождаем память занимаемую массивом
array = tmp;
Теперь у нас переменная array - массив из трех элементов и первые два остались на месте из старого массива

Правда если array содержит данные не простого типа, а некоего класса, то memcpy конечно же использовать нельзя. Прийдется в цикле сделать присваивание поэлементное:
Код:
for (int i = 0; i < 2; i++)
tmp[i] = array[i];

В чистом с++ нет понятия динамический массив, для этого используй класс из STL std::vector

Последний раз редактировалось Йоха; 15.08.2011 в 12:50.
Йоха вне форума   Ответить с цитированием
Пользователь сказал cпасибо:
nexen (15.08.2011)
Старый 15.08.2011, 13:00   #20
nexen
Новичок
 
Регистрация: 05.07.2010
Сообщений: 12
Сказал(а) спасибо: 13
Поблагодарили 0 раз(а) в 0 сообщениях
nexen На верном пути
По умолчанию

Цитата:
Сообщение от Йоха Посмотреть сообщение
...
Насчет динамического массива, я не то имел ввиду. Я не хотел копировать значения одного массива в другой. Я хотел сделать так, чтобы кол-во элементов динамического массива было задано инициализацией (да, там я её забыл), а затем менялось. То есть :
int elems=1,amount,mDel=0;
int*massiv=new int[elems]; // В книге так динам. массив задавался.
...code...
cin >> amount; // Кол-во, допустим, человек.
for (int i=0;i<amount; i++)
if (massiv[i]<max) mDel+=1;
// Вышли из цикла.
if (mDel==amount) {...code...}
// В коде идет проверка такого плана : если у всех элементов значение меньше переменной MAX, то в массиве остается лишь одна строчка, а все остальные удаляются при помощи либо обнуления через for, либо просто изменения значения elems на 1, чтобы массив имел один элемент, а все остальные (не знаю, удалятся ли они по условию...) удалились.

Проще, наверное, будет привести полный пример. Вот моя ломаная ( :< ) программа, где я хотел использовать то, о чем писал. Однако при первом вводе ученика, она выдает ошибку дебагера.
Задание : в первой строке вводится N-кол-во учеников. В каждой из последующих N-строк идет информация о каждом в виде First-name Second-name School Grade. Нужно вывести номер школы, в которой больше всего учеников, набравших наивысший балл на районе. Т.е, если входные данные такие :
DAWd dawd 3 87
jdiaw jkdw 3 87
dwaji hjw 2 87
выходные данные будут такие :
3
p.s Не вышло объявить двумерный динамический массив : (
Код:
#include <iostream>
using namespace std;
int main()
{
	int amount, str, school, grade,pol=1,max=-1,l;
	int*pupleS=new int[pol];
	int*puplePG=new int[pol];
	cout << "Enter number of students:" << endl;
	cin >> amount; cin.ignore();
	for (int i=0;i<amount;i++)
	{
		cout << "Enter information (F-name S-name School Grade) about student number #" << i+1 << " :\n";
		cin >> str >> str >> school >> grade; cin.ignore(); 
		l=0;
		if (grade>max)
		{
			pol=2; max=grade;
			pupleS[l]=school; puplePG[l]=1;
		}
		else if (grade==max)
		{
			while (pupleS[l]!=0 && pupleS[l]!=school)
				l++;
			if (pupleS[l]==school)
				puplePG[l]++;
			else
			{
				pol++;
				pupleS[l]=school;
				puplePG[l]=1;
			}
		}
	}
	max=puplePG[0]; int kpp;
	for (int i=1;i<pol;i++)
		if (max<puplePG[i]) {kpp=i; max=puplePG[i];}
		cout << "Best school is " << kpp << endl;
		delete [] pupleS;
		delete [] puplePG;
return 0;
}
nexen вне форума   Ответить с цитированием
Старый 15.08.2011, 15:03   #21
Йоха
Умный
 
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
Йоха Скоро придёт к известности
По умолчанию

Цитата:
Насчет динамического массива, я не то имел ввиду. Я не хотел копировать значения одного массива в другой. Я хотел сделать так, чтобы кол-во элементов динамического массива было задано инициализацией (да, там я её забыл), а затем менялось.
Приведеный кусок кода делает как раз то что ты хотел. Просто так размер менять нельзя. Если сильно хочется - используй std::vector, но собственно он делает то же самое, просто реализация скрыта в недрах класса.

А вот исходник я не осилил.
Если я правильно понял задачу, то вот мой вариант решения:

Код:
#include <iostream>
#include <string>
struct SCHOOLINFO
{
	std::string name;
	int school;
	int grade;
	int count;
};
int _tmain(int argc, _TCHAR* argv[])
{
	int number, max = -1;
	std::cout << "Enter number of students" << std::endl;
	std::cin >> number;
	SCHOOLINFO *info = new SCHOOLINFO[number];
	// ввод данных и вычисление максимального бала
	for (int i = 0; i < number; i++)
	{
		std::cout << "Enter fname lname school grade for student #" << i + 1 << std::endl;
		std::cin >> info[i].name >> info[i].name >> info[i].school >> info[i].grade;
		info[i].count = 0;
		if (info[i].grade > max)
			max = info[i].grade;
	}
	int maxcount = 0, school;
	// подсчет количества школ имеющих максимальный бал и вычисление школы имеющей максимум
	for (int i = 0; i < number; i++)
	{
		if (info[i].grade == max)
		{
			info[i].count++;
			if (info[i].count > maxcount)
			{
				maxcount = info[i].count;
				school = info[i].school;
			}
		}
	}
	
	std::cout << "highest grade has school " << school << std::endl;
	delete[] info;
	return 0;
}

Последний раз редактировалось Йоха; 15.08.2011 в 15:06.
Йоха вне форума   Ответить с цитированием
Пользователь сказал cпасибо:
nexen (15.08.2011)
Старый 15.08.2011, 15:50   #22
nexen
Новичок
 
Регистрация: 05.07.2010
Сообщений: 12
Сказал(а) спасибо: 13
Поблагодарили 0 раз(а) в 0 сообщениях
nexen На верном пути
По умолчанию

Цитата:
Сообщение от Йоха Посмотреть сообщение
...
Пришлось погуглить насчет _tmain, насколько я понял, это то же самое, что main, просто имеет некоторые упрощенные функции для компилятора. Все остальное я, вроде бы понял, да и я бы так же сделал, если бы знал, что структура поддерживает динамические массивы (а классы их поддерживают?? а двумерные динамические массивы?? и если да, то, пожалуйста, подскажите, как их задать?).
Однако... проблема в том, что кол-во учеников может быть, как написано в задаче, до 100.000. Что дает ОГО-ГО-ГО мусорной памяти при динамическом массиве на 100.000 учеников, так ещё и для структуры в 3 переменных экземпляра. А использовать из них нужно только тех, у кого наивысшие баллы, то есть, если нашелся человек с наивысшим баллом, можно сразу весь массив потереть. Именно поэтому мне нужно по ходу дела менять массив.

p.s Кстати, а почему практически никто не использует using namespace std; ?

p.p.s Только доперло насчет того куска кода, где ты показывал легкую альтернативу std::vector. Даже если каждый раз пересоздавать массив, то я, в конце концов, столкнусь либо с уймой проверок, так как пересоздание массива должно быть ПРЯМО в цикле for, а это значит, что на разные итерации нужны разные объявления массивов. Тут уж я чекнусь быстрее, но за то, что показал такой подход, спасибо! ^^

p.p.p.s Кстати, в этой задачи имена не нужны вообще, а потому я просто использовал строковую str и больше её не использовал (Вот в чем ошибка >_< я её в int занес, а вводил имя >_____<! Теперь все работает, и, похоже, прямо во время работы программы размер массива меняется в зависимости от pol++ или pol=1. Однако, у меня там ошибка в конце, из-за чего всегда должно быть две и более школ, в которых есть хотя бы по одному ученику с наивысшим баллом, иначе ошибка). Можно ли как-то, как динамический массив, во время работы программы выпилить одну переменную или не динамический массив из памяти процесса?

p.p.p.p.s Кстати, мне компилятор на твое решение матерится Оо
1>d:\git\tests\helloworld!\example.cpp(10) : error C2061: syntax error : identifier '_TCHAR'

Последний раз редактировалось nexen; 15.08.2011 в 16:33.
nexen вне форума   Ответить с цитированием
Старый 15.08.2011, 20:24   #23
Йоха
Умный
 
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
Йоха Скоро придёт к известности
По умолчанию

Цитата:
Сообщение от nexen Посмотреть сообщение
Пришлось погуглить насчет _tmain, насколько я понял, это то же самое, что main, просто имеет некоторые упрощенные функции для компилятора.
Такое объявление делается для поддержки юникода, перед использованием необходимо включить файл <tchar.h>

Цитата:
Все остальное я, вроде бы понял, да и я бы так же сделал, если бы знал, что структура поддерживает динамические массивы (а классы их поддерживают?? а двумерные динамические массивы?? и если да, то, пожалуйста, подскажите, как их задать?).
Классы от структур отличаются лишь тем что у них по умолчанию уровень доступа к членам private, в структурах public, соответсвенно можно конечно.

Многомерные массивы динамически нормально не создаются, требуются разного рода ухищрения. Самый нормальный вариант использовать какой-нибудь готовый класс, ну или написать самому.

Цитата:
Однако... проблема в том, что кол-во учеников может быть, как написано в задаче, до 100.000. Что дает ОГО-ГО-ГО мусорной памяти при динамическом массиве на 100.000 учеников, так ещё и для структуры в 3 переменных экземпляра. А использовать из них нужно только тех, у кого наивысшие баллы, то есть, если нашелся человек с наивысшим баллом, можно сразу весь массив потереть. Именно поэтому мне нужно по ходу дела менять массив.
И кто-то будет вводить сто тысяч учеников ?
Согласен можно исключить из структуры name, оно все равно не используется.
А остальное, даже при количестве данных в 100000, объем занимаемой памяти будет равен 12 * 100000, то есть чуть больше 1 мегабайта, что является сущим пустяком.

Цитата:
p.s Кстати, а почему практически никто не использует using namespace std; ?
Вываливание пространства имен в глобальное пространство - не очень хорошая идея по целому ряду причин. namespace для того и придумали что бы все было в своих "загонах"

Цитата:
p.p.p.p.s Кстати, мне компилятор на твое решение матерится Оо
1>d:\git\tests\helloworld!\example.cpp(10) : error C2061: syntax error : identifier '_TCHAR'
включи <tchar.h> ошибка пропадет.

Кстати сейчас вот сел еще раз почитал условие задачи, мой алгоритм неверный. На работе в попыхах не совсем верно понял.
Йоха вне форума   Ответить с цитированием
Пользователь сказал cпасибо:
nexen (16.08.2011)
Старый 15.08.2011, 21:52   #24
Йоха
Умный
 
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
Йоха Скоро придёт к известности
По умолчанию

Вот 100% рабочий вариант -)
Первая часть где ввод данных и вычисление максимального бала - не изменилась. И кстати занимать памяти это дело будет всего 782 Кбайта при количестве элементов 100000.

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

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

Код:
#include <tchar.h>
#include <iostream>
#include <string>
#include <map>

struct SCHOOLINFO
{
	int school;
	int grade;
};

int _tmain(int argc, _TCHAR* argv[])
{
	std::map<int, int> schoolmap;
	std::string name;
	int count, maxgrade = 0;
	std::cout << "Enter number of students" << std::endl << "> ";
	std::cin >> count;
	SCHOOLINFO *info = new SCHOOLINFO[count];
	std::cout << "Enter fname lname school grade for students" << std::endl;
	for (int i = 0; i < count; i++)
	{
		std::cout << "#" << i + 1 << "> ";
		std::cin >> name >> name >> info[i].school >> info[i].grade;
		if (info[i].grade > maxgrade)
		{
			maxgrade = info[i].grade;
		}
	}
	int school, maxcount = 0;
	for (int i = 0; i < count; i++)
	{
		if (info[i].grade == maxgrade)
			if (schoolmap.count(info[i].school) == 0)
				schoolmap.insert(std::make_pair(info[i].school, 1));
			else
			{
				schoolmap[info[i].school]++;
				if (schoolmap[info[i].school] > maxcount)
				{
					maxcount = schoolmap[info[i].school];
					school = info[i].school;
				}
			}
	}
	std::cout << "winner school " << school << std::endl;
	delete[] info;
	return 0;
}

Последний раз редактировалось Йоха; 15.08.2011 в 22:00.
Йоха вне форума   Ответить с цитированием
Старый 15.08.2011, 22:35   #25
Йоха
Умный
 
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
Йоха Скоро придёт к известности
По умолчанию

Все, врубился! Идея в том что после ввода максимальной оценки все предыдущие данные становятся неактуальными. Вот измененный вариант без выделения памяти вообще, все считается в процессе ввода. Единственное что не учтено - то что если две или более школы наберут одинаковое количество максимальных балов. Победителем будет та школа которая первой ввелась -)

Код:
#include <tchar.h>
#include <iostream>
#include <string>
#include <map>

int _tmain(int argc, _TCHAR* argv[])
{
	std::map<int, int> schoolmap;
	std::string name;
	int count, school, grade, schoolwinner, maxgrade = -1, maxcount = -1;
	std::cout << "Enter number of students" << std::endl << "> ";
	std::cin >> count;
	std::cout << "Enter fname lname school grade for students" << std::endl;
	for (int i = 0; i < count; i++)
	{
		std::cout << "#" << i + 1 << "> ";
		std::cin >> name >> name >> school >> grade;
		if (grade == maxgrade)
		{
			if (schoolmap.count(school) == 0)
				schoolmap.insert(std::make_pair(school, 1));
			else
			{
				schoolmap[school]++;
				if (schoolmap[school] > maxcount)
				{
					maxcount = schoolmap[school];
					schoolwinner = school;
				}
			}
		}
		else if (grade > maxgrade)
		{
			schoolmap.clear();
			schoolmap.insert(std::make_pair(school, 1));
			maxgrade = grade;
			maxcount = 1;
			schoolwinner = school;
		}
	}
	std::cout << "winner school " << schoolwinner << std::endl;
	return 0;
}
Йоха вне форума   Ответить с цитированием
Пользователь сказал cпасибо:
nexen (16.08.2011)
Старый 16.08.2011, 06:00   #26
nexen
Новичок
 
Регистрация: 05.07.2010
Сообщений: 12
Сказал(а) спасибо: 13
Поблагодарили 0 раз(а) в 0 сообщениях
nexen На верном пути
По умолчанию

Получается, если я включу директиву tchar.h, а затем помечу main, как _tmain с необходимыми параметрами, то на ввод и вывод я смогу использовать любой язык, пусть даже русский или японский?

Убил мозг конструкцией std::map<int,int> schoolmap;. В книге об этом написано не было ;/ В итоге нашел такое :
map <key_type, value_type [, comparing_option [, memory_allocator] ] > map_name
- и прочее на http://en.wikipedia.org/wiki/Map_(C%2B%2B) . Но я от природы глупый и ничего в этом не понял : ( Есть где попроще написано? Желательно с простыми примерами, ато на вики самый просто пример уже вбил в ступор из-за std::cin >> s && , я даже до map не дошел :/

p.s Насчет того, чтобы не заморачиваться с оптимизацией. Дело в том, что я уже решал эти задачи на Pascal'е. Это был мой первый язык. Вот там таки было ещё хуже, ведь массив нельзя объявить ничем, кроме литерала или константы. Там пришлось ухищряться, а тут гораздо проще выходит, поэтому я и решил продвинуться вперед и попробовать сделать более или менее оптимизированный динамический массив. (именно поэтому я так судорожно бился за каждую лишнюю строчку, так как это задача из с4, а там на оптимизацию смотрели).

Последний раз редактировалось nexen; 16.08.2011 в 06:06.
nexen вне форума   Ответить с цитированием
Старый 16.08.2011, 09:05   #27
Йоха
Умный
 
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
Йоха Скоро придёт к известности
По умолчанию

Цитата:
Сообщение от nexen Посмотреть сообщение
Получается, если я включу директиву tchar.h, а затем помечу main, как _tmain с необходимыми параметрами, то на ввод и вывод я смогу использовать любой язык, пусть даже русский или японский?
Не уверен насчет ввода/вывода любого языка ... Все таки вывод осуществляется в консоль, у которой локаль по умолчанию 866.
Просто такие обертки создает сама студия при генерации нового проекта. Если UNICODE определен, то _tmain разворачивается в уникодный вариант, TCHAR в wchar_t, иначе просто в char.

Цитата:
Убил мозг конструкцией std::map<int,int> schoolmap;. В книге об этом написано не было ;/ В итоге нашел такое :
map <key_type, value_type [, comparing_option [, memory_allocator] ] > map_name
- и прочее на http://en.wikipedia.org/wiki/Map_(C%2B%2B) . Но я от природы глупый и ничего в этом не понял : ( Есть где попроще написано? Желательно с простыми примерами, ато на вики самый просто пример уже вбил в ступор из-за std::cin >> s && , я даже до map не дошел :/
map - класс из STL, суть его в том что бы хранить в списке пары ключ-значение. Ключ уникален, то есть не может быть двух записей с однаковым ключом. Подробнее об map и о других классах STL лучше почитать в соответствующей литературе. STL - это Standart Template Library (стандартная бибилотека шаблонов)

Цитата:
p.s Насчет того, чтобы не заморачиваться с оптимизацией. Дело в том, что я уже решал эти задачи на Pascal'е. Это был мой первый язык. Вот там таки было ещё хуже, ведь массив нельзя объявить ничем, кроме литерала или константы. Там пришлось ухищряться, а тут гораздо проще выходит, поэтому я и решил продвинуться вперед и попробовать сделать более или менее оптимизированный динамический массив. (именно поэтому я так судорожно бился за каждую лишнюю строчку, так как это задача из с4, а там на оптимизацию смотрели).
ну тогда понятно

Последний раз редактировалось Йоха; 16.08.2011 в 12:14.
Йоха вне форума   Ответить с цитированием
Пользователь сказал cпасибо:
nexen (16.08.2011)
Старый 20.08.2011, 15:43   #28
nexen
Новичок
 
Регистрация: 05.07.2010
Сообщений: 12
Сказал(а) спасибо: 13
Поблагодарили 0 раз(а) в 0 сообщениях
nexen На верном пути
По умолчанию

Как можно 1 символ перегнать в тип int? atoi и прочие считывают только строки : (
nexen вне форума   Ответить с цитированием
Старый 20.08.2011, 16:40   #29
LordJZ
Супер-модератор
 
Аватар для LordJZ
 
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
LordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранита
По умолчанию

Цитата:
Сообщение от nexen Посмотреть сообщение
Как можно 1 символ перегнать в тип int? atoi и прочие считывают только строки : (
Символы 0-9 идут по порядку:
Код:
char c = '9';
int i = c - '0';
assert(i == 9);
LordJZ вне форума   Ответить с цитированием
Пользователь сказал cпасибо:
nexen (21.08.2011)
Старый 20.08.2011, 19:11   #30
nexen
Новичок
 
Регистрация: 05.07.2010
Сообщений: 12
Сказал(а) спасибо: 13
Поблагодарили 0 раз(а) в 0 сообщениях
nexen На верном пути
По умолчанию

Получается, что можно любой целочисленной переменной присвоить значение символа, просто в ц.переменной будет его ASCII код? А если я хочу обратно переделать? Т.е из, допустим, кода 132 ASCII, который хранится в переменной i=132, получить её символ, что мне нужно сделать? В Pascal'е был унарный оператор #...
nexen вне форума   Ответить с цитированием
Старый 20.08.2011, 20:06   #31
zergtmn
MaNGOS Dev
 
Аватар для zergtmn
 
Регистрация: 07.03.2010
Сообщений: 314
Сказал(а) спасибо: 30
Поблагодарили 153 раз(а) в 83 сообщениях
zergtmn Обладатель прекрасной аурыzergtmn Обладатель прекрасной ауры
По умолчанию

(char)i
zergtmn вне форума   Ответить с цитированием
Пользователь сказал cпасибо:
nexen (21.08.2011)
Старый 21.08.2011, 09:44   #32
nexen
Новичок
 
Регистрация: 05.07.2010
Сообщений: 12
Сказал(а) спасибо: 13
Поблагодарили 0 раз(а) в 0 сообщениях
nexen На верном пути
По умолчанию

Что ж такое, опять проблемы с одинарными символами ;/ На этот раз мне нужно следующее. Есть строка, в ней мне нужны определенные 10 символов, работу с ними я уже организовал - спасибо вам за подсказку ^^ - а вот проверка не выходит. Дело в том, что каждая строка имеет тип string, и если первые 8 символов Dialogue, то выполняется функция, иначе итерация заканчивается. Я пытался и так :
string lolz=textLine[0]+textLine[1]....textLine[7];
и так :
char dialogue[8];
for (int i=0;i<8;i++)
strcat(dialogue,textLine[i]);
Как только не пытался. Все в пустую ;\ Подскажите, как вообще не сломать себе мозг с этими одинарными символами и что сделать мне в приведенной выше программе, чтобы проверка работала нормально?
nexen вне форума   Ответить с цитированием
Старый 21.08.2011, 10:06   #33
zergtmn
MaNGOS Dev
 
Аватар для zergtmn
 
Регистрация: 07.03.2010
Сообщений: 314
Сказал(а) спасибо: 30
Поблагодарили 153 раз(а) в 83 сообщениях
zergtmn Обладатель прекрасной аурыzergtmn Обладатель прекрасной ауры
По умолчанию

if(0 == strncmp(str.c_str(), "Dialogue", 8))
zergtmn вне форума   Ответить с цитированием
Пользователь сказал cпасибо:
nexen (21.08.2011)
Старый 21.08.2011, 15:58   #34
nexen
Новичок
 
Регистрация: 05.07.2010
Сообщений: 12
Сказал(а) спасибо: 13
Поблагодарили 0 раз(а) в 0 сообщениях
nexen На верном пути
По умолчанию

Цитата:
Сообщение от zergtmn Посмотреть сообщение
if(0 == strncmp(str.c_str(), "Dialogue", 8))
А если мне нужно N-символов с I-символа сравнить в одной строке с другой?
Предположим, что пользователь вводить строку, которая является именем файла.
cin >> x;
Где x=*****.mkv или x=*****.cpp, и мне нужно узнать, что же он ввел за расширение и, исходя из этого, редактировать файл.
nexen вне форума   Ответить с цитированием
Старый 21.08.2011, 16:30   #35
rsa
Почетный флудер
Старожил
 
Аватар для rsa
 
Регистрация: 08.03.2010
Адрес: Мурманск, Россия
Сообщений: 788
Сказал(а) спасибо: 55
Поблагодарили 333 раз(а) в 151 сообщениях
Записей в дневнике: 1
rsa Как самоцвет среди гранитаrsa Как самоцвет среди гранитаrsa Как самоцвет среди гранитаrsa Как самоцвет среди гранита
По умолчанию

Цитата:
Сообщение от nexen Посмотреть сообщение
А если мне нужно N-символов с I-символа сравнить в одной строке с другой?
Предположим, что пользователь вводить строку, которая является именем файла.
cin >> x;
Где x=*****.mkv или x=*****.cpp, и мне нужно узнать, что же он ввел за расширение и, исходя из этого, редактировать файл.
вот за что терпеть не могу прирожденных виндоуз-юзеров... ну с чего вы решили что в файле 1.cpp находится именно код а не видео? а файл 2.mkv - это вообще текстовый файл про морковку должен быть, а не то что вы подумали. нет такого понятия "расширение", оно сдохло еще в CP-M, до того как его в DOS привинтили.
ну а по существу вопроса - лучше пользоваться не приехавшими из C функциями а STL шаблонами. в данном случае string::compare, там можно задавать позиции сравнения.
rsa вне форума   Ответить с цитированием
Пользователь сказал cпасибо:
nexen (22.08.2011)
Старый 21.08.2011, 17:02   #36
zergtmn
MaNGOS Dev
 
Аватар для zergtmn
 
Регистрация: 07.03.2010
Сообщений: 314
Сказал(а) спасибо: 30
Поблагодарили 153 раз(а) в 83 сообщениях
zergtmn Обладатель прекрасной аурыzergtmn Обладатель прекрасной ауры
По умолчанию

http://www.cplusplus.com/reference/s.../find_last_of/
тут пример есть
zergtmn вне форума   Ответить с цитированием
Пользователь сказал cпасибо:
nexen (22.08.2011)
Старый 22.08.2011, 08:07   #37
Йоха
Умный
 
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
Йоха Скоро придёт к известности
По умолчанию

Цитата:
Сообщение от rsa Посмотреть сообщение
вот за что терпеть не могу прирожденных виндоуз-юзеров... ну с чего вы решили что в файле 1.cpp находится именно код а не видео? а файл 2.mkv - это вообще текстовый файл про морковку должен быть, а не то что вы подумали. нет такого понятия "расширение", оно сдохло еще в CP-M, до того как его в DOS привинтили.
Может в линуксе расширение и сдохло, а в виндовс оно живет и здравствует. В 99% случаев расширение файла однозначно указывает на его содержимое. Безусловно при написании програмы необходимо делать проверку на содержимое файла, но для юзеров в общем случае расширение является признаком по которому можно определить что это за файл: если .mkv - то это кино, если .cpp то это код на с++.
Йоха вне форума   Ответить с цитированием
Старый 22.08.2011, 08:24   #38
Minimajack
Гость
 
Сообщений: n/a
По умолчанию

да ладно вам...большая часть юзеров виндовс вообще ничего не знает о расширениях ( в win XP оно по умолчанию скрыто для зарегистрированных файлов).
  Ответить с цитированием
Старый 22.08.2011, 09:41   #39
Йоха
Умный
 
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
Йоха Скоро придёт к известности
По умолчанию

Цитата:
Сообщение от Minimajack Посмотреть сообщение
да ладно вам...большая часть юзеров виндовс вообще ничего не знает о расширениях ( в win XP оно по умолчанию скрыто для зарегистрированных файлов).
Да речь не о том что знают или не знают юзеры. По расширению выбирается программа для открытия файлов и иконки сопоставляются. Рядовому юзеру оно сто лет не сдалось знать что к чему, он видит в проводнике файл с иконкой своего любимого медиа-плеера и тыкает в него в надежде что откроется кино, и как ни странно в подавдяющем большинстве случаев открывается именно окино.
И я если вижу расширение .mkv - то я считаю что кино полагаясь только на расширение, а не лезу в хекс редактор сверить заголовок файла на предмет соответствия его формату mkv.

Последний раз редактировалось Йоха; 22.08.2011 в 09:44.
Йоха вне форума   Ответить с цитированием
Старый 22.08.2011, 10:35   #40
Minimajack
Гость
 
Сообщений: n/a
По умолчанию

Цитата:
Сообщение от Йоха Посмотреть сообщение
Да речь не о том что знают или не знают юзеры. По расширению выбирается программа для открытия файлов и иконки сопоставляются.
речь о
Цитата:
и мне нужно узнать, что же он ввел за расширение и, исходя из этого, редактировать файл.
расширения мало, нужен заголовок.
Цитата:
Сообщение от Йоха Посмотреть сообщение
Юзеру оно сто лет не сдалось знать что к чему, он видит в проводнике файл с иконкой своего любимого медиа-плеера и тыкает в него в надежде что откроется кино, и как ни странно в подавдяющем большинстве случаев открывается именно окино.
угу...в большинстве случаев это именно так. Но могу привести примеры когда наоборот( вопросы за прошлую неделю):
зы сам сначала запускаю программу для работы с файлом, а уж потом в ней и выбираю какой файл ( ну и в некоторых случаях кодировку, формат и т.п.); иногда просто ctrl+Q достаточно или F4 в тотале.
  Ответить с цитированием
Ответ


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[11330] использование ObjectGuid для тотемов вместо uint64 rsa Принятые патчи 2 11.04.2011 14:58
считаеться ли использование текстур и моделей оригинального WoW клиента нарушением автроских прав? Ultra Корзина 3 25.12.2010 14:51
Ограничение на использование игровой почты. Greshnikk Новичкам 0 07.06.2010 14:27
[patch] Использование AURA_INTERRUPT_FLAG_CAST Insider42 Патчи на рассмотрении 4 28.05.2010 13:15


Текущее время: 21:13. Часовой пояс GMT +3.


ru-mangos.ru - Русское сообщество MaNGOS
Главная цель проекта MaNGOS - обучающая, поэтому разрешается использовать исходный код и собранную программу только для образовательных целей.
Вы не можете использовать MaNGOS в коммерческих целях, а также не разрешается устанавливать публичные серверы на базе MaNGOS.
Любое копирование материалов, информации в любом виде без указания источника - форума Ru-MaNGOS будет считаться нарушением авторских прав и нарушением Уголовного Кодекса РФ, ст. 146 ст. 147.
Перевод vBulletin: zCarot