Страницы

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

суббота, 6 октября 2018 г.

В чём разница между İnterface и Abstract класс

Раньше interface не имел реализации и нам приходилось реализовывать абстрактные классы. Но сейчас, а конкретно, начиная с 'Java8', interface может иметь реализацию. Зачем так поступили? В чём здесь выигрыш? Какие преимущества дает интерфейс, имеющий реализацию? И главное, в чем тогда смысл использования абстрактных классов, если интерфейс может содержать реализацию методов?


Ответ

Интерфейс описывает только поведение (методы) и не может иметь состояние (поля), абстрактный класс - может.
В случае с default-методами, поведение может быть не только описано, но и реализовано. Однако по-прежнему без доступа к состоянию.
В Java 8 default-методы были добавлены во многом ради Stream API. Это позволило добавить методы spliterator() и stream() всем коллекциям, которые были написаны до появления Stream API, не затрагивая их реализации:
public interface Iterable // ...
default Spliterator spliterator() { return Spliterators.spliteratorUnknownSize(iterator(), 0); } }
public interface Collection extends Iterable { // ...
@Override default Spliterator spliterator() { return Spliterators.spliterator(this, 0); }
default Stream stream() { return StreamSupport.stream(spliterator(), false); } }
Как видите, default-методы тут ведут себя как миксины, оборачивающие некоторую стороннюю реализацию (Spliterators, StreamSupport) и превращающую ее в честные методы коллекций.

Пример из жизни. Есть интерфейс доступа к данным, который может иметь разные реализации:
public interface Repository { Foo getFooWithTimeout(int id, int timeout); // ... }
И хочется иметь его сокращенную версию какого-то метода со значениями параметров по-умолчанию. Тогда достаточно просто обернуть существующий метод default-методом:
public interface Repository { Foo getFooWithTimeout(int id, int timeout);
default Foo getFoo(int id) { return getFooWithTimeout(id, 0); } // ... }
Мы расширили контракт всех реализаций интерфейса Repository новым методом, при этом никто не пострадал нам не пришлось вторгаться в реализации.

Конструктор класса File не создает файл на диске

Пытаюсь создать новый файл по примеру из книги, но он не создается. Подобных примеров с использованием конструктора
File f = new File("E://test.txt"); в интернете много, но почему-то у меня на JDK 8 оно не работает.
public class Main { public static void main(String[] args) throws IOException{ File f = new File ("E://Workspace//create4.txt");
System.out.println("File name : "+ f.getName()); System.out.println("Parent: " + f.getParent()); System.out.println(f.exists() ? "exists" : "does not exist"); } }
В итоге, вот, что получается:
File name : create4.txt Parent: E:\Workspace does not exist
Файла - нет. Знаю, что если набрать в try f.createNewFile(); то все будет ок, но раз приводят примеры без него, то значит должно работать.


Ответ

Конструктор класса java.io.File создаёт объект, представляющий файл на диске. Но конструктор не создаёт этот файл, а предоставляет некоторый интерфейс, который затем позволяет что-либо сделать. Например, проверить существует ли файл. Проще говоря, объект класса File после создания представляет собой только имя файла, независимо от его физического существования на диске.
Как верно замечено в вопросе, чтобы создать файл нужно вызвать метод createNewFile. Или же передавать объект типа File каким-либо функциям для дальнейшей работы. Но ещё раз повторю, что конструктор сам никаких новых файлов на диске не создаёт.

Почему оператор << для ostream не перегружен для контейнеров?

Почему оператор << для ostream не перегружен для контейнеров, таких как vector, set, map?
И если есть проблемы с перегрузкой оператора << для ostream, то почему бы не добавить функцию print или print_container, которая бы могла выводить контейнеры.
Спрашиваю больше из-за любопытства и из-за того, что такую мелочь приходится реализовывать самому. Притом, что во многих других языках выводить контейнеры не составляет труда.


Ответ

Скажите, как правильно выводить vector - через запятую? с фиксированной шириной поля? Может, все брать в скобки?
А vector - строки нужно брать в кавычки? или нет?
А list - с какой именно точностью и в каком формате выводить?
Заметим, это вы решаете не для себя, а для всех программистов на C++...
Вы готовы к таким holy wars?
А написать свой вывод - секундное же дело. Ну, в крайнем случае напишите copy(c.begin(),c.end(),ostream_iterator(cout,",")) :-)
"По-моему, так" (с) Пух

C++ разница между массивами

Есть два массива:
char *str char* str[]
По своему принципу, это просто одномерный массив, но при этом, я не могу добавить никаких значений во второй. Вопрос: какая между ними тогда разница? Зачем объявлять их именно в таком виде и какой от этого плюс?
Update


Ответ

char* str[] (с пустыми квадратными скобками) — при использовании в качестве аргумента функции при её объявлении это то же самое, что и char **str.
Как это дело трактовать — зависит исключительно от логики кода:
Это может быть указатель на массив указателей (тогда можно сделать что-то наподобие char *foo = str[16];). Причём элементы массива могут указывать как на начало нуль-терминированных строк, так и на отдельные символы, хранящиеся где-то в другом месте. Это может быть просто указатель на char*-переменную, позволяющий модифицировать саму эту переменную отовсюду, куда мы передали этот указатель. Это может быть двумерный массив типа char. Такой массив называется jagged и, в отличие от традиционного, позволяет хранить разное количество элементов в каждой строке (если первый индекс обозначает номер строки) или столбце (если первый индекс обозначает номер столбца) char* str[N] (с некой константой в скобках) — это уже полноценный массив фиксированной длины, хранящий в себе N элементов типа char *
Однако в данном случае есть три важных момента:
Это работает только при объявлении переменных. Если вы попытаетесь указать подобную конструкцию в качестве аргумента функции при её объявлении, содержимое квадратных скобок будет проигнорировано, и вы получите первый случай. Если вы совмещаете объявление массива с его заполнением (char* str = {...}), константу N можно опустить, тогда её значение будет вычислено автоматически. В C++ значение N должно быть именно константой, в противном случае вы получите ошибку компиляции. Массивы переменной длины разрешены только в Си не ранее C99.

Мобильная версия сайта

Здравствуйте. Хотел задать такой вопрос. У меня есть сайт который прекрасно работает на всех 4-х браузерах (включая IEv6 :)). Теперь хочу сделать мобильную версию сайта. Скажите, что нужно знать для верстки сайта для мобильных телефонов, какие могут быть "подводные камни". К примеру, я заметил что OperaMini не отображает таблицы правильно, а показывает все одной строкой. Хотел бы услышать такие особенности, как Cookies, JavaScript, минимальное разрешение экрана, CSS3 и остальные важные отличия от их стандартных версий. В общем все, что нужно учесть при переходе на мини-версию сайта.


Ответ

Почитать можно тут и тут. О, чуть не забыл, еще тут почитайте.

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

или(предпочтительнее использовать первый вариант)

"/css/handheld.css" - путь к таблице стилей для моб. устройств; media="handheld" - указание браузеру, что данный ресурс следует использовать только в случае просмотра веб-страницы с помощью устройств у которых маленькое расширение экрана. Рекомендую еще создать CSS файлик для принтеров(значение "print" атрибута "media"). Можно почитать подробно на htmlbook
Как правильно подключать данный стиль. Если на странице есть стили для всех устройств (со значением "all" атрибута "media", прошу заметить что оно устанавливается по-умолчанию), то:
Создаем файл "reset.css". Он должен обнулять свойства всех нужных нам селекторов. После подключение/объявление всех стилей в шапке странице(тег head) подключаем файл "reset.css". При подключении не забываем указать тип устройств, для которых данная каскадная таблица стилей будет отображаться, - "handheld". Подключаем стили для мобильных устройств.
Если же все стили на станице четко распределены по типам носителей(устройств, что отображают страницу), то файл "reset.css" подключать не нужно. Нежданно-негадано проблема может возникнуть из-за так называемых внутренних стилей. Подогнать их под разные девайсы относительно затруднительно(но возможно, к примеру с помощью JS), поэтому рекомендую вынести их в соответствующие файлы стилей.

Рекомендации при верстке под handheld:
Не верстайте с помощью WML. Он безнадежно устарел и вместо него используется XHTML/CSS, по крайней мере на момент написания этого ответа. Из-за того, что свойства float, clip, overflow, both не пашут на большинстве мобильных телефонов, придется ограничиться использованием элементов с абсолютным позиционированием(position: absolute;). Так же избегайте блоков fixed. Насчет relative ничего написать не могу. Сокращенные свойства типа: "margin: 10px 20px 30px 40px;" придется разбить на более простые: "margin-top: 10px; margin-right: 20px; margin-bottom: 30px; margin-left: 40px;". Табличная верстка крайне нежелательна. Она плохо обрабатывается устройствами подобного вида. Запрещены вложенные таблицы и даже не работают атрибуты "cellpadding" и "cellspacing". Cookie чаще всего адекватно устанавливаются и считываются, причем в даже в старых телефонах. Импортировать внешние шрифты запрещено. CSS3 юзать рано, его поддержка почти отсутствует. Flash контент или заменять на аналогичный не флеш или прятать. Причиной тому является его проблемное отображение на моб. устройствах и сомнения в дальнейшей поддержке. Использовать JS для формирования дизайна страницы по-минимуму. Речь идет не про динамическую составляющую страницы. Постараюсь продемонстрировать на примере: Некоторый верстальщик создал страничку, после тестов увидел, что один из блоков не на своем месте. Нескольких минут борьбы с CSS и верстальщик понимает, что где-то стиль проблемного блока перекрывается из-за чего все его старания решить проблему безрезультатны. Вместо того, что бы искать проблемное определение ему приходит в голову "гениальная" идея пофиксить положение блока javascript-ом, выполнив его после загрузки страницы. На таких костылях страничка была добавлена на сайт и опубликована. Минутой позже страничку просматривает некоторый пользователь с использованием ПК. Элементы сайта отображаются нормально, пользователь счастлив. Еще через минуту с мобильного телефона заходит на только что опубликованную страницу другой пользователь, телефон не самый новый и JS у него не пашет, именно поэтому проблемный блок коварно меняет свою позицию превращая великолепнейший дизайн в кашу. Пример не очень удачный, но суть отображает.

Получить доступ к папке

Нужно получить права на чтение и запись залоченого фолдера.
Или как сделать следующий код валидным:
DirectoryInfo dir = new DirectoryInfo(@"D:/System Volume Information");
foreach (var item in dir.GetDirectories()) { Console.WriteLine(item.FullName); }
Желательно что бы работало с System Volume Information
Следующий код не работает тоже:
[Flags] enum MoveFileFlags { MOVEFILE_REPLACE_EXISTING = 0x00000001, MOVEFILE_COPY_ALLOWED = 0x00000002, MOVEFILE_DELAY_UNTIL_REBOOT = 0x00000004, MOVEFILE_WRITE_THROUGH = 0x00000008, MOVEFILE_CREATE_HARDLINK = 0x00000010, MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x00000020 }
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, MoveFileFlags dwFlags);
static void Main(string[] args) { string path = @"D:/System Volume Information";
DirectoryInfo dir = new DirectoryInfo(path);
MoveFileEx(path, path + "2", MoveFileFlags.MOVEFILE_REPLACE_EXISTING);
string msg = new Win32Exception(Marshal.GetLastWin32Error()).Message;
Console.WriteLine(msg); }


Ответ

Ага, я нашёл, как Far это делает.
Он не просто запускает процесс от имени администратора (на самом деле, дочерний процесс, с которым связывается через pipe). Этот самый дочерний процесс, будучи запущенным от имени администратора, имеет право затребовать себе привилегии Backup и Restore (вот официальный метод, как сделать такое на чистом WinAPI). Что он и делает. Имея эти привилегии, дочерний процесс может делать всё
Мораль: вы можете ограничить в правах административный процесс, но он может снять ваши ограничения.

Для читателей, вот работающий код: (разумеется, вы должны добавить манифест, как указано в ответе @Dmitry)
class Program { static public void Main() { using (var outf = File.CreateText(@"D:\dirlist.txt")) { if (!RequestSeBackupPrivilege()) { outf.WriteLine("Cannot request privilege: "); return; } try { string path = @"D:\System Volume Information"; var dir = new DirectoryInfo(path); foreach (var item in dir.GetFileSystemInfos()) outf.WriteLine(item.FullName); } catch (Exception ex) { outf.WriteLine("Exception:"); outf.Write(ex); } } }
static bool RequestSeBackupPrivilege() { LUID luid;
if (!LookupPrivilegeValue(null, "SeBackupPrivilege", out luid)) return false;
TOKEN_PRIVILEGES_SINGLE tp = new TOKEN_PRIVILEGES_SINGLE { PrivilegeCount = 1, Luid = luid, Attributes = SE_PRIVILEGE_ENABLED };
IntPtr hToken; return OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out hToken) && AdjustTokenPrivileges( hToken, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero) && (Marshal.GetLastWin32Error() != ERROR_NOT_ALL_ASSIGNED); }
const int SE_PRIVILEGE_ENABLED = 0x00000002; const int TOKEN_QUERY = 0x00000008; const int TOKEN_ADJUST_PRIVILEGES = 0x00000020; const int ERROR_NOT_ALL_ASSIGNED = 1300;
[DllImport("kernel32.dll", ExactSpelling = true)] static extern IntPtr GetCurrentProcess();
[StructLayout(LayoutKind.Sequential)] struct TOKEN_PRIVILEGES_SINGLE { public UInt32 PrivilegeCount; public LUID Luid; public UInt32 Attributes; }
[StructLayout(LayoutKind.Sequential)] struct LUID { public uint LowPart; public int HighPart; }
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool LookupPrivilegeValue( string lpSystemName, string lpName, out LUID lpLuid);
[DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool OpenProcessToken( IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] static extern bool AdjustTokenPrivileges( IntPtr htok, bool disall, ref TOKEN_PRIVILEGES_SINGLE newst, int len, IntPtr prev, IntPtr relen); }
Определения структур данных взяты на pinvoke.net.

Массив функций: можно ли реализовать?

Можно ли в C++ реализовать массив функций? То есть, в массив можно записать функции a(), b() и c() (не сами функции, а операторы для их вызова), а затем вызывать их, как будет удобно. Если нет, то можно вызывать ту функцию, которая указана в аргументах?


Ответ

В современном c++ присутствуют удобные средства для оперирования функциями как функциональными объектами. Посмотрите functional, а именно std::function и std::bind. По указанным ссылкам также находятся очень хорошие примеры.
Разумеется в c++ можно работать и с голыми указателями на функции (свободные и функции-члены класса), но это не так удобно и просто. Особенно при построении пользовательского интерфейса.
Пример массива функций. В качестве массива используем стандартный контейнер std::vector. Ниже продемонстрировано как можно для более узкой сигнатуры функции использовать более широкое определение. Известно что вызывающая сторона ожидает сигнатуру void(int), а мы будем ей передавать void(int, int) и void(const std::string&, int, int)
#include // std::cout #include // std::bind #include #include
void a(int x, int y) { std::cout << "a(" << x << ", " << y << ")" << std::endl; } void b(int x, int y) { std::cout << "b(" << x << ", " << y << ")" << std::endl; } void c(const std::string& s, int x, int y) { std::cout << "c(" << s << ", " << x << ", " << y << ")" << std::endl; }
int main () { using namespace std::placeholders; // adds visibility of _1, _2, _3,...
std::vector> functions;
// создаем и помещаем в вектор функциональный объект, во время вызова необходимо передать один аргумент functions.emplace_back(std::bind(a, _1, _1)); functions.emplace_back(std::bind(a, _1, 42)); functions.emplace_back(std::bind(a, _1, 100500)); functions.emplace_back(std::bind(b, _1, 42)); functions.emplace_back(std::bind(b, 42, _1)); functions.emplace_back(std::bind(c, "Hello world!", _1, 3));
int i = 0; for (const auto& fn : functions) { fn(i++); }
return 0; }
Вывод.
a(0, 0) a(1, 42) a(2, 100500) b(3, 42) b(42, 4) c(Hello world!, 5, 3)
Еще один пример (взят с www.cplusplus.com):
// bind example #include // std::cout #include // std::bind
// a function: (also works with function object: std::divides my_divide;) double my_divide (double x, double y) {return x/y;}
struct MyPair { double a,b; double multiply() {return a*b;} };
int main () { using namespace std::placeholders; // adds visibility of _1, _2, _3,...
// binding functions: auto fn_five = std::bind (my_divide,10,2); // returns 10/2 std::cout << fn_five() << '
'; // 5
auto fn_half = std::bind (my_divide,_1,2); // returns x/2 std::cout << fn_half(10) << '
'; // 5
auto fn_invert = std::bind (my_divide,_2,_1); // returns y/x std::cout << fn_invert(10,2) << '
'; // 0.2
auto fn_rounding = std::bind (my_divide,_1,_2); // returns int(x/y) std::cout << fn_rounding(10,3) << '
'; // 3
MyPair ten_two {10,2};
// binding members: auto bound_member_fn = std::bind (&MyPair::multiply,_1); // returns x.multiply() std::cout << bound_member_fn(ten_two) << '
'; // 20
auto bound_member_data = std::bind (&MyPair::a,ten_two); // returns ten_two.a std::cout << bound_member_data() << '
'; // 10
return 0; }

Как починить android.os.NetworkOnMainThreadException

Здравствуйте. Пытаюсь сделать POST запрос на ajax страницу с помощью HttpURLConnection. Сильно не пинайте, я только сегодня начал практиковать Java и Android. Тестю на API 22 (Intel x86). В обычном хроме та же страница нормально загружается. Logcat:
03-24 10:23:26.842 4679-4679/? I/art: Late-enabling -Xcheck:jni 03-24 10:23:27.402 4679-4679/com.gobonus.gobonus D/AndroidRuntime: Shutting down VM 03-24 10:23:27.427 4679-4679/com.gobonus.gobonus E/AndroidRuntime: FATAL EXCEPTION: main Process: com.gobonus.gobonus, PID: 4679 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.gobonus.gobonus/com.gobonus.gobonus.WelcomeActivity}: android.os.NetworkOnMainThreadException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2358) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2420) at android.app.ActivityThread.access$900(ActivityThread.java:154) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5294) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699) Caused by: android.os.NetworkOnMainThreadException at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1147) at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:110) at libcore.io.IoBridge.connectErrno(IoBridge.java:137) at libcore.io.IoBridge.connect(IoBridge.java:122) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:183) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:456) at java.net.Socket.connect(Socket.java:882) at com.android.okhttp.internal.Platform.connectSocket(Platform.java:174) at com.android.okhttp.Connection.connect(Connection.java:152) at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:276) at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:211) at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:382) at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:106) at com.android.okhttp.internal.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:217) at com.gobonus.gobonus.Request.(Request.java:65) at com.gobonus.gobonus.WelcomeActivity.onCreate(WelcomeActivity.java:15) at android.app.Activity.performCreate(Activity.java:5990) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2311) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2420) at android.app.ActivityThread.access$900(ActivityThread.java:154) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5294) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904) at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)  03-24 10:23:27.498 4679-4690/com.gobonus.gobonus W/art: Suspending all threads took: 26.757ms Request.java:
package com.gobonus.gobonus;
import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.ProtocolException; import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets;
public class Request {
private final String USER_AGENT = "GoBonus Android Client 1.0"; private final String API_SERVER = "http://192.168.2.21";
public String Content;
public Request (String session_token, String uri, String params) {
String urlParameters = "session_token="+session_token+"&"+params; // url params byte[] postData = new byte[0];
System.setProperty("http.agent", USER_AGENT); // user agent truck
// api = android.os.Build.VERSION_CODES.KITKAT) { postData = urlParameters.getBytes( StandardCharsets.UTF_8 ); } else postData = urlParameters.getBytes(Charset.forName("UTF-8"));
int postDataLength = postData.length; URL url = null;
try { url = new URL( API_SERVER + uri); } catch (MalformedURLException e) { e.printStackTrace(); } HttpURLConnection conn= null; try { conn = (HttpURLConnection) url.openConnection(); } catch (IOException e) { e.printStackTrace(); } conn.setDoOutput( true ); conn.setInstanceFollowRedirects( false ); try { conn.setRequestMethod("POST"); } catch (ProtocolException e) { e.printStackTrace(); } conn.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded"); conn.setRequestProperty( "charset", "utf-8"); conn.setRequestProperty( "Content-Length", Integer.toString( postDataLength ));
conn.setUseCaches( false ); try { DataOutputStream wr = new DataOutputStream( conn.getOutputStream()); wr.write( postData ); conn.connect(); Content = ConvertData(conn); } catch (IOException e) { e.printStackTrace(); } } protected String ConvertData (HttpURLConnection url) throws IOException { // local variables String line; StringBuffer text = new StringBuffer();
InputStreamReader in = new InputStreamReader((InputStream) url.getContent()); BufferedReader buff = new BufferedReader(in); do { line = buff.readLine(); text.append(line + "
"); } while (line != null); return text.toString(); }
}

WelcomeActivity.java
package com.gobonus.gobonus;
import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.TextView;
public class WelcomeActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView WebTest = (TextView) findViewById(R.id.webTest); WebTest.setText(new Request("123", "/ajax", "foo=bar").Content); setContentView(R.layout.activity_welcome); }
public void LoginGo(View view) { Intent intent = new Intent(WelcomeActivity.this, LoginActivity.class); startActivity(intent); } }
Манифест





Layout

Быстрый запуск программы через CMD

Подскажите, что нужно сделать, что бы программу можно было запустить по имени через консоль?
Например, если написать в CMD слово Skype, то запускается Skype.


Ответ

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

Вызов и подключение программы на c++ из c#

Есть программа на c++, которая генерирует зашифрованное сообщение и выводит в файл и консоль. Программа на c# должна эти данные выводить на winforms. Как их вообще связать? Т.е. вызвать шифратор сообщения на с++ из c#, подождать пока она посчитает и выведет данные, а затем на с# в winforms выведет ответ?


Ответ

Лучше переделать программу на C++ в dll, подключить его и из C# вызать соответствующий метод.
C++
Запускаем Visual Studio .NET. Создаём новый проект File->New->Project. Выбираем Visual C++ Project, На вкладке Templates->Visual C++, Выбираем “Win32 Project”. Выбираем имя для проекта, например TestLib. Нажимаем OK. В следующей форме выбираем Application Type: DLL и Empty Project. Добавим в "Source File" New Item->C++ File. Добавим код
#include extern "C" { double __declspec(dllexport) Add (double a, double b) { return a + b; } } Компилируем.
C#
using System.Runtime.InteropServices; using System.Windows.Forms;
namespace WindowsFormsApp1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); }
[DllImport("TestLib.dll", CallingConvention = CallingConvention.Cdecl)] public static extern double Add(double a, double b); private void button1_Click(object sender, EventArgs e) { var x = Add(25, 17); MessageBox.Show(x.ToString()); } } }

Зачем нужен 0xDEADBEEF?

Я разбираюсь в программе и вижу объявление unsigned long transfer[TRANSFER_LENGTH] = { 0xDEADBEEF }; а ниже по коду for (int i = 0; i < TRANSFER_LENGTH; i++) transfer[i] = GetData(); Вот зачем присваивать transfer 0xDEADBEEF, а не взять просто 0?


Ответ

Потому что DEADBEEF прекрасно видно в hex-dump'е как осмысленная константа 0xDEADBEEF. Вот представьте себе, что Вы анализируете лог обмена и видите там 00000000. Неясно - была передача данных или нет. И что нули означают. А когда получается DEADBEEF понятно, что что-то произошло нехорошее и в каком конкретно месте нужно искать причину. Еще раз поясню, что при нормальном исполнении программы вероятностью увидеть DEADBEEF (или любую другую аналогичную) константу равна 0. А нолей в памяти бывает сколько угодно. Вот на этом игра и ведется. PS: еще обращу внимание на два момента: DEADBEEF по-английски означает 'дохлое мясо' :-) константа DEADBEEF одинаково записывается как строчка и как байты в hex-представлении

Что означает доллар?

Здравствуйте. Не могу понять, что означает эта запись на jQuery var $tab_title_input = $( "#tab_title"), Насколько я знаю, знак доллара обычно обозначает какую-то функцию (или слово jQuery). Что этим хотели сказать разработчики? Пример взят с офсайта jQuery


Ответ

Знак доллара является разрешенным символов для идентификатора в языке Javascript. jQuery использует знак $ как псевдоним (сокращение) для идентификтора jQuery То есть в данном конкретном случае $tab_title_input - просто имя, включающее знак доллара, $( "#tab_title") - вызов функции jQuery.

Количество ядер процессора

Имеется задача вычислительного характера. Предположительно программа будет исполнятся на машине с многоядерным процессором (процессорами), количество ядер неизвестно заранее.
Вопрос: стоит ли программно определять количество ядер (к примеру с помощью System.Environment.ProcessorCount) и создавать соответствующее количество потоков, в которых и будут производится вычисления, или никакого выигрыша в продуктивности подобным образом получить не удаться?


Ответ

Стоит. Если система может выполнять одновременно 2 потока, а вы будете запускать, к примеру, 4, то лишние 2 потока не добавят эффективности. Если же система может выполнять больше потоков, чем вы создадите, то вы потеряете в эффективности - вычислительные ресурсы (оставшиеся ядра cpu) будут простаивать. Если задача распараллеливается - ее нужно распараллеливать настолько, насколько это возможно. Конечно, о здравом смысле тоже не стоит забывать. При увеличении количества потоков рано или поздно будет достигнута та ситуация, когда накладные расходы станут соизмеримыми (или превысят) чистое время вычислений.

Парсинг сайта в java с помощью jsoup

Решил написать простенькую телепрограмму с использованием jsoup. Задача более чем скучная, но для меня новая ибо раньше с парсерами не работал. Прошу у Вас помощи не в написание кода, а совета как работать с парсером, читал статьи, но они рассказывают только про заголовки и т.п., а вот как например спарсить расписание с первого канала на странице. И может быть вы считаете, что jsoup полная лажа посоветуйте другой.


Ответ

Ну, а в чём проблема? Загрузите документ Снавигируйте к элементу, содержащему программы. Тем же способом найдите нужные элементы данных. Какие именно HTML-атрибуты вам нужны, устанавливается внимательным чтением исходника сайта, который вы собираетесь распарсить. На сайте даже есть простейший пример (без навигации, просто все ссылки).

