Страницы

Поиск по вопросам

воскресенье, 1 декабря 2019 г.

Как создать анимированные звёзды в космосе?

#javascript #css3 #svg #анимация


Делаю анимацию вращения планет солнечной системы.   

https://ru.stackoverflow.com/a/918238/28748  

Не хватает реалистичного, анимированного фона звездного неба.  



Величина звёзд их яркость, взаимное расположение должно быть случайным. 

Желательно добавить мерцание более крупных звёзд. 

С помощью svg smil я не могу реализовать такое, так как в этом языке нет ничего подобного,
как в JS Math.random()  

Как реализовать подобную анимацию на Javascript?
    


Ответы

Ответ 1



В качестве одного из вариантов, можно создать кучу элементов, которые будут звездами, поставить им случайную позицию и размер. Для некоторых, например размер которых больше установленного значения, добавить класс css, добавляющий мерцание. Например так: function createStar(center, radius, animation) { var star = document.createElement('div'); star.className = 'star'; star.style.width = `${radius}px`; star.style.height = `${radius}px`; star.style.top = `${center.top-radius/2}px`; star.style.left = `${center.left-radius/2}px`; star.style.animationDelay = `${animation.delay}s`; star.style.animationDuration = `${animation.duration}s`; if (radius > 6) { star.classList.add('shine'); } return star; } var container = document.getElementById("d"); for (var i = 0; i < 200; i++) { container.appendChild(createStar({ top: getRandom(0, container.offsetHeight), left: getRandom(0, container.offsetWidth) }, getRandom(2, 7), { duration: getRandom(3, 15, false), delay: getRandom(0, 7, false) })); } function getRandom(min, max, notFloor) { return (!notFloor && Math.floor || (a => a))(Math.random() * (max - min + 1) + min); } html, body { margin: 0; padding: 0; } #d { width: 100vw; height: 100vh; background: #040e17; position: relative; overflow: hidden; } .star::before { content: ''; background-color: #fff; position: absolute; border-radius: 50%; background-color: rgba(255, 255, 255, 1); position: absolute; top: 50%; left: 50%; width: 50%; height: 50%; transform: translate(-50%, -50%); } .star { border-radius: 50%; background-color: rgba(255, 255, 255, 0.7); position: absolute; box-shadow: 0px 0px 2px 1px rgba(255, 255, 255, .5); } .shine { animation: shine infinite alternate; } @keyframes shine { from { box-shadow: 0px 0px 2px 1px rgba(255, 255, 255, .5); } to { box-shadow: 0px 0px 5px 10px rgba(255, 255, 255, .5); } }
Вместо обычных элементов, можно так же работать и с элементами svg с настроенной анимацией, возможно даже лучше будет.

Ответ 2



Приблизил к оригиналу насколько смог. Собственно, что делают звезды на небе? Ну, максимум, пульсируют или исчезают на время. Применив одну и ту же анимацию с разной длительностью получаем довольно реалистичный эффект. Размер звезд от одного до пяти пикселей, но с вероятностью в десять процентов мы генерируем звезду размеров giant - их в десять раз меньше и они немного больше остальных. В #root>div можно раскоментировать blur для большей реалистичности, но все будет лагать. Желательно развернуть на всю страницу. const params = { amount: 200, size: { min: 1, max: 5, giant: 9 }, duration: { min: 5, max: 25, } } const randomBetween = (a, b) => { return (a + (Math.random() * (b - a))); } for (let i = 0; i < params.amount; i++) { let star = $("
"); let size = Math.round(Math.random() * 10) === 0 ? params.size.giant : randomBetween(params.size.min, params.size.max); star.css({ "width": size + "px", "height": size + "px", "left": randomBetween(0, 100) + "%", "top": randomBetween(0, 100) + "%", "box-shadow": "0 0 " + size + "px " + size / 2 + "px #043668", "animation-duration": randomBetween(params.duration.min, params.duration.max) + "s" }); $("#root").append(star); } body, html { margin: 0; width: 100%; height: 100%; background: radial-gradient(ellipse at center, rgba(8, 25, 42, 1) 19%, rgba(1, 4, 6, 1) 100%); } #root { position: absolute; width: 100%; height: 100%; overflow: hidden; } #root>div { position: absolute; background: radial-gradient(ellipse at center, rgba(177, 198, 219, 1) 2%, rgba(5, 63, 118, 1) 100%); border-radius: 100%; /* filter:blur(1px); */ animation: shine infinite alternate; } @keyframes shine { 0% { transform: scale(1); opacity: 1; } 20% { transform: scale(.9); opacity: .8; } 40% { transform: scale(1); opacity: .9; } 40% { transform: scale(.2); opacity: .2; } 60% { transform: scale(.2); opacity: .1; } 80% { transform: scale(.5); opacity: .5; } 100% { transform: scale(.9); opacity: .9; } }


