Форум программистов, компьютерный форум CyberForum.ru

Задачи для тренировки и лучшего понимания - C++

Войти
Регистрация
Восстановить пароль
Другие темы раздела
C++ Возможно переписать программу? http://www.cyberforum.ru/cpp/thread153534.html
Есть программа Upgrade UA.exe хочу запустить ее на windows mobile 6. Возможно ли ее переписать.
C++ scanf Пусть нужно читать из текста слова, пропуская все символы, кроме a-z и A-Z. То есть из текста Hello, world! ololo O_o получить только Hello world ololo O o Меня интересует, можно ли это сделать с помощью одной лишь только функции scanf. Она, насколько я понял, позволяет немного использовать регулярные выражения (точно не знаю, они ли это). Так вот, можно ли сделать так, чтобы к примеру... http://www.cyberforum.ru/cpp/thread153153.html
C++ Вернуть stdin в консоль
Допустим я перенаправил поток stdin/stdout в файл с помощью функции freopen. Как заставить его снова работать с консолью? Добавлено через 9 минут Нашел. #include <cstdlib> #include <stdio.h> #include <conio.h> using namespace std;
Прошу помочь.Подключение dll на неуправляемом С/С++ C++
Возникла проблема.Есть рабочая dll, необходимо подключить к CLR приложению. Подключение происходит нормально. Все функции работают нормально кроме одной(хотя dll проверял все работает в обычных Win32 приложениях).Данная функция производит загрузку из файла если файл не найден-возвращает код ошибки,т.е. все нормально.Но если файл находит(путь указан точный) то происходит ошибка исключение...
C++ Не сразу закрывающаяся программа http://www.cyberforum.ru/cpp/thread152799.html
Есть команды в терминале.. вроде telnet или sql, эти программы запускаешь и они остаются открытыми пока не дашь команду, например, quit. Во время работы программы она показывает знак приглашения новой команды ">". Как это можно осуществить в C++?
C++ Парсер на С вопшем есть файл с текстом..... в етом файле есть какие даные(мусор)...и есть дни: Понедельник,Вторник,среда......с етого файла нада вывести ети дни в порядке нахождениэ... ето походу несложная задача,но для новичка сложно.... нужно именно на С а не С++ ... я пока только думал считывать каждую строку в масив и проверять каждый елемент по буквам... подробнее

Показать сообщение отдельно
Kastaneda
Форумчанин
Эксперт С++
4479 / 2841 / 227
Регистрация: 12.12.2009
Сообщений: 7,224
Записей в блоге: 1
Завершенные тесты: 1
27.07.2010, 10:46     Задачи для тренировки и лучшего понимания
Я тоже эти 2 решения нашел, третье так и не смог, поэтому посмотрел в ответы. Там оказывается решение состоит в том, что добавляется один символ, что по-моему не совсем соответствует условию задачи. (кстати об этом решении я думал, но счел его некорректным)

Добавлено через 10 минут
Помните недавно задачку, сейчас случайно в инете нашел более подробное описание, почему данный код так себя ведет.
Кому интересно.
Неочевидная особенность в синтаксисе определения переменных
Предлагается совершенно невинный на вид кусок кода на C++. Здесь нет ни шаблонов, ни виртуальных функций, ни наследования, но создатели этого чудесного языка спрятали грабли посреди чистa поля.

struct A {
A (int i) {}
};

struct B {
B (A a) {}
};

int main () {
int i = 1;
B b(A(i)); // (1)
return 0;
}

* This source code was highlighted with Source Code Highlighter.


Вопрос: какой тип у переменной b? Совсем не тот, который можно было бы предположить на первый взгляд.


Анализ

Конечно же, тип переменной b не B, иначе бы не было этой статьи Я не буду сразу приводить ответ, а вместо этого расскажу, как до него можно дойти, не копаясь в тысячестраничном стандарте.

Для начала добавим немного отладочной печати:
#include <iostream>
struct A {
A (int i) { std::cout << 'A';}
};

struct B {
B (A a) { std::cout << 'B';}
};

int main () {
int i = 1;
B b(A(i)); // (1)
return 0;
}

* This source code was highlighted with Source Code Highlighter.


Если попробовать запустить этот код, окажется, что вообще ничего не выводится. Но если заменить строку (1) на
B b(A(1));

внезапно всё начинает работать.

А теперь посмотрим внимательно на вывод компилятора при максимально включенных предупреждениях
$ g++ -W -Wall test.cpp
x.cpp:2: warning: unused parameter ‘i’
x.cpp:6: warning: unused parameter ‘a’
x.cpp: In function ‘int main()’:
x.cpp:10: warning: unused variable ‘i’

С первыми двумя строками всё понятно, действительно параметры конструкторов не используются. А вот последняя строка выглядит очень странно. Как переменная i оказалась неиспользуемой, если она используется в следующей строке?

В принципе, этой информации достаточно, чтобы, немного подумав, ответить на поставленный вопрос. Но если умные мысли в голову не приходят, и хочется ещё немного поприключаться, почему бы просто не спросить компилятор? На помощь приходит RTTI.

#include <iostream>
#include <typeinfo>

struct A {
A (int i) {}
};

struct B {
B (A a) {}
};

int main () {
int i = 1;
B b(A(i)); // (1)
std::cout << typeid(b).name() << std::endl;
return 0;
}

* This source code was highlighted with Source Code Highlighter.


При компиляции GCC 4.3 результатом выполнения этой программы является строка
F1B1AE

в которой зашифрована нужная нам информация о типе переменной (конечно, другой компилятор выдаст другую строку, формат вывода type_info::name() в стандарте не описан и оставлен на усмотрение разработчика). Узнать же, что означают эти буквы и цифры, нам поможет c++filt.
$ c++filt -t F1B1AE
B ()(A)

Вот и ответ: это функция, принимающая на вход параметр типа A и возвращающая значение типа B.

Причина

Осталось понять, почему наша строка проинтерпретировалась таким неожиданным способом. Всё дело в том, что в объявлении типа переменной лишние скобки вокруг имени игнорируются. Например, мы можем написать
int (v);

и это будет означать в точности тоже самое, что
int v;


Поэтому многострадальную строку (1) можно без изменения смысла переписать, убрав лишнюю пару скобок:
B b(A i);

Теперь невооружённым взглядом видно, что b это объявление функции с одним аргументом типа A, которая возвращает значение типа B.

Заодно мы объяснили странный ворнинг о неиспользованной переменной i — действительно, она не имеет никакого отношения к формальному параметру i.

Workarounds

Нам осталось только объяснить компилятору, что же на самом деле мы от него хотим — то есть, получить переменную типа B, проинициализированную переменной типа A. Самый простой способ — добавить лишних скобок, вот так:
B b((A(i)));

или так:
B b((A)(i));

Этого достаточно, чтобы убедить парсер, что это не объявление функции.

Как альтернативу, можно использовать форму вызова конструктора с помощью присваивания, если только конструктор не объявлен explicit:
B b = A(i);

Несмотря на наличие знака '=', никакого лишнего копирования здесь не происходит, в чём можно легко убедиться, заведя в классе B приватный конструктор копирования.

А можно просто ввести дополнительную переменную:
A a(i);
B b(a);

Правда, при этом потребуется лишнее копирование переменной a, но во многих случаях это приемлемо.

Выберите тот способ, который кажется вам более понятным
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru