Ru-MaNGOS

Ru-MaNGOS (http://mangos.ytdb.ru/index.php)
-   Языки программирования (http://mangos.ytdb.ru/forumdisplay.php?f=34)
-   -   Использование разыменования в C++ (http://mangos.ytdb.ru/showthread.php?t=4990)

nexen 13.08.2011 07:01

Использование разыменования в 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]; // Почему работает без разыменования?

Как я понял, разыменование используется для того, чтобы по указателю можно было получить значение по заданному ранее адресу, а так же изменить его, но в примерах выше значения выводятся и изменяются без разыменования, т.е используется адрес...
Вообщем я запутался в том, что написал ;/

LordJZ 13.08.2011 07:23

Код:

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'


nexen 13.08.2011 08:24

Перепутал операторы потокового ввода и вывода, извиняюсь.
Не понимаю значение слова "кастуется" :( Но если я правильно понял, то первое ваше замечание насчет std::cout было о том, что строка будет выводить без разыменования? Если да, то тогда для каких вообще переменных нужно разыменование при выводе? Я уверен на 100% только в том, что разыменование нужно для одиночной переменной.

LordJZ 13.08.2011 08:44

Каст (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"


Йоха 13.08.2011 19:59

Цитата:

Сообщение от nexen (Сообщение 24700)
Недавно начал читать книгу Джеффа Кента "C++ : Основы программирования". Сложностей, как мне кажется, нет никаких

Хех, сложностей в с++ вагон и маленькая тележка!
Конечно в программе типа:
Код:

int a = 1;
printf(a);

трудно обнаружить сложности, но когда ты начнешь использовать наследование, виртуальные функции, перегрузку операторов, шаблоны... поверь, сложностей будет море.

Deamon 13.08.2011 20:38

Цитата:

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

+1.

Например вот небольшой mindfuck в С++: http://codepad.org/jO9y9T5j
И таких mindfuck'ов в С++...

LordJZ 13.08.2011 21:08

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

Deamon, пояснение к коду? У меня все отрабатывает корректно.

Deamon 13.08.2011 21:32

Цитата:

Сообщение от LordJZ (Сообщение 24710)
Пришли да напугали...

Deamon, пояснение к коду? У меня все отрабатывает корректно.

Майдфак в том, что у функции формальный параметр - класс, а фактический - число. Этот пример демонстрирует автоматическое преведение типов в С++: перед вызовом функции f неявно вызывается конструктор класса A.

LordJZ 13.08.2011 21:43

Цитата:

Сообщение от Deamon (Сообщение 24711)
Майдфак в том, что у функции формальный параметр - класс, а фактический - число. Этот пример демонстрирует автоматическое преведение типов в С++: перед вызовом функции 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();
        }
    }


Forgotten 13.08.2011 23:15

Можно, но, судя по коду, намного сложнее :)

rsa 13.08.2011 23:24

Цитата:

Сообщение от Forgotten (Сообщение 24714)
Можно, но, судя по коду, намного сложнее :)

хех. будем спорить на каком языке проще отстрелить себе все ненужные части тела? ставлю 10 баксов на асм :)

LordJZ 14.08.2011 04:33

Цитата:

Сообщение от Forgotten (Сообщение 24714)
Можно, но, судя по коду, намного сложнее :)

Только в данном конкретном примере, т.к. C# — строго типизированный язык, а C++ — нет.

nexen 14.08.2011 14:42

Раз уж отошли от темы, тогда поясните, пожалуйста, что значит оператор " -> "?

Den 14.08.2011 14:53

Для выбора объекта.

LordJZ 14.08.2011 14:59

Цитата:

Сообщение от nexen (Сообщение 24722)
Раз уж отошли от темы, тогда поясните, пожалуйста, что значит оператор " -> "?

Обращение к первому объекту по указателю.
Код:

class A
{
public:
    void f();
};

A* a = ...;
a->f();
(*a).f(); // То же самое
a[0].f(); // То же самое


rsa 14.08.2011 15:37

Цитата:

Сообщение от LordJZ (Сообщение 24724)
Обращение к первому объекту по указателю.

только не забудьте ремарку - "если этот оператор никто не перегрузил раньше". а то бывает иногда :(

LordJZ 14.08.2011 16:27

Цитата:

Сообщение от rsa (Сообщение 24725)
только не забудьте ремарку - "если этот оператор никто не перегрузил раньше". а то бывает иногда :(

Ну это к любому оператору относится... опять же, стрельба в ноги

nexen 15.08.2011 09:36

Дочитал книжку, однако там так и не были описаны операторы для работы с символьными строками и символьными массивами. Нашел в интернете, что следующая функция-член работает и с С-строками и классой С++ строк : 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 :(

Йоха 15.08.2011 12:33

Цитата:

Сообщение от nexen (Сообщение 24740)
Дочитал книжку, однако там так и не были описаны операторы для работы с символьными строками и символьными массивами. Нашел в интернете, что следующая функция-член работает и с С-строками и классой С++ строк : 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 (Сообщение 24740)
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

nexen 15.08.2011 13:00

Цитата:

Сообщение от Йоха (Сообщение 24744)
...

Насчет динамического массива, я не то имел ввиду. Я не хотел копировать значения одного массива в другой. Я хотел сделать так, чтобы кол-во элементов динамического массива было задано инициализацией (да, там я её забыл), а затем менялось. То есть :
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;
}


Йоха 15.08.2011 15:03

Цитата:

Насчет динамического массива, я не то имел ввиду. Я не хотел копировать значения одного массива в другой. Я хотел сделать так, чтобы кол-во элементов динамического массива было задано инициализацией (да, там я её забыл), а затем менялось.
Приведеный кусок кода делает как раз то что ты хотел. Просто так размер менять нельзя. Если сильно хочется - используй 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;
}


nexen 15.08.2011 15:50

Цитата:

Сообщение от Йоха (Сообщение 24753)
...

Пришлось погуглить насчет _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'

Йоха 15.08.2011 20:24

Цитата:

Сообщение от nexen (Сообщение 24754)
Пришлось погуглить насчет _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> ошибка пропадет.

Кстати сейчас вот сел еще раз почитал условие задачи, мой алгоритм неверный. На работе в попыхах не совсем верно понял.

Йоха 15.08.2011 21:52

Вот 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:35

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

Код:

#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;
}