Ответ 3



Мои 5 копеек на WebGL =) Чтобы использовать это в реальной жизни, нужно как минимум еще математический шум заменить на текстуру. Seed для шума можно поменять вот в этой строчке #define r(x) fract(1e4*sin((x) * 541.121)) и расположение звезд изменится Вариант попроще, тут меньше итераций цикла в шейдере, меньше звезд и тормозов.

Как сделать выборочную / отложенную загрузку js, css и изображений?

#javascript #html #dom #оптимизация_сайтов


Какими способами и инструментами можно оптимизировать загрузку мобильных версий сайта
применительно к адаптивному веб-дизайну? Иногда необходимо переделывать фронтэнд без
возможности изменений серверной стороны, поэтому ищу лучшее решение с учетом этого момента.

Ситуация 1. Есть 2 js и 2 css файла. Как можно сделать, чтобы грузился только js
#1 и css #1, в зависимости от screen.width например?

Ситуация 2. В dom есть элементы с классом .only-desktop, в которых находятся изображения.
Какой наиболее быстрый и правильный способ предотвратить загрузку изображений в .only-desktop?
    


Ответы

Ответ 1



Здесь официальное руководство от google, с примерами. Для начала воспользуйтесь одним из готовых решений, примеры прилагаются. HeadJs, пожалуй, проще всего. Сложные правила для media queries становятся сильно проще, если использовать какой-либо препроцессор стилей и миксины Пример для раздельных Javascript с помощью enquire: Этот пример подразумевает, что вы используете require или webpack, поддерживающие сборку догружаемых модулей. Конечно, вы можете использовать любой доступный способ инжекции скриптов и ресурсов. Тем же способом можно подгрузить enquire, или любую другую из вышеперечисленных библиотек из cdn, не меняя серверную часть. Согласно этому исследованию, самым эффективным путём запрета загрузки изображений является каскадная перезапись свойства посредством @media queries

Ответ 2



Это похоже на какую-то преждевременную оптимизацию. Если у вас действительно такой большой сервис, то тогда проще генерировать макеты под девайсы на серверной стороне, как это делает например apple. Подгружать css в зависимости от разрешения, можно указав атрибут media в теге link Для JavaScript можно использовать такой хак Вы писали про modernizr.js, посмотрите на yepnopejs с помощью него, вы сможете загружать необходимые вам стили и js файлы в зависимости от условий. Чтобы изображения не загружались сразу, используйте атрибут fake-src и туда пишите url для фото, потом с помощью JS подставлять url изображения из fake-src в src.

Ответ 3



Вы можете выставить media queries для загрузки файлов в зависимости от разрешения экрана (Ситуация 1) или для загрузки классов внутри файла стилей (Ситуация 2). Или я не правильно понял ваш вопрос?

Ответ 4



добавляейте атрибуты async или defer в зависимости от того что нужно

Как создавать перегруженные методы/функции в сервисе для репозитория

#c_sharp #net #проектирование


Предположим имеется следующий класс:

public class User
{
    public string FirstName {get;set;}
    public string LastName {get;set;}
    public bool Gender {get;set;}
    public int Age {get;set;}
}

public UserService
{
    readonly IRepository _userRepository;

    public UserService(IRepository userRepository)
    {
        _userRepository = userRepository;
    }

    //Функция возвращающая всех пользователей
    public IEnumerable GetUsers()
    {
        return _userRepository.Table.ToList();
    }
}


Предположим мне необходимо наложить некие ограничения на возвращаемых пользователей,
пусть будет возраст и пол, тогда я создам такую функцию:

public IEnumerable GetUsers(int age, bool gender)
{
    return _userRepository.Table
        .Where(x=>x.Age==age&&x.Gender==gender)
        .ToList();
}


А если понадобится фильтровать по какому либо другому набору полей, не создавать
же 100500 таких методов/функций, ведь они могут с собой и пересекаться и тогда явно
будет дублирование кода.

Данные User, UserService приведены для примера, все совпадения с действительностью
не специальны.

Хочется узнать как необходимо создавать перегруженные методы/функции.
    


Ответы

Ответ 1



Это тот момент, когда стоит задуматься, какие у вас абстракции и почему. Как у вас хранятся данные на самом деле? Положим, на самом деле вы работаете с голым списком прямо в памяти. В этом случае достаточно принимать Func filter и передавать его в Enumerable.Where как есть. Положим, на самом деле вы работаете с базой данных. В этом случае вы можете принимать Expression> filter и передавать его в Queryable.Where как есть. Положим, на самом деле вы работаете с веб-сервисом. В этом случае вы можете принимать список IDictionary с именами свойств и значениями, передавать его сервису, сервис может строить или компилировать соответствующее выражение (в зависимости от того, что в нём на самом деле: вариант 1 или 2). Если требуются более сложные условия, чем проверка на равенство, нужно смотреть, фильтры какой сложности требуется поддерживать, и искать компромиссы. Возможно, сейчас я услышу возражения: "Но мне же нужно супер-универсальное сверх-модульное архи-заменяемое решение!" Нет, оно вам не нужно. YAGNI! Вы никогда не скроете факта, что все три варианта работают с совершенно разной скоростью, имеют разные ограничения и так далее. Нет никакого "общего случая", это миф. Поэтому не изобретайте сложности там, где они вам не нужны. А они вам не нужны практически никогда. Скажите, зачем вам понадобился "сервис", если уже есть "репозиторий"? Вам действительно нужен лишний слой абстракций?

Ответ 2



А если понадобится фильтровать по какому либо другому набору полей, не создавать же 100500 таких методов/функций, ведь они могут с собой и пересекаться и тогда явно будет дублирование кода. Отложенное выполнение - то что вам надо. Если сделать вот так, то всегда можно сделать отложенный расчет логики. public IQueryable GetUsers() { return _userRepository.Table.AsQueryable(); } Стоит учитывать, что иногда для запроса GetUsers().Where(u => u.Age > 20) можно спокойно вызывать Sum\Count\Show, а иногда лучше явно материализовать запрос (добавить .ToList()), чтобы не дергать базу несколько раз. Для частых кейсов всегда можно завернуть в функцию: public static IQueryable GetActiveUsers() { return GetUsers().Where(u => u.IsActive); } либо просто фильтр: public static IQueryable WhereUsersActive(IQueryable users) { return users.Where(u => u.IsActive); } можно ещё экстеншном, если хочется: public static IQueryable WhereUsersActive(this IQueryable users) { return users.Where(u => u.IsActive); }

Ответ 3



Репозиторий и сервис не нужны. Вы не должны пытаться заранее определить, какие запросы к данным вам понадобятся, да это и не получится. Тысяча функций на все случаи жизни в репозитории — чистый дубляж кода, они обычно не несут особого смысла. IEnumerable или IQueryable — достаточно мощная абстракция. Вы сможете (относительно) легко поменять базу данных. (Проблемы «протекающих абстракций» всё равно останутся — например, если новая база плохо делает какие-нибудь операции.) И вы сможете легко выразить производные операции, отталкиваясь от списка, LINQ вполне подходит для этого. Уточнение: IQueryable — абстракция уровня модели. То, что необходимо выставлять UI-уровню из VM, это не IQueryable<Т>, а коллекция VM-объектов (для вашего случая — UserVM). Скорее всего, вам необходимо будет при переходе к VM-объектам ограничить (пользователю никогда не хочется видеть миллион юзеров, он столько в голове не удержит) и материализовать список сущностей, а не выставлять голый queryable.Select(user => new UserVM(user)), иначе каждый чих в UI будет дёргать базу.

Ответ 4



Ответ на самом деле зависит от того, что подразумевается под "сервисом". Если под сервисом подразумевается что-то, что будет вызываться изнутри бизнес логики - то да, в этом виде он абсолютно излишен. Единственный плюс в таком "сервисе" - он, возможно, чуть-чуть облегчает юнит-тестирование, ценой отказа от IQueryable. Но если под сервисом подразумевается фасад BL-уровня, т.е. вызываться методы этого сервиса будут из UI/Presentation, то сервис в таком виде должен существовать: он прячет IQueryable от Presentation, не давая бизнес-логике выползти в код UI. он должнен, по возможности преобразовывать модели BL в Local DTO - модели, отвязанные от базы, и пригодные для представления. он должен очерчивать время жизни бизнес-операций (контролировать время жизни контекста / unit of work) - этому сейчас мешает лишний Generic Repository. он должен контролировать fetch plan - не давать бизнес-логике уйти в n+1. Предложения выбросить фасад (сервис) в таком случае - это, практически, предложение делать запросы в базу напрямую из UI, что является чистейшим злом :) Посмотрите официальный гайд Microsoft Application Architecture Guide, раздел Business Layer Guidelines. Паттерн, который вы пытаетесь реализовать сервисом, называется Application Façade, его предназначение Centralize and aggregate behavior to provide a uniform service layer. Т.е. он делает именно то, что делает ваш сервис - прячет от UI особенности работы бизнес-логики. Он прячет сам факт существования базы, возможности фильтровать пользователей, особенности выборки - и оставляет тупой интерфейс для UI - отдать параметры, получить пользователей. И в таком случае - ответ на вопрос "как создавать методы" - достаточно очевиден: Интерфейс фасада должен соответствовать потребностям вызывающего его кода UI. А не следовать возможностям фильтрации или каким-то особенностям бизнес операций. Если UI нужно выбрать пользователя по последней букве фамилии - у вас в фасаде должен быть метод "ВыбратьПоПоследнейБуквеФамилии". Если UI не нужен метод "получить всех пользователей" - то и в фасаде его быть не должно.

Ответ 5



Можно вынести параметр делегата фильтрации из Where в параметр функции как то так: public IEnumerable GetUsers(Func filter) { return _userRepository.Table .Where(filter) .ToList(); } и использовать как var users = GetUsers(x=>x.Age==age&&x.Gender==gender); P.S. Если в целом Руководство по C# --- Перегрузка методов

Ответ 6



Возвращать "голые" IEnumerable<> или IQueryable<> "не есть хорошо", поскольку вы сливаете потребителю вашего класса всё и пусть он сам разбирается с этим. Этим вы нарушаете разделение на слои вашего приложения, поскольку в этом случае возвращаемое вами значение может быть проброшено далеко вверх по слоям. Но, как всегда для этого есть решение. Называется "Спецификация": https://en.wikipedia.org/wiki/Specification_pattern Придуман данный шаблон Эриком Эвансом и подробно описан в его книге. Вот ещё пример реализации: http://www.codeproject.com/Articles/670115/Specification-pattern-in-Csharp

Как создать диалог, который закрывается при нажатии Esc?

#c_sharp #winforms


Как создать форму/диалог в WinForms, который закрывается при нажатии Esc, независимо
от того в каком из контролов находится фокус? И как вернуть данные из диалога?
    


Ответы

Ответ 1