Зачем надо писать typename для уточнения типа?

При использовании шаблонов иногда надо писать typename у типов - когда и зачем это делать?
template inline void PRINT_ELEMENTS (const T& coll, const char* optcstr="") { typename T::const_iterator pos;
std::cout << optcstr; for (pos=coll.begin(); pos!=coll.end(); ++pos) { std::cout << *pos << ' '; } std::cout << std::endl; }


Ответ

Проблема в том, что T::const_iterator — зависимое имя: оно зависит от параметра шаблона T. В этой точке компилятор не знает, каким будет T, и не может предсказать, будет ли T::const_iterator именем типа или, например, именем статического поля или вообще шаблона. Поэтому он и не пытается угадать, и предполагает, что это поле. Если же ему подсказать, он будет предполагать, что T::const_iterator — это тип, и поймёт, что typename T::const_iterator pos; — объявление переменной. Почему же компилятор не может подождать с выяснением смысла выражения T::const_iterator до того момента, когда тип T будет уже известен (то есть, до момента разворачивания шаблона с конкретным типом T)? А вот почему: на момент применения шаблона тип T имеет право быть ещё не определён! И ещё он может зависеть от самого шаблона. Так что откладывать выяснение смысла выражения нельзя. Пример: template class comparable { bool compare(T& other) { return this == other; } };
class length : public comparable // в этой точке для comparable // тип T ещё не известен полностью! { ... Пример кода, иллюстрирующего «скользкие» моменты, приведён ниже. Он не компилируется gcc (так как нету полагающегося по стандарту typename), но более либеральный MSVC 2012 его компилирует и выполняет. typename для того и нужен, чтобы исключить подобные сюрпризы. #include "stdafx.h" // нужно для MSVC #include using namespace std;
template struct A { void f() { // если T::iterator - тип, это предварительное объявление функции // если T::iterator - число, это объявление переменной с инициализацией int x(T::iterator); } void g() { int x = 5; { // если T::iterator - шаблон, принимающий числовой аргумент, // это инстанциация шаблона в переменную x, перекрывающую x // за фигурными скобками // если T::iterator -- экземпляр класса с перегруженным оператором <, // это сравнение T::iterator с нулём, а затем сравнение результата // со значением переменной x! T::iterator<0> x; // Кто-то всё ещё сомневается, что C++ - непредсказуемый язык? } } };
struct T1 { typedef int iterator; };
struct T2 { static const int iterator = 5; };
struct T3 { template struct iterator { iterator() { cout << "constructing template with C = " << C << endl; } }; };
struct T4 { struct Titerator { Titerator operator < (int value) { cout << "in operator < " << value << endl; return Titerator(); } bool operator > (int value) { cout << "in operator > " << value << endl; return false; } }; static Titerator iterator; };
T4::Titerator T4::iterator = T4::Titerator();
int main(int argc, char* argv[]) { A a1; a1.f(); A a2; a2.f(); A a3; a3.g(); A a4; a4.g(); return 0; } Результат работы таков: constructing template with C = 0 in operator < 0 in operator > 5

try-catch против if-else

Я сейчас изучаю C# по учебнику Шилдта, а он учит заключать все узкие моменты в try-catch
Это нормальная практика ветвления кода, или лучше пользоваться if-else? Я, конечно, понимаю разницу между ошибками и исключениями. Но теперь у меня расплывается граница между некоторыми исключениями и обычными ветвлениями в коде.
Например операция деления одного числа на другое подразумевает, что пользователь может (попробовать) поделить число на ноль. С одной стороны результат этой операции будет исключением, которое можно обработать. С другой стороны можно и не доводить дело до исключения, заранее проверяя вводимые числа.
Как принято поступать в обществе профессиональных программистов?


Ответ

Вообще подмена исключений условными блоками - не самая здравая идея. Любая функция (метод) в принципе должна выполнять одну возложенную на нее задачу. Если по тем или иным причинам задача выполнена быть не может, то должно быть брошено исключение. Сам метод в общем случае не должен заниматься обработкой собственных исключений, для этого есть вызывающий его код. Метод должен либо выполнить задачу, либо сообщить о невозможности ее выполнения. Вернемся к вашему примеру: Например операция деления одного числа на другое подразумевает, что пользователь может (попробовать) поделить число на ноль. С одной стороны результат этой операции будет исключением, которое можно обработать. С другой стороны можно и не доводить дело до исключения, заранее проверяя вводимые числа. В этом случае должно быть именно вызвано исключение - ваш метод получил некорректные входные данные, и не может правильно произвести операцию деления. Тут интересна такая ваша фраза: С другой стороны можно и не доводить дело до исключения, заранее проверяя вводимые числа. Можно. Но что должен делать код дальше, если проверка не прошла? Вернуть некое магическое значение типа -1 или 0? Это будет некорректно с точки зрения логики. Вывести сообщение об ошибке? Это будет попахивать ошибкой проектирования - отвечать за вывод сообщений об ошибках должен совсем другой код. Появится связность кода, а это очень плохо. Помимо того, существуют такие исключительные ситуации, в которых никакие if-else не помогут. Скажем, не удалось открыть соединение базой данных. Что программа должна делать дальше? Войти в условие и попытаться еще раз открыть его, а затем еще, еще и еще? Вряд ли. Ну а что касается if-else, то их имеет смысл использовать там, где "не сработавший" вариант - всего лишь одно из возможных корректных состояний программы. Резюмирую - метод должен либо выполнить задачу, либо сообщить о невозмождности ее выполнения. Обрабатывать собственные исключения чаще всего не нужно. Следует пробрасывать их вверх. Весьма рекомендую также прочесть у Рихтера главу, посвященную исключениям. Да и вообще саму эту книгу

Как разрешается конфликт изменений при слиянии ветвей?

Диспозиция такая:
Есть две ветки. в каждой из них присутствует файл который редактировался (один и тот же).
При слиянии веток что произойдет с этим файлом?


Ответ

Если кратко: произойдет конфликт слияния (merge conflict) и его нужно будет как-то разрешить.
Для бинарных файлов: только выбрать версию А или Б (или другие, если octomerge).
Бывает, что бинарные файлы Git воспринимает как текстовые и тогда merge их необратимо портит. Это прежде всего относится к файлам office-форматов.
Для текстовых файлов: пара вариантов:
Вручную разрешить конфликты
После merge в файле появятся куски из обеих сливаемых версий, как-то так:
<<<<<<< HEAD содержимое файла из первой ветки ====== содержимое файла из второй ветки >>>>>>> otherbranch
Нужно будет вручную отредактировать конфликтный файл (или файлы), при этом не забывая удалить метки, оставленные Git (>>>>>>> otherbranch). Затем:
git add conflicting-file-name.txt git commit -m'merged A and B'
Выбрать одну из версий файла
Можно явным образом указать: какой файл выбирать. Подходит, только если одна из версий не нужна.
git checkout --ours a.txt git checkout --theirs a.txt git add a.txt git commit -m "added theirs"

Сделал вам тестовый репозиторий, чтобы сразу клонировать и посмотреть, как оно работает.
git clone https://github.com/NickVolynkin/git-merge-test.git cd git-merge-test git merge otherbranch open a.txt
В файле видны отметки, можете с ним теперь проделать вышеописанные действия.
Подробнее написано в книге Pro Git на русском. Ее обязательно нужно прочитать, прежде чем работать со слиянием веток. Фундаментальное понимание процесса ничем не заменить.
Потренироваться с ветвлением и слиянием можно тут: Learn Git Branching

Как проверить есть ли на устройстве доступ к интернету?

Как можно проверить есть ли на устройстве доступ к интернету?


Ответ

Функция
public boolean isOnline() { ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo netInfo = cm.getActiveNetworkInfo(); return netInfo != null && netInfo.isConnectedOrConnecting(); }
И в манифест:

Взял отсюда

Зачем указатель, если есть ссылка? [дубликат]

На данный вопрос уже ответили: Чем отличаются ссылки от указателей в С++ 2 ответа #include using namespace std;
void display_ptr(int *ptrint) { cout << *ptrint << endl; }
void display_addr(int &toint) { cout << toint << endl; }
int main() { int i{ 10 }; display_ptr(&i); display_addr(i); }
В данном примере для меня непонятны возможности конструкции с указателем, по сравнению с передачей значения по ссылке.
Как видно, чтобы использовать значение по указателю, нужно достать его с помощью *, а еще передать в аргумент с помощью &
Используя передачу по ссылке, ничего не нужно кроме указания в самом параметре, при этом значение также не копируется и его также можно изменять по ссылке.
Не совсем понимаю какой профит у указателей, если намного удобней передавать значение по ссылке.


Ответ

Если с инглишем хорошо, то милости просим на англоязычный стэковерфлов. Если в двух словах:
Ссылку нельзя перенацелить Нельзя создать ссылку на ссылку Указатель можно обнулить Указатели поддерживают адресную арифметику(+, -, ++, --) Указатель нужно разыменовывать Указатель является переменной, которая содержит адрес памяти. Вне зависимости от того, как реализуется ссылка, ссылка имеет тот же адрес памяти что и элемент на который она ссылается. Ссылки нельзя поместить в массив Можно создавать константные ссылки на временные объекты

Создайте дизайн молнии

Я пытаюсь воссоздать символ молнии от The Flash (DC Comics) (или знак на футболке, которую носит Sheldon Cooper из The Big Bang Theory ) в CSS.

Этот символ будет действовать, как система звездного рейтинга, но вместо этого будет - "система рейтинга молний".
Однако, поскольку я пытаюсь свести HTML к минимуму, то я бы хотел, чтобы в основном это был стиль CSS.
Ниже пример моего кода:
position: relative; margin: 0 auto; } .circ:hover{ background:gray; } .circ:hover .bolt{ background:gold; } .circ { height: 50%; width: 50%; background: white; border: 5px solid black; border-radius: 50%; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); box-shadow:0 0 10px 2px black; } .bolt { position: absolute; top: 5%; left: 50%; height: 70%; width: 30%; background: yellow; border: 2px solid black; border-bottom: none; transform: perspective(200px) skewX(-10deg) rotateX(15deg); } .bolt:before { content: ""; position: absolute; top: 90%; left: 20%; height: 50%; width: 100%; background: inherit; border: 2px solid black; transform: ; } /* .bolt:after{ content:""; position:absolute; top:-40%;left:20%; height:50%; width:100%; background:inherit; transform:perspective(50px) skewX(-10deg) rotateX(45deg); }*/