nexen 16.08.2011 06:00

Получается, если я включу директиву 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, а там на оптимизацию смотрели).

Йоха 16.08.2011 09:05

Цитата:

Сообщение от nexen (Сообщение 24765)
Получается, если я включу директиву 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, а там на оптимизацию смотрели).
ну тогда понятно =)

nexen 20.08.2011 15:43

Как можно 1 символ перегнать в тип int? atoi и прочие считывают только строки : (

LordJZ 20.08.2011 16:40

Цитата:

Сообщение от nexen (Сообщение 24852)
Как можно 1 символ перегнать в тип int? atoi и прочие считывают только строки : (

Символы 0-9 идут по порядку:
Код:

char c = '9';
int i = c - '0';
assert(i == 9);


nexen 20.08.2011 19:11

Получается, что можно любой целочисленной переменной присвоить значение символа, просто в ц.переменной будет его ASCII код? А если я хочу обратно переделать? Т.е из, допустим, кода 132 ASCII, который хранится в переменной i=132, получить её символ, что мне нужно сделать? В Pascal'е был унарный оператор #...

zergtmn 20.08.2011 20:06

(char)i

nexen 21.08.2011 09:44

Что ж такое, опять проблемы с одинарными символами ;/ На этот раз мне нужно следующее. Есть строка, в ней мне нужны определенные 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]);
Как только не пытался. Все в пустую ;\ Подскажите, как вообще не сломать себе мозг с этими одинарными символами и что сделать мне в приведенной выше программе, чтобы проверка работала нормально?

zergtmn 21.08.2011 10:06

if(0 == strncmp(str.c_str(), "Dialogue", 8))

nexen 21.08.2011 15:58

Цитата:

Сообщение от zergtmn (Сообщение 24864)
if(0 == strncmp(str.c_str(), "Dialogue", 8))

А если мне нужно N-символов с I-символа сравнить в одной строке с другой?
Предположим, что пользователь вводить строку, которая является именем файла.
cin >> x;
Где x=*****.mkv или x=*****.cpp, и мне нужно узнать, что же он ввел за расширение и, исходя из этого, редактировать файл.

rsa 21.08.2011 16:30

Цитата:

Сообщение от nexen (Сообщение 24867)
А если мне нужно N-символов с I-символа сравнить в одной строке с другой?
Предположим, что пользователь вводить строку, которая является именем файла.
cin >> x;
Где x=*****.mkv или x=*****.cpp, и мне нужно узнать, что же он ввел за расширение и, исходя из этого, редактировать файл.

вот за что терпеть не могу прирожденных виндоуз-юзеров... ну с чего вы решили что в файле 1.cpp находится именно код а не видео? а файл 2.mkv - это вообще текстовый файл про морковку должен быть, а не то что вы подумали. нет такого понятия "расширение", оно сдохло еще в CP-M, до того как его в DOS привинтили.
ну а по существу вопроса - лучше пользоваться не приехавшими из C функциями а STL шаблонами. в данном случае string::compare, там можно задавать позиции сравнения.

zergtmn 21.08.2011 17:02

http://www.cplusplus.com/reference/s.../find_last_of/
тут пример есть

Йоха 22.08.2011 08:07

Цитата:

Сообщение от rsa (Сообщение 24868)
вот за что терпеть не могу прирожденных виндоуз-юзеров... ну с чего вы решили что в файле 1.cpp находится именно код а не видео? а файл 2.mkv - это вообще текстовый файл про морковку должен быть, а не то что вы подумали. нет такого понятия "расширение", оно сдохло еще в CP-M, до того как его в DOS привинтили.

Может в линуксе расширение и сдохло, а в виндовс оно живет и здравствует. В 99% случаев расширение файла однозначно указывает на его содержимое. Безусловно при написании програмы необходимо делать проверку на содержимое файла, но для юзеров в общем случае расширение является признаком по которому можно определить что это за файл: если .mkv - то это кино, если .cpp то это код на с++.

22.08.2011 08:24

да ладно вам...большая часть юзеров виндовс вообще ничего не знает о расширениях ( в win XP оно по умолчанию скрыто для зарегистрированных файлов).

Йоха 22.08.2011 09:41

Цитата:

Сообщение от Minimajack (Сообщение 24875)
да ладно вам...большая часть юзеров виндовс вообще ничего не знает о расширениях ( в win XP оно по умолчанию скрыто для зарегистрированных файлов).

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

22.08.2011 10:35

Цитата:

Сообщение от Йоха (Сообщение 24880)
Да речь не о том что знают или не знают юзеры. По расширению выбирается программа для открытия файлов и иконки сопоставляются.

речь о
Цитата:

и мне нужно узнать, что же он ввел за расширение и, исходя из этого, редактировать файл.
расширения мало, нужен заголовок.
Цитата:

Сообщение от Йоха (Сообщение 24880)
Юзеру оно сто лет не сдалось знать что к чему, он видит в проводнике файл с иконкой своего любимого медиа-плеера и тыкает в него в надежде что откроется кино, и как ни странно в подавдяющем большинстве случаев открывается именно окино.

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


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

ru-mangos.ru - Русское сообщество MaNGOS