В том редком случае, если на форме нет кнопок вообще - что, на мой взгляд, редкость для диалога, вам стоит воспользоваться решением из соседних ответов. Если на форме есть как минимум одна кнопка, её закрывающая, то стоит использовать стандартный механизм, описанный ниже. Гораздо более простой способ сделать кнопку, реагирующую на Esc - это задать свойство Form.CancelButton. Достаточно лишь бросить кнопку с надписью "Отмена" на форму, открыть свойства формы, и выбрать кнопку в списке CancelButton: После этого эта кнопка будет нажиматься по Esc вне зависимости от текущего активного контрола. Это действие так же автоматически задаст DialogResult = DialogResult.Cancel в свойствах кнопки, что вызовет закрытие формы по нажатию либо на Esc, либо напрямую на кнопку. Подробно эта тема, как и связанные с ней, рассмотрена в MSDN: Практическое руководство. Создание кнопки "Отмена" в Windows Forms Соответствующее свойство для кнопки по умолчанию - Form.AcceptButton - задает точно такое же поведение для Enter. В отличие от CancelButton, задание AcceptButton в дизайнере не выставляет DialogResult у выбранной кнопки, так что при необходимости автоматического закрытия по Enter придется задать это свойство вручуню. Что делать, если на диалоге нет кнопки Cancel? например, диалог вообще не подразумевает отмены действия. Т.к. на диалоге (по крайней мере на диалоговых окнах WinForms, которые обсуждаются в этом вопросе) есть хотя бы одна кнопка, то ее и стоит выбрать и как AcceptButton, и как CancelButton, обеспечив ее срабатывание и по Enter, и по Esc.

Ответ 2



По умолчанию, форма, если содержит хотя бы один дочерний контрол, игнорирует обработку клавиш, даже если вы подписались на соответствующие события. Это поведение можно поменять изменив свойство формы KeyPreview = true (по умолчанию false). После этого события формы будут срабатывать на нажатия клавиш и вызывать соответствующие обработчики. Рабочий пример. В конструкторе для проверки можно накидать на форму произвольных контролов и поиграть со значением указанного свойства. Для вызова в режиме диалога все тоже самое, но добавить присваивание значения свойству DialogResult. public partial class Form1 : Form { public Form1() { InitializeComponent(); this.KeyPreview = true; this.KeyDown += Form1_KeyDown; } private void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyData == Keys.Escape) { ((Form1)sender).Close(); } } }

Ответ 3



Например, надо создать диалог, который возвращает DialogResult.Cancel, если нажали Esc или кнопку закрытия окна; DialogResult.OK и значение ключа, если нажали Enter в поле ввода. Для перехвата нажатий можно использовать KeyPreview, но он работает не всегда. Пример в конце ответа. Поэтому лучше переопределить метод ProcessCmdKey. using System.Windows.Forms; class Dialog : Form { public int Key { get; private set; } public Dialog() { var tb = new TextBox() { Parent = this }; tb.KeyDown += (s, e) => { if (e.KeyCode == Keys.Enter && tb.Text.Contains("1")) { this.Key = DateTime.Now.Millisecond; this.DialogResult = DialogResult.OK; this.Close(); } }; } protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { var ret = base.ProcessCmdKey(ref msg, keyData); if (keyData == Keys.Escape) { this.DialogResult = DialogResult.Cancel; this.Close(); ret = true; } return ret; } } Использовать диалог можно так var d = new Dialog(); if(d.ShowDialog() == DialogResult.OK) Console.WriteLine(d.Key); // вывести значение ключа KeyPreview не всегда подходит. Например, после открытия формы первое нажатие Key.Left не перехватывается. public partial class Form1 : Form { public Form1() { var t = new TextBox() { Parent = this }; var l = new Label() { Parent = this }; this.KeyPreview = true; this.KeyDown += Form1_KeyDown; this.Shown += (s, e) => l.Focus(); } private void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyData == Keys.Left) { ((Form1)sender).Close(); } } } Дополнение 4: Для того, чтобы получить информацию о Windows окнах (windows styles, class name, windows rect и т.д.), можно использовать HWndSpy - исходный код тут. У всплывающих окон, диалогов, контекстных меню и т.д., в значении Windows Styles указывается WS_POPUP. Дополнение 3: Диалоговое окно или диалог - это окно для вывода информации и (или) получения ответа от пользователя. Меню или контекстное меню - это окно, которое не содержит кнопки OK и/или Cancel и закрывается при нажатии Esc. Дополнение 2: Форма/диалог/всплывающее окно, далее диалог - это окно с определенным поведением. Дополнение 1: Не во всех диалогах есть кнопки. Например, если нажать Win+S в Windows 10, то откроется диалог, в котором нет кнопок OK и Cancel.