Но не знаю, как дальше продолжать отсюда. Я попытался использовать свойство perspective, хотя я не знаю, что у меня уже есть ли до сих пор обработка по этому свойству - в основном потому, что я немного запутался относительно того, что perspective делает со свойствами :before и :after, когда они применяются к родительскому элементу.
Выбрал для этого CSS, так как белый фон и цвет молнии будут меняться при щелчке, и ещё потому, что я знаю, как это сделать с помощью CSS.
Знаю, что SVG может быть лучшим вариантом здесь, но я не смог изучить SVG из-за ограничений по времени, поэтому предпочел бы использовать «то, что я знаю, как использовать», то есть CSS.
Перевод вопроса: Create a lightning bolt design (like The Flash)@jbutler483


Ответ

Однозначно svg тут 100%-ое решение, но предложу еще свой кривой css вариант) :
* { box-sizing: border-box; } html, body, .wrap { margin: 0; width: 100%; height: 100%; } .wrap { /* display: flex; align-items: center; align-content: center; justify-content: center; */ max-width: 500px; width: 100%; margin: 2rem auto; } .z { position: relative; width: 300px; height: 300px; margin: 0 auto; } .lg { position: absolute; transform: skewX(-50deg) rotate(-40deg) translate(-78%, -82%); z-index: 2; top: 50%; left: 50%; } .lightning-border{ background: #d4c6cb; width: 42px; height: 130px; left: 50.5%; } .lightning{ background: #fbe028; width: 35px; height: 120px; } .lg:before, .lg:after { content: ''; position: absolute; } .lightning:before { top: -130px; left: -20px; border-bottom: 150px solid #fbe028; border-left: 30px solid transparent; border-right: 10px solid transparent; } .lightning:after { top: 90px; left: 15px; border-top: 150px solid #fbe028; border-left: 10px solid transparent; border-right: 30px solid transparent; } .lightning-border:before { top: -140px; left: -24px; border-bottom: 172px solid #d4c6cb; border-left: 38px solid transparent; border-right: 16px solid transparent; } .lightning-border:after { top: 88px; left: 14px; border-top: 172px solid #d4c6cb; border-left: 16px solid transparent; border-right: 38px solid transparent; } .circle { width: 180px; height: 180px; background: #fff; border: 3px solid #000; border-radius: 50%; position: absolute; z-index: 1; left: 50%; top: 50%; margin: -90px 0 0 -90px; } body { background: #e63737; }


codepen
P.S: Bazzzzzinga! ;)

Регулярное выражение для пароля от 6 символов с использованием цифр, спец. символов, латиницы, наличием строчных и прописных символов

Нужно настроить регулярное выражение для "Сложного пароля": от 6 символов с использованием цифр, спец. символов, латиницы, наличием строчных и прописных символов. Если введенные символы не соответствуют данному выражению то return false;


Ответ

Необходимо использовать позитивный просмотр вперёд. Он позволит обеспечить все перечисленные вами условия.
Вот так выглядит выражение целиком:
/(?=.*[0-9])(?=.*[!@#$%^&*])(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z!@#$%^&*]{6,}/g
Вот пример на regex101. Можете попробовать написать свои пароли и проверить работу регулярного выражения на соответствие своим требованиям.
Пояснение:
(?=.*[0-9]) - строка содержит хотя бы одно число; (?=.*[!@#$%^&*]) - строка содержит хотя бы один спецсимвол; (?=.*[a-z]) - строка содержит хотя бы одну латинскую букву в нижнем регистре; (?=.*[A-Z]) - строка содержит хотя бы одну латинскую букву в верхнем регистре; [0-9a-zA-Z!@#$%^&*]{6,} - строка состоит не менее, чем из 6 вышеупомянутых символов.

Основано на ответе на вопрос: "Javascript regular expression password validation having special characters"

Обновление
Важно понять, что для того, чтобы проверить обязательное наличие определённых символов в строке, достаточно использовать такой шаблон: (?=.*[%s]), где вместо %s надо указывать требуемый набор символов.
Шаблон должен быть в самом начале регулярного выражения и присутствовать столько раз, сколько уникальных правил для проверки строки вы хотите использовать.
После отрезка с повторениями этого шаблона необходимо использовать обобщённый набор из всех разрешённых символов. Нам надо склеить «куски» в один общий набор разрешённых символов. Затем к нему надо будет применить ограничение по количеству символов, соответствующее выбранной длине строки.
Чтобы в коде легче читалось такое регулярное выражение, и его было легче проверить, в случае опечатки можно использовать такую функцию для генерации итогового выражения:
function makePasswordRegExp(patterns, min, max) { var min = min || ''; // Если минимальное число символов не указано, берём пустую строку var max = max || ''; // Если максимальное число символов не указано, берём пустую строку var regex_string = ''; var rules = []; var range = "{" + min + "," + max + "}"; // Разрешённый диапазон для длины строки for (rule in patterns) { // Обрабатываем входящий массив из ВСЕХ правил для строки if (patterns.hasOwnProperty(rule)) { rules.push(patterns[rule]); // Запоминаем правила // Формируем последовательность из шаблонов `(?=.*[%s])` // Она проверит обязательное присутствие всех символов из входящего набора regex_string += "(?=.*[" + patterns[rule] + "])"; } } // Добавляем в хвост набор из ВСЕХ разрешённых символов и разрешённую длину строки regex_string += "[" + rules.join('') + "]" + range; // Собираем всё в одно регулярное выражение return new RegExp(regex_string, 'g'); }
Использование:
// Набор правил // Имена ключей в этом объекте могут быть любыми // Они для лучшего понимания частей итогового регулярного выражения var patterns = { 'numeric': '0-9', 'special': '!@#$%^&*', 'latin_lower': 'a-z', 'latin_upper': 'A-Z' };
// В вашем случае есть ограничение только по минимальной длине от 6 символов var min = 6;
// Передаём правила в функцию и смотрим итоговое выражение console.log(makePasswordRegExp(patterns, min));
// Вывод: /(?=.*[0-9])(?=.*[!@#$%^&*])(?=.*[a-z])(?=.*[A-Z])[0-9!@#$%^&*a-zA-Z]{6,}/g
Безусловно, функцию можно улучшить, добавив в неё проверку большего из двух аргументов min и max и тому подобное. Она призвана только показать подход, который может упростить отладку таких сложных регулярных выражений.

Как можно сделать фон штриховкой на CSS/HTML?

Можно ли сделать такой штрих, если да, то как


Ответ

Можно, используя градиент
.dash { height: 30px; background: repeating-linear-gradient(-60deg, #555 0, #555 1px, transparent 1px, transparent 5px); }


Как парсить аргументы командной строки?

Пишу консольное приложение которое должно принимать более 5 параметров. При этом есть обязательные параметры есть не обязательные, одни параметры должны работать только с другими и т.д.. Я уже погряз в различных if..else if..else. Как облегчить себе жизнь? Есть ли рекомендации и стандартные приёмы по работе с аргументами командной строки?


Ответ

Если параметров много, лучше всего вынести их разбор в отдельный класс или набор классов. Когда if/else образуют сложную структуру, можно использовать «повышенную декларативность» C# и описывать структуру команд, например, так:
var commandLinePattern = Command.WithName('add') .HasOption('-fileName')
| Command.WithName('help') .HasParameter("CommandName");
Конечно, это потребует определённой изобретательности при проектировании, так что ниже изложу подробнее.
Следующим шагом мы опишем наши команды:
public interface ICommand { void Run(); }
public HelpCommand : ICommand { public string CommandName { get; set; }
public bool Verbose { get; set; }
public int PageSize { get; set; }
public void Run() { if (CommandName == "add") { Console.WriteLine("Help on the ADD command"); } . . . } }
Шаблон командной строке (переменная commandLinePattern в первом примере) можно применить к конкретной строке параметров, чтобы построить экземпляр конкретного класса команды, и заполнить его свойства, использую рефлексию:
var command = commandLinePattern.Parse(args); command.Run();
UPDATE
Итого, получается приблизительно такой код:
static class Program { private static readonly commandLinePatterm = Command.WithName('add') .HasOption('-fileName') .HasOption('-move')
| Command.WithName('help') .Parameter("CommandName");
static void Main(string[] args) { var command = commandLinePattern.Parse(args); command.Run(); } }
UPDATE «для новичка»
Немного о том, как реализовать всю эту красоту. Наше чудо по внешнему виду и внутреннему устройству очень напоминает регулярные выражения: сначала мы описываем некий шаблон аргументов командной строки, и затем применяем его к реальным аргументам. Результатом такого применения будет объект, который можно будет выполнить. Назовём его командой
Название команда возникло не просто так — это один из паттернов проектирования, описанный в классическом труде банды четырёх.
Я не знаю, какие командные строки вам приходится разбирать, поэтому сделаю несколько предположений:
Программа может выполнить за один запуск одну и только одну команду. Команда идёт первой в командной строке. Команда не требует префиксов, таких как дефис или косая черта. За командой могут следовать один или несколько параметров. Параметры могут быть именованными и безымянными. Именованные параметры имеют префикс, например, дефис. Именованные параметры могут иметь значение, в этом случае оно отделяется от имени двоеточием.
Приблизительно такие правила используются в большом количестве утилит, например, в архиваторах pkzip, arj и rar; в утилитах контроля версий git и hg — то есть этих двух правил действительно хвататет для широкого спектра задач.
arj add archive *.c -m0
arj — это имя программы, add — команда, archive (имя архива) и *.c (что архивировать) — безымянные параметры; -m — именованный параметр (опция), 0 — значение параметра.
В arj значение параметра не требуется отделять символом : или =. Мы пойдём другим путём, исключительно для из-за того, что пример демонстрационный.
Такой шаблон параметра командной строки может быть описан простым классом:
public class CommandLinePattern { public string Name { get; set; }
public List Parameters { get; set; }
public List Options { get; set; } }
Например, команда help может иметь такой шаблон
program Help CommandName [-Verbose] [-PageSize:num]
Которому соответствует экзмепляр класса CommandLinePattern
var pattern = new CommandLinePattern { Name = "Help", Parameters = new List { "CommandName" }, Options = new List { "Verbose", "PageSize" }, };
Нам нужно решить две задачи: построить такой шаблон, и применить его. В коде выше мы воспользовались статическим классом Command для того, чтобы начать конструировать шаблон:
public static class Command { public static CommandLinePattern WithName(string name) { return new CommandLinePattern { Name = name, Parameters = new List(), Options = new List(), }; } }
Остальные методы конструирования разместим непосредственно в классе CommandLinePattern
public CommandLinePattern HasOption(string name) { Options.Add(name);
return this; }
public CommandLinePattern HasParameter(string name) { Parameters.Add(name);
return this; }
Благодаря конструкции return this; мы можем строить объект последовательно, увязывая методы в цепочку:
var pattern = Command.WithName("Help") .HasParameter("CommandName") .HasOption("Verbose") .HasOption("PageSize");
Таким образом мы описываем шаблоны команды. Теперь решим вторую задачу — разбор командной строки и создание объекта-команды.
В классе CommandLinePattern реализуем метод TryParse, который будет пробовать разобрать командную строку и в случае успеха создавать объект, реализующий такой интерфейс ICommand
public virtual bool TryParse(string[] args, out ICommand result) { result = null; // Конечно, наш шаблон не может соответствовать пустой командной строке. if (args.Length == 0) return false;
// И он не может соответствовать какой-то другой команде. if (args[0] != Name) return false;
var properties = new Dictionary(); var nextParameterIndex = 0;
for (int i = 1; i < args.Length; i++) { if (args[i].StartsWith("-")) { var parameterWithoutHyphen = args[i].Substring(1); var nameValue = parameterWithoutHyphen.Split(':'); if (nameValue.Lenth == 1) properties.Add(nameValue[0], null); else properties.Add(nameValue[0], nameValue[1]); } else { var name = Parameters[nextParameterIndex]; nextParameterIndex++;
var value = args[i]; properties.Add(name, value); } }
// Для команды с имененем Help мы найдём класс HelpCommand: var className = Name + "Command"; var type = Type.GetType(className); // И создадим его экземпляр: result = (ICommand)Activator.CreateClass(type);
// Теперь значения всех параметров запишем в свойства // только что созданного экземляра: foreach (var property in properties) { var name = property.Key; var value = property.Value;
type.GetProperty(name) .SetValue(result, value); }
return true; }
public virtual ICommand Parse(string[] args) { ICommand result; if (TryParse(args, out result)) return result;
throw new FormatException(); }
Имейте в виду, что такая запись значений будет работать только со строковыми свойствами — в реальной программе вам потребуется конвертировать строковые значения в типы свойств.
Теперь у нас уже всё готово. Мы можем написать наш разбор параметров, но «для красоты» сделаем ещё один финальный штрих.
Создадим класс, который позволит объединить два шаблона и проверять сначала левый, а затем правый:
public class OrCommandLinePattern : CommandLinePattern { private readonly CommandLinePattern left; private readonly CommandLinePattern right;
public OrCommandLinePattern(CommandLinePattern left, CommandLinePattern right) { this.left = left; this.right = right; }
public override bool TryParse(string[] args, out ICommand result) { if (left.TryParse(args, result)) return true;
return right.TryParse(args, result); } }
В базовый класс добавим реализацию оператора ИЛИ
public static CommandLinePattern operator |(CommandLinePattern left, CommandLinePattern right) { return new OrCommandLinePattern(left, right); }
Теперь мы можем объединить несколько паттернов с помощью вертикальной черты:
var commandLinePattern = Command.WithName('add') .HasOption('-fileName')
| Command.WithName('help') .HasParameter("CommandName");
И в конце запускаем парсинг с помощью вызова одного единственного метода:
var command = commandLinePattern.Parse(args);
Результатом работы парсера будет экземпляр класса, реализующего интерфейс ICommand с заполненными свойствами. Нам остаётся только запустить его:
command.Run();

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

Предположим имеется следующий класс:
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 приведены для примера, все совпадения с действительностью не специальны.
Хочется узнать как необходимо создавать перегруженные методы/функции.


Ответ

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

Доступ к памяти из кучи после её освобождения

Почему не ловлю ошибку сегментирования в этом случае?
#include
int main(int argc, char* argv[]) { int* ptr = new int(47);
std::cout << ptr << " " << *ptr << std::endl;
/* Память выделенная в heap'e должна вернуться системе. Или она будет доступна программе до окончания области видимости указателя ? */ delete ptr;
*ptr = 74;
std::cout << ptr << " " << *ptr << std::endl; }


Ответ

Разименовывание невалидного указателя приводит к неопределенному поведению - так на C++ писать нельзя.
"Неопределенное поведение" вовсе не означает, что программа выпадет с ошибкой. В таком состоянии, программа может делать все что угодно, в том числе и работать так, как этого хочет программист.
Допускать неопределенное поведение в программе запрещено.

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

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


Ответ

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

Запретить поворот Activity и всего приложения

Добрый день. Как правильно решить такую ситуацию? Есть андроид-приложение, которое зависит от одного параметра - диагональ дисплея. Эту величину, или приблизительную к ней, я нахожу - проблем нету. В зависимости от дисплея >5 дюймов - только landscape, <5 - только портрет. protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (ScreenSize<5) { setContentView(R.layout.startactivity_p); //отобразить хмл портретный } else{ setContentView(R.layout.startactivity_l); // отобразить хмл ландскейп }
} В каждом xml-layout'е прописал следующее: android:screenOrientation="landscape" android:orientation="vertical" и android:screenOrientation="portrait" android:orientation="horizontal" соответственно. Но приложение все равно поворачивается. Подскажите, как можно это исправить?


Ответ

Для каждого вашего случая setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); и setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); Не поворачивается. Вообще вот хорошая статья

Чем отличаются static, self и parent в php?

Собственно хотелось бы увидеть различие работы со static:: от parent:: и self::


Ответ

parent - вызываем родительский метод (не обязательно статичный), self - вызываем метод именно этого класса, static - вызываем метод текущего класса. Разница между self и static хорошо видна, например, когда вы делаете new self() или new static() - в первом случае будет создан объект класса, где упомянут self (т.е. создан родитель), во втором - объект того класса, где вызывается метод (т.е. потомок)
примеры можно посмотреть здесь. "когда применять" - всегда, если только вам не нужен именно текущий класс, а не его наследники. Не знаю когда это может понадобиться, поэтому можете использовать static всегда, потом меньше проблем будет )
в документации можно почитать эту статью, там как раз описано отличие static и self и прочее
(ответ перенесён из комментариев BOPOH)

Получить 20 случайных чисел от 1 до 1000, но чтобы эти числа не повторялись

Как на JS сделать такую задачу. Нужно получить 20 случайных чисел от 1 до 1000 но чтобы эти случайные числа не повторялись. Как сделать такое? Все это дело должно работать в цикле. Вот пример половины кода.
var random_start = 1; // От какого генерировать var random_end = 1000; // До какого генерировать
allСycles = 20; for(countCycles=1;countCycles<=allСycles;countCycles++){ alert ("Случайное рандомное и уникально не повторающиеся число от 1 до 1000"); }
Пробовал по подсказкам так, но бывает числа повторяются
var random_end = 1000; allСycles = 20; for(countCycles=1;countCycles<=allСycles;countCycles++){
var test = Math.floor(Math.random()*(random_end+1)+1); alert(test);
}


Ответ

Использую библиотеку Lodash
console.log(_.shuffle(_.range(1,1001)).slice(0,20))
Без нее:
var random_start = 1; // От какого генерировать var random_end = 1000; // До какого генерировать allСycles = 20; var array= [] for(i=random_start;i<=random_end;i++){ array.push(i) } for(countCycles=1;countCycles<=allСycles;countCycles++){ console.log(array.splice(Math.random()*array.length,1)[0]) }

Как на SVG реализовать анимацию теней и z-index?

Как реализовать на SVG подобный пример с игрой теней и изменением z-index элементов?
Для полного эффекта развернуть на весь экран и кликнуть для просмотра анимации.
const shadows = document.getElementsByClassName("shadows")[0]; const shadowsChildren = shadows.children; let count = 0; let left = false; shadows.addEventListener("click", function() { let interval = setInterval(function() { !left ? count++ : count--; shadowsChildren[left ? count : count - 1].style.zIndex = left ? count : shadowsChildren.length - count; shadowsChildren[left ? count : count - 1].className = !left ? 'span' : ''; if (count === shadowsChildren.length) { left = true; clearInterval(interval); } if (count === 0) { left = false; clearInterval(interval); } }, 100); }); * { margin: 0; padding: 0; } html, body { width: 100%; height: 100%; background: #272727; } .container { position: fixed; width: 100vw; height: 100vh; display: flex; align-items: center; justify-content: center; background: orange; } .shadows { cursor: pointer; background: orange; position: relative; text-shadow: -15px 5px 20px #303030; width: 80vw; color: orange; text-align: center; letter-spacing: -20px; transition: all 0.25s ease-out .2s; font-family: fantasy; font-size: 200px; } span { position: relative; margin-left: -10px; transition: all 0.25s ease-out; } span.span { text-shadow: 15px 5px 20px #303030; transition: all 0.25s ease-out; }

C L I C K M E

Вариант css:hover
* { margin: 0; padding: 0; } html, body { width: 100%; height: 100%; background: #272727; } .container { position: fixed; width: 100vw; height: 100vh; display: flex; align-items: center; justify-content: center; background: orange; } .shadows { cursor: pointer; background: orange; position: relative; text-shadow: -15px 5px 20px #303030; width: 80vw; color: orange; text-align: center; letter-spacing: -20px; transition: all 0.25s ease-out .2s; font-family: fantasy; font-size: 200px; } span { position: relative; margin-left: -18px; transition: all 0.25s ease-out; } .shadows:hover span { text-shadow: 15px 5px 20px #303030; } .shadows:hover span:nth-child(1) { z-index: 8; } .shadows:hover span:nth-child(2) { z-index: 7; } .shadows:hover span:nth-child(3) { z-index: 6; } .shadows:hover span:nth-child(4) { z-index: 5; } .shadows:hover span:nth-child(5) { z-index: 4; } .shadows:hover span:nth-child(6) { z-index: 3; } .shadows:hover span:nth-child(7) { z-index: 2; } .shadows:hover span:nth-child(8) { z-index: 1; }
C L I C K M E


Ответ

Сложная анимация перемещения
Основа этой анимации - перемещение отдельной буквы вместе с фильтрами, создающими тень.
На первом этапе все буквы из начальных позиций собираются в середину слова. На втором этапе буквы разбегаются из середины на исходные позиции
Все перемещения букв реализуются командой изменения значения атрибута "X", задающего горизонтальную координату буквы:
C
Чтобы не запутаться в последовательности начала и окончания разных анимаций, необходимо продумать систему присвоения имен уникальных идентификаторов анимаций.
В данном примере команда начала анимации для каждой буквы включает название буквы. Например: begin="anC", begin="anL" Для анимаций возврата букв на исходную позицию:
begin="anBackC", begin="anBackL" Логика последовательности выполнения анимаций реализуется при помощи конструкции: begin="anBackC.end+0.25s" Словами это звучит так, - анимация возврата буквы "L" начнется после окончания анимации возврата буквы "C", после паузы равной 0.25s (секунды)
Смотреть интересней в полно-экраном режиме снипета
* { margin: 0; padding: 0; } text { text-align: center; font-family: sans-serif; font-size: 200px; font-weight: 900; fill: #FFA500; -webkit-filter: url(#shadowLetter); filter: url(#shadowLetter); } C L I C K M E

Передача массива в функцию не обьявляя его

Как можно передать массив в функцию не обьявляя его?
template void foo(int(&arr)[N]) { for (int var : arr) printf("%d
", var); }
int main(){ foo( { 1, 4, 5, 6 } ); // <- Ошибка return 0; }


Ответ

Проблема вашего кода не имеет никакого отношения к массивам.
Если вы хотите передавать что-то по lvalue-ссылке, то помните, что ко временным объектам разрешается привязывать только константные lvalue-ссылки (т.е., выражаясь корректнее, ссылки на константу). Нужно только иметь в виду, что в случае массива константность всего массива "проваливается вниз" и становится константностью индивидуальных элементов массива
template void foo(const int (&arr)[N]) { ...
Это все, что надо исправить в вашем коде.
http://coliru.stacked-crooked.com/a/e98e75636ab73993

Что означает знак вопроса в пути к файлу .css и .js?

style.css?123123
common.js?11133_444
Что означает знак вопроса? Можно передавать параметры?


Ответ

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

Разница между .h и .hpp

В чем разница между файлами с расширениями .h и .hpp в C++? Что лучше использовать?


Ответ

Строго говоря разницы между ними нет совсем. Разница может быть лишь в том, как IDE их интерпретирует. .h, если следовать некоторой логике, это заголовок для C(.c), тогда как .hpp это заголовок для C++(.cpp, .cxx etc.). Но всё это условности и зависят от предпочтений и используемых IDE. К примеру, в Visual Studio мы имеем .h и .cpp файлы, по умлочанию.
Единственно, на мой взгляд, где различное именование может принести пользу, это в проекте, где сочетается C и C++ код. Тогда стоит иметь .h/.c для C-кода и .hpp/.cpp для C++ когда. Других применений, кроме персональных предочтений, я не вижу.

Как получить доступ к private-полям класса извне?

Есть учебное задание, в котором необходимо получить доступ к private-полям класса извне. struct Cls дана изначально. Я нагуглил что нужно создать копию структуры, но с public методами, а потом через нее стучаться в изначальную. Вопрос в том как это реализовать? Как можно вернуть ссылку на private поля?
struct Cls { Cls(char c, double d, int i); private: char c; double d; int i; };

struct B { B(char c, double d, int i); public: char c1; double d1; int i1; };
// Эта функция должна предоставить доступ к полю c объекта cls. // Обратите внимание, что возвращается ссылка на char, т. е. // доступ предоставляется на чтение и запись. char &get_c(Cls &cls) {
return ((B*)(&cls))->c1 = 'p';
}
// Эта функция должна предоставить доступ к полю d объекта cls. // Обратите внимание, что возвращается ссылка на double, т. е. // доступ предоставляется на чтение и запись. double &get_d(Cls &cls) { /* ... */ }
// Эта функция должна предоставить доступ к полю i объекта cls. // Обратите внимание, что возвращается ссылка на int, т. е. // доступ предоставляется на чтение и запись. int &get_i(Cls &cls) { /* ... */ }
int main() { Cls cls('h', 2.0, 3); char ch = get_c(&cls); cout << ch << endl; }


Ответ

Вы не можете честным и надёжным путём получить доступ к приватным данным. Существуют грубые хаки, наподобие «угадать бинарный лэйаут данных и скастить указатель», которые прямо запрещены стандартом, и дают право компилятору наказать вас в любой момент.
Правильный ответ на вопрос, как получить доступ к приватным данным — никак. Ваш преподаватель либо задаёт вопрос с подвохом, либо плохо знает язык, который преподаёт.
Конкретно в вашем случае, код
(B*)(&cls)->c1
нарушает strict aliasing rule (правило 3.10/10 стандарта).
Дополнительное чтение по теме:
What is the strict aliasing rule? GotW #76: Uses and Abuses of Access Rights

Окей, исходя из развернувшейся дискуссии в ответе @Vlad from Moscow, вопрос о доступе через указатель на «чужой» тип не так уж очевиден даже из стандарта. Как видите, мы покамест не пришли к общему мнению о том, правомерен ли такой доступ по стандарту. В любом случае, доступ к приватным полям — очень плохой стиль программирования, и даже если так возможно сделать, делать этого не нужно

Обновление: Другие ответы: ([1], [2] и [3]) убедили меня в том, что к приватным полям таки можно получить доступ «законным» — то есть, совместимым со стандартом путём. (Впрочем, с трактовкой стандарта в последнем из них я не вполне согласен, но это лишь показывает, что сам по себе стандарт — достаточно большой и не очень ясно написанный текст.)
Тем не менее, любой из приведённых подходов кажется мне грубым хаком, и я бы крайне не рекомендовал пользоваться ими в production-коде. Думаю, будет поучительно, если вы отправите ссылку на это обсуждение вашему преподавателю.

Составной ключ в Dictionary

Допустим, есть класс, у которого есть 2 цифровых поля.
Хотелось бы эти 2 поля сделать первичным ключем в Dictionary.
В будущем этот ключ будет использоваться для поиска совпавших значений между 2 мя словарями.
Как это можно сделать, что бы не потерять в производительности?
У меня была идея, хранить их как строку, но может быть есть решение лучше?
P.S
Dictionary использую из-за высокой скорости поиска по ключу.
К моему удивлению, DataTable оказался тормознутее=( на 20к строк


Ответ

Как один из вариантов
Можно использовать класс Tuple. Например Dictionary, T3>, где T1, T2, T3 значения любых типов. В Tuple сравниваться будет по внутренним значениям.
у Tuple переопределены методы GetHashCode и Equals © Grundy Использовать структуру, т.к. у структур идет сравнение по всем имеющимся полям Передавать IEqualityComparer в конструктор, где Т - тип ключа. Сравнение будет производиться с использованием компаратора.

Три цвета фона расположенные под углом

Как мне получить фон, похожий на этот образ:

Только 3 цвета, которые идут от верхнего угла, как солнечный луч.
Может быть, лучше использовать простой PNG или SVG для фонового изображения?
Перевод вопроса: Three colors angled background color @Chris


Ответ

Ну такой "кривой" вариант на css с помощью border
.bg { position:absolute; top: 0; left: 0; right: 0; bottom: 0; overflow: hidden; background: #16334a; } .bg:after { content: ''; position: absolute; top: 0; right: 0; border-bottom: 100vh solid #204158; border-left: 70vw solid transparent; } .bg:before { content: ''; position: absolute; right: 0; top: 0; border-top: 70vh solid #0a253e; border-right: 100vw solid transparent; } .inner { position: relative; z-index: 5; color: #ccc; text-transform: uppercase; font-family: Arial; text-align: center; top: 40%; }

Lorem ipsum dolor sit amet, consectetur adipisicing elit. In, impedit.

CSS анимированное шестиугольное меню

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

Гамбургер кнопка в виде шестиугольника находится в центре. После нажатия на неё отображаются треугольные фигуры, окружающие кнопку гамбургера. Значок гамбургера превращается в крест, чтобы при повторном нажатии на него вернуть всё в исходное положение. В моей поясняющей картинке на самом деле отсутствует один шаг в самом начале. На левой половине картинки должна отображаться только кнопка гамбургера.
Поэтому мой вопрос заключается в следующем:
Не могли бы вы посоветовать мне, как создавать эту анимацию из шестиугольника с помощью HTML, CSS через jQuery или другими способами.
Какие способы вы бы использовали, чтобы сделать это?
Источник


Ответ

Вариант с CSS-переменными + clip-path. Тут не вся функциональность, это лишь набросок, но идея, думаю, понятна.
UPD: добавил кнопку и еще немного причесал код.
document.querySelector('.menu__btn').addEventListener('click', () => { document.querySelector('.menu').classList.toggle('menu--open'); }); :root { --side: 200px; --a: 25% 5%; --b: 75% 5%; --c: 100% 50%; --d: 75% 95%; --e: 25% 95%; --f: 0% 50%; --g: 50% 50%; --x: 0; --y: 0; --coordAfter: 25px; } .menu { width: var(--side); height: var(--side); padding: 0; margin: 50px auto; position: relative; } .menu__list { padding: 0; margin: 0; list-style-type: none; } .menu__triangle { position: absolute; left: 0; top: 0; transition: transform .25s, opacity .25s; background-color: #d261ff; width: var(--side); height: var(--side); opacity: 0; } .menu__triangle:hover { background-color: #9c29c1; } .menu--open .menu__triangle { transform: translate3d(var(--x), var(--y), 0); opacity: 1; } .menu__btn { border: none; background: none; position: absolute; left: 0; right: 0; top: 0; bottom: 0; margin: auto; background: #250031; clip-path: polygon(var(--a), var(--b), var(--c), var(--d), var(--e), var(--f)); font-size: 0; width: calc(var(--side) / 6); height: calc(var(--side) / 6); z-index: 1; text-align: center; } .menu__btn:hover, .menu--open .menu__btn { background-color: #613175; } .menu__btn-dash { width: calc(var(--side) / 14.285); background-color: #fff; height: 2px; display: inline-block; vertical-align: middle; position: relative; } .menu__btn-dash:after { width: inherit; height: inherit; left: 0; top: 0; background-color: inherit; transform: rotate(90deg); transform-origin: 50% 50%; transition: transform .2s; position: absolute; content: ' '; } .menu--open .menu__btn-dash:after { transform: rotate(0); } .menu__1 { clip-path: polygon(var(--a), var(--b) , var(--g)); --y: calc(var(--coordAfter) * -1); } .menu__2 { clip-path: polygon(var(--g), var(--b), var(--c)); --y: calc(var(--coordAfter) * -1/2); --x: var(--coordAfter); } .menu__3 { clip-path: polygon(var(--g), var(--c), var(--d)); --y: calc(var(--coordAfter) / 2); --x: var(--coordAfter); } .menu__4 { clip-path: polygon(var(--e), var(--g), var(--d)); --y: var(--coordAfter); } .menu__5 { clip-path: polygon(var(--f), var(--g), var(--e)); --x: calc(var(--coordAfter) * -1); --y: calc(var(--coordAfter) / 2); } .menu__6 { clip-path: polygon(var(--f), var(--a), var(--g)); --x: calc(var(--coordAfter) * -1); --y: calc(var(--coordAfter) * -1/2); }


Перевод числа в римскую систему счисления

Сегодня нашел задачу для перевода числа в римскую систему счисления. Как многие знают римляне не использовали отрицательных значений, ноль и дроби.
Решил задачу следующим образом:
function convertToRoman(number) { let roman = { "M": 1000, "CM": 900, "D": 500, "CD": 400, "C": 100, "XC": 90, "L": 50, "XL": 40, "X": 10, "IX": 9, "V": 5, "IV": 4, "I": 1 }; let result = ""; for (var i of Object.keys(roman)) { var repeat = Math.floor(number / roman[i]); number -= repeat * roman[i]; result += i.repeat(repeat); } return result; } //Тесты для примера console.log(convertToRoman(100)); console.log(convertToRoman(5789)); console.log(convertToRoman(952)); console.log(convertToRoman(782));
Можно ли решить эту задачу за наименьшее количество операций?


Ответ

Решение через reduce
Выглядит не тривиально, но время исполнения в 2.5 раза быстрее при 100 повторах подряд. function convertToRoman(number) { return [ { value: 1000, char: 'M' }, { value: 900, char: 'CM' }, { value: 500, char: 'D' }, { value: 400, char: 'CD' }, { value: 100, char: 'C' }, { value: 90, char: 'XC' }, { value: 50, char: 'L' }, { value: 40, char: 'XL' }, { value: 10, char: 'X' }, { value: 9, char: 'IX' }, { value: 5, char: 'V' }, { value: 4, char: 'IV' }, { value: 1, char: 'I' } ].reduce((result, currentValue) => { while (number >= currentValue.value) { result += currentValue.char; number -= currentValue.value; } return result; }, ''); } //Тесты для примера console.log(convertToRoman(100)); console.log(convertToRoman(5789)); console.log(convertToRoman(952)); console.log(convertToRoman(782));
Предлагайте свои решения, кому интересно.