Как нарисовать простую шахматную доску?

#javascript #html #css


Как нарисовать простую шахматную доску с помощью html/css и javascript?
    


Ответы

Ответ 1



Простой пример. var chessWrap = document.querySelector('.ch-wrap'); var i = 0, count = 0; while (count < 8 * 8) { var item = document.createElement('div'); chessWrap.appendChild(item); item.classList.add('ch-item'); if (i && i % 2) item.classList.add('ch-black') i += ((i + 2) % 9) ? 1 : 2; count++; } .ch-wrap { width: 400px; height: 400px; border: 1px solid #111; } .ch-item { width: 50px; height: 50px; float: left; } .ch-black { background: #111; }


Ответ 2



Проверено в Chrome 54 и Firefox 50. А вообще: http://caniuse.com/#feat=css-mixblendmode http://caniuse.com/#feat=css-repeating-gradients html { background: white; display: flex; } body { width: 100vmin; height: 100vmin; margin: auto; border: 1px solid red; box-sizing: border-box; background: repeating-linear-gradient(90deg, white, white 12.5%, black 12.5%, black 25%); } div { height: 100%; width: 100%; background: repeating-linear-gradient(0deg, black, black 12.5%, white 12.5%, white 25%); mix-blend-mode: difference; }


Ответ 3



function shahmatLine(number){ let summ = ''; if(number % 2 == 0){ for(let k=0; k<8; k++){ summ = summ + " " + "#"; } } else{ for(let k=0; k<8; k++){ summ = summ + "#" + " "; } } return summ; } function Shahmat(lineCount) { for(let i = 0; i < lineCount; i++){ console.log(shahmatLine(i)); } }

Чем опасна авторизация на форумах через учетную запись социальных сетей?

#веб_программирование #авторизация #vkontakte_api #facebook_api


Доброго времени суток!
Я не собираюсь заниматься разработкой %сабж%. Мне интересен сам принцип, который
заложен в авторизации пользователя на различных форумах (в том числе сомнительного
происхождения) при помощи новых "модных" возможностей, используя красивые кнопки, на
подобие: "ВКонтакте", "Фэйсбук" и прочих соц.сетей.

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


PS: Будет полезно, если будут прямые ссылки на техническую документацию или описание
данной возможности авторизации к вашим ответам/комментариям.
Сильно умно не пишите, не силен я в web разработке и всяких там систем авторизаций...Мне
бы как-нибудь по-простому :-)

Очередной раз заранее вас благодарю за ваши ответы.    


Ответы

Ответ 1



По-простому: форум доверяет ВКонтакту (кто же не знает ВК!). Приходит на форум юзер, говорит, «Я Вася из ВК», форум сам напрямую бежит к ВК и уточняет, «ВК, это точно Вася?», ВК подтверждает, «да, это Вася из ВК». При этом про Васю ВК лишней инф-ии не раскрывает. Даже email не даёт - только имя-фамилию, id и ссылку на картинку с физиономией. Другие соц. сети, или, например, Google, светят email человека. В таком варианте злоупотреблений быть не может. Чтобы форум мог нагадить человеку, нужно дополнительно запросить каких-то прав, разрешений, установить приложение и т.п. ВК не дурак, и об этом подробно напишет: "Приложение такое-то запрашивает доступ к вашим ключам от квартиры и кошельку - дать?". От дурака особо не защитить, конечно, но если люди голову не выключали, то злоупотреблений не произойдёт.

Ответ 2



Ну обычно схемы работают достаточно просто - форум запрашивает у сервера соц сети форму авторизации (редирект с токеном), пользователь авторизуется у на сервере соц сети, соц сеть отдаёт новый токен форуму. По этому токену он может спросить у сервера соц сети авторизован ли пользователь, его имя ну и прочиее данные которые разрешены пользователем соц сети. общая схема примерно такая. Возможности использовать в корыстных целях нету, только если есть бреши у соц сети. На уровне апи такой возможности естественно не предусматривают.

Олимпиадная задача с повышенной сложностью

#cpp


Салют всем чайникам и гуру, девелоперам и фрилансерам, прогерам и кодерам! Но речь
не о классификации и иерархии нашего брата. Речь о олимпиадной задачи, которую я уже
неделю не могу решить. Я точно знаю: решение что-то простое и гениальное - но вот под
каким камнем оно спряталось? Так что, суровые хэшкод-юзеры, прошу у вас помощь в решение
этой задачи!
Задача:
Язык программирования: С++.
В программе должна быть 1 единственная функция вывода информации, которая может только
писать, т.е. не может удалять текст, а только вставлять новый. При этом она работает
следующий образом
Исполняемый код:
func( "1" );


Вывод:
(1)
[1]


Исполняемый код:
func( "1" );
func( "2" );


Вывод
(1)
(2)
[2]
[1]


Испоняемый код:
func( "1" );
func( "2" );
func( "qwer" );


Вывод
(1)
(2)
(qwer)
[qwer]
[2]
[1]


Я уверен, что задача решается легко, но у меня нет других вариантов, кроме как все
же буферизовать хвост, изменять его, и заменять старый хвост на новый. Но тогда приходится
использовать удаление символов.
P.S. задача не совсем олимпиадная, эта задачка была давно в какой-то мощной статье
по альтернативному программирование где рассматривалось несколько примеров, но вот
код реализации такой задачи не помню. И статью ту тоже не могу найти. У самого без
удаление символов написать не получается.    


Ответы

Ответ 1



Испоняемый код: func( "1" ); func( "2" ); func( "qwer" ); Вывод (1) (2) (qwer) [qwer] [2] [1] то есть нужно напечатать в обычном и обратном порядке ???? как я понял можно только вызывать одну и ту же функцию... (если да то решение ниже) делаем класс func и в нём храним std::vector делаем конструктор func(string) с записью дубля в вектор и выводом на экран в деструкторе выводим вектор в обратном порядке UPD:: ну ещё будет "красиво" перегрузить "operator()" дабы не портить конструкторы

Ответ 2



Ещё один вариант, без глобального списка, но с макросами: #include class StringPrinter { const char* content; public: StringPrinter(const char* s) : content(s) { std::cout << '(' << content << ')' << std::endl; } ~StringPrinter() { std::cout << '[' << content << ']' << std::endl; } }; #define func(S) StringPrinter PASTE1(stringPrinterInstance, __LINE__) (S) #define PASTE1(T1, T2) PASTE2(T1, T2) #define PASTE2(T1, T2) T1 ## T2 int main() { func("1"); func("2"); func("3"); func("whatever"); }

Ответ 3



Внесу свои 5 копеек на Си. Правда не уверен, что формально этот код отвечает условиям задачи (это я насчет одной функции в программе). По сути же, изображено тоже самое, что ранее показано с классом и его деструктором в С++. Из main() вызывается только одна функция и никаких "левых" параметров ей не передается. #include #include #include struct list { struct list *next; char *text; }; static struct list *list = 0; static void rfunc() { struct list *p = list; while (p) { printf ("[%s]\n",p->text); p = p->next; } } func (char *s) { printf ("(%s)\n",s); if (!list) atexit(rfunc); struct list *p = malloc(sizeof(*p)); p->next = list; p->text = s ? strdup(s) : NULL; list = p; } int main (int ac, char *av[]) { while (ac--) func(av[ac]); } Ничто не упрятано, так сказать, все секреты наружу.

Ответ 4



Очевидно же. Создаем в функции статический объект, который накапливает строки. По завершении работы программы объект разрушается, и в его деструкторе можно вывести строки в нужном порядке: #include #include #include class Collector { public: void push(const std::string& s) { data_.push_back(s); } ~Collector() { for (const auto& s: data_) { std::cout << "(" << s << ")" << std::endl; } std::reverse(data_.begin(), data_.end()); for (const auto& s: data_) { std::cout << "[" << s << "]" << std::endl; } } private: std::vector data_; }; void func(const std::string& s) { static Collector collector; collector.push(s); } int main() { func("1"); func("2"); func("qwer"); } http://ideone.com/njet2N