Страницы

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

суббота, 7 декабря 2019 г.

Что есть ANSI и ASCII

#c #utf_8 #ascii #ansi


Я бы хотел, наконец, разобраться, как правильно называть строки 8-ми битных символов.

Что такое строка символов UTF-8 мне хорошо понятно - это строка, каждый символ которой
представлен переменным количеством 8-ми битных блоков (байтов).

Что такое строки UTF-16/UTF-32 мне тоже ясно.

Но я не могу понять, как корректно называть восьмибитные кодировки, где первые 128
знаков строго определены, а последующие - меняются в зависимости от используемой кодовой
страницы.

Кто-то их называет ascii, кто-то ansi, или просто CP1251, если подразумевается конкретная
кодировка.

Помогите разобраться. Гугл только запутал.
    


Ответы

Ответ 1



ASCII (American Standard Code for Information Interchange) - первый вариант кодировки. Потом появились CP866, KOI8-R, Windows 1251 и вот это всё. Так что, CP1251 - это расширенная версия ASCII. ANSI - это расширения ASCII, в которых были удалены псевдографические элементы и добавлены символы типографики. CP1251 - это пример ANSI кодировки. Если на диаграмме Эйлера показать:

Ответ 2



ASCII (читается аски́) - это первая кодировка применявшаяся еще в пору когда 99% юзеров SO еще даже не родились (1963 год). Кодировка 7-битная, то есть определено 128 символов, 8-й бит полного байта использовался для проверки четности поскольку в то время каналы были ненадежные, то предполагалось что будет проверяться каждый полученный байт. Далее со временем стало понятно, что для других языков можно использовать 8-й бит для отображения национальных символов - то есть использовать 256 символов. Эту расширенную 8-битовую кодировку условно называют ANSI (читается анси́) по названию американского института стандартов в рамках которого и была предложена 8-битовая кодировка. Соответственно, для каждого национального языка была предложена своя раскладка второй половины таблицы (от 128 до 255 символа), а первая половина таблицы от 0 до 127 - изначальные символы ASCII. KOI-8, CP-1251, 1252 и проч. - это различные инкарнации ANSI Далее когда дело дошло до иероглифов стало понятно, что в 256 символов не уместиться и появилась UNICODE (читается юникод) - где на 1 символ отводится 2 байта, то есть 65536 символов, где таблица была жестко поделена между национальными символами, например таблица ASCII осталась в интервале U+0000 до U+007F, а наша с вами кириллица в интервале U+A640 до U+A69F ну и т.д. С нарастанием угара стало ясно что 65536 символов также не хватает, потому что появились эмодзи, стали поднимать голову другие национальные символы справедливо указывавшие на нехватку места в таблице UNICODE, тогда был предложен UTF-8 (читается ютиэф 8), где количество байтов в символе имеет разную длину и может быть от 1-го до 4 байт, что дает 1 112 064 символов. Вот, как то так.

Ответ 3



Считаю название «восьмибитные» или «однобайтовые кодировки» вполне корректным общим названием для подобных вещей. Само собой, если подразумевается какая-то конкретная кодовая страница/кодировка, то она и указывается: «KOI8-R», «CP1251» «CP1250», «ISO8859-5». ASCII как стандарт (а это действительно стандарт — American standard code for information interchange) определяет, если я правильно помню, только первые 127 кодов символов. Поэтому формально символы типа «я», «č», «њ», «Ḱ» не принадлежат ASCII. «ANSI» — это вообще исключительно русскоязычный (sic!) термин для CP1251, т.к. вообще-то это сокращение обозначает американский национальный институт стандартизации (а «OEM» — original equipment manufacturer).

Неочевидное поведение блока using в C#

#c_sharp #net #dispose


Наткнулся на такой необычный код на METANIT. Объявлена структура:

public struct S : IDisposable
{
    private bool dispose;
    public void Dispose()
    {
        dispose = true;
    }
    public bool GetDispose()
    {
        return dispose;
    }
}


И есть такой код, который использует ее:

var s = new S();
using (s)
{
    Console.WriteLine(s.GetDispose());
}
Console.WriteLine(s.GetDispose());


Код выводит false, false, хотя казалось, что должно выводиться false, true. Самое
интересное то, что если структуру S сделать классом, то будет выводиться ожидаемое
значение :)

Объясните, что происходит за кулисами с переменной s? Почему для структуры будет
false, false, а для класса - false, true
    


Ответы

Ответ 1



Ваш код с using разворачивается следующим образом: var s = new S(); var using_s = s; try { Console.WriteLine(s.GetDispose()); } finally { using_s.Dispose(); } Console.WriteLine(s.GetDispose()); using вызыват Dispose не на вашей переменной s а на своей собственной переменной. И соответственно поле dispose обновляется не у переменной s. Для примера можно рассмотреть следующий код: using System; public static class Program { public static void Main() { var s = new S(); using (s) { s.Mark = 42; Console.WriteLine(s.GetDispose()); } Console.WriteLine(s.GetDispose()); var c1 = new C(); using (c1) { c1.Mark = 42; Console.WriteLine(c1.GetDispose()); } Console.WriteLine(c1.GetDispose()); var c2 = new C(); using (c2) { c2 = new C { Mark = 42 }; Console.WriteLine(c2.GetDispose()); } Console.WriteLine(c2.GetDispose()); } } public struct S : IDisposable { public int Mark; private bool dispose; public void Dispose() { Console.WriteLine(Mark); dispose = true; } public bool GetDispose() { return dispose; } } public class C : IDisposable { public int Mark; private bool dispose; public void Dispose() { Console.WriteLine(Mark); dispose = true; } public bool GetDispose() { return dispose; } } В случаях s.Mark = 42; и c2 = new C { Mark = 42 }; назначение переменной внутри блока using не влияет на значение поля Mark, выводимое методом Dispose, так как using вызывает Dispose на своей собственной переменной. И компилятор даже выводит соответствующие предупреждение. В случае с c1.Mark = 42; происходит не изменение переменной, а изменение объекта, на который она указывает.

Вывод битового кода числа

#битовые_операции #cpp


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


Ответы

Ответ 1



int i, N; N = 1234; i = 65536; while (true) { if (N & i) // битовое И - в данном случае вернет 2^i - если i-ый бит 1 printf("1"); else printf("0"); if (i == 1) // мы рассмотрели младший бит - выходим из цикла break; i >>= 1; // битовый сдвиг, запись числа смещается на один бит } // аналогично делению на 2, но быстрее. Как вариант. Вариаций много, изучите битовые операции: wiki.

Ответ 2



Странно, что std::bitset никто не вспомнил: #include #include #include int main() { int num = 32; std::cout << std::bitset(num) << "\n"; } 00000000000000000000000000100000

Ответ 3



typedef unsigned short ushort; ushort num = 34; for(int i = 15; i >= 0; --i) // short 16 бит (00000000 00000000) std::cout << ((num >> i) & 1) << " "; // проходимся по битам и выводим через пробел Для этого необходимо выучить побитовые операции, это совсем несложно - информации в интернете полным полно

Ответ 4



http://ideone.com/IHMlWD #include template char * tobinary(number x, char *buf) { number q; char *p=buf; if((number)~0<0) { *(p++) = '0' + (x<0); q = (number)1 << ((sizeof(number)<<3) - 2); } else q = (number)1 << ((sizeof(number)<<3) - 1); for(; q; q>>=1) *(p++) = x & q ? '1' : '0'; *p = 0; return buf; } #define POSVAL 7 #define NEGVAL -7 int main(void) { char temp[128]; #define TEST(type,val) do { type x=val; puts(tobinary(x, temp)); } while(0) TEST(char, POSVAL); TEST(unsigned char, POSVAL); TEST(signed char, POSVAL); TEST(unsigned short, POSVAL); TEST(signed short, POSVAL); TEST(unsigned, POSVAL); TEST(signed, POSVAL); TEST(unsigned long, POSVAL); TEST(signed long, POSVAL); TEST(unsigned long long, POSVAL); TEST(signed long long, POSVAL); TEST(char, NEGVAL); TEST(unsigned char, NEGVAL); TEST(signed char, NEGVAL); TEST(unsigned short, NEGVAL); TEST(signed short, NEGVAL); TEST(unsigned, NEGVAL); TEST(signed, NEGVAL); TEST(unsigned long, NEGVAL); TEST(signed long, NEGVAL); TEST(unsigned long long, NEGVAL); TEST(signed long long, NEGVAL); #undef TEST getchar(); return 0; }

Ответ 5



Была как то задача, в которой необходимо было заполнить массив от 0 до а битами каждого числа. #include using namespace std; int main() { int a; cin >> a; int row = 1 << a, row1; int digit[row][a]; for(int i = 0; i < row; i++){ row1 = i; for(int j = 0; j < a; j++){ digit[i][j] = (row1 >> (a - j - 1)) & 1; } } for(int i = 0; i < row; i++){ for(int j = 0; j < a; j++){ cout << digit[i][j] << " "; } cout << endl; } return 0; }

Система друзей на PHP

#php #mysql


У меня есть страница, где должны выводиться:


заявки в друзья
уже подтверждённые друзья в таком виде: id - Username


Как реализовать такую систему на PHP:


какой должна быть структура БД?
как определить, что пользователь дружит или только отправил заявку?

    


Ответы

Ответ 1



Сделайте отдельную таблицу для заявок, к примеру reguests. Пускай она будет примерно так: | id | sender | taker | accept | Первые три поля понятны, а вот accept пускай имеет значения 1 или 0 в зависимости подтверждения заявки. То есть 1, если подтвердил, 0 если еще нет. Чтобы реализовать систему друзей, то сделайте таблицу frinends (к примеру) и пускай она имеет примерно такой вид: | id | id1 | id2 | В поля id1 и id2 вписываете двух человек, которые подружились. Потом просто проверяете наличие пары нужных ид в таблице. Вот. Коротко и думаю ясно) Недавно сам ломал голову над такой системой, так что буду рад помочь.

Ответ 2



Предположим, что таблица с пользователями у вас уже есть. Остаётся создать таблицу, в которой буду "статусы" отношений между ними и, если нужно, то можно сделать еще одну таблицу, в которой будут храниться значения статусов Таблица users_status: user_inviter (id юзера, который пригласил) user_invited (id приглашенного юзера) stat_val_id (текущий статус - ключ к полю stat_id в таблице ниже) Таблица status_value stat_id stat_val (пригласил, отклонил, принял, игнорировал etc.) UPD Смотреть запрос в работе или так: SELECT * FROM `userlist` WHERE `user_id` IN ( SELECT IF(`user_invited` = '3', `user_inviter`, `user_invited`) FROM `users_status` WHERE `stat_val_id` = '2' ) user_invited = '3' - "3" - id пользователя, у которого ищем друзей stat_val_id = '2' - "2" - статус, означающий "дружат"

Ответ 3



Тут можно обойтись и одной таблицей со полями userId1, userId2, status. Рассмотрим пример вконтактика - там если отправляешь заявку добавления в друзья, то становишься подписчиком, а когда заявку подтверждают, то друзьями. Здесь поле статуса отвечает как раз за определение типа связи, а их смена должна быть определена в триггерах. На уровень приложения смену статуса выносить не стоит. Пример. Пользователь делает заявку на добавление в друзья, при этом выполняется запрос: insert into friends_rels (userId1, userId2) values ($id1, $id2); А уже триггер должен определить является ли это заявкой, или же подтверждением. Определяет путем запроса к таблице: select userId1, userId2 from friends_rels where userId1 = $id2 and userId2 = $id1; Если находит, значит это подтверждение заявки: модифицирует строку NEW.status = 'friends' и выполняет update на заявку, где также присваивает статус того, что они - друзья. Если же запись селектом не была найдена, то значит это заявка на добавление в друзья и нужно лишь модифицировать статус: NEW.status = 'subscribe'. Первичный ключ для строки не стоит делать - он попросту не нужен, а нужно только повешать уникальность на сочетание двух полей. Таким образом вся логика сосредоточена в одном только триггере на уровне БД, т.е. на уровне хранения данных. Отсутствуют лишние Joinы для определения типа связи. Также не нужно обрабатывать кучу частных ситуаций типа той, когда одной пользователь сделал заявку второму, а второй пользователь сделал заявку на добавление в друзья первого - здесь все пройдет верно, а в других реализациях возможно отклонение от требуемого поведения.

AsEnumerable в Entity Framework

#c_sharp #entity_framework #sql_server


Здравствуйте уважаемые специалисты! Хочу задать вопрос по Entity Framework. Например
у меня есть такой код
return from city in context.City
       where SomeFunc(city, id, name)
       select new City(city);

bool SomeFunc(City city, int id, int name)
{
    return city.Id == id || city.Name == name || city.Code == name;       
}

когда я выполняю код то получаю такое исключение 

LINQ to Entities does not recognize the method  and this method cannot be translated
into a store expression

В интернете советуют использовать метод AsEnumerable
return from city in context.City.AsEnumerable()
       where SomeFunc(city, id, name)
       select new City(city);

Это работает но очень медленно потому что context.City.AsEnumerable() выдает мне
сразу все города из таблицы и потом выполняет к ним функцию SomeFunc
Можно написать так: 
return from city in context.City
       where city.Id == id || city.Name == name || city.Code == name
       select new City(city);

и все будет работать быстро. Но тогда получится такая проблема - это условие может
быть использовано еще в каком-то методе и тогда надо будет дублировать этот код что
не есть хорошо. Как быть? Может быть в Entity Framework есть какой то способ избежать
и дублирования кода и выполнения условий в SQL а не в C#? Заранее спасибо!     


Ответы

Ответ 1



Попробуйте перейти от Func к Expression: Expression> SomeFunc(int id, string name) { return city => city.Id == id || city.Name == name || city.Code == name; } var result = cities.Where(SomeFunc(id, name)).Select(city => new City(city));

Ответ 2



Если условие используется в нескольких местах, вынесите эту фильтрацию в отдельный метод: private IQueryable GetFilteredCities(int id, string name) { return context.City .Where(city => city.Id == id || city.Name == name || city.Code == name); } Затем, его можно использовать в других методах: var cities1 = GetFilteredCities(1, "Moscow"); var cities2 = GetFilteredCities(3, "London").Where( ... ).Select( ... ); В результате выполнения метода GetFilteredCities SQL-запрос выполняться не будет, а будет просто формироваться условие. Непосредественно запрос выполнится при вызове методов AsEnumerable(), ToList() или ToArray().

Самовыполняющиеся функции [дубликат]

#javascript


        
             
                
                    
                        
                            This question already has answers here:
                            
                        
                    
                
                        
                            Что в Javascript значит синтакс ( function(){…} )( param1,
param2); ?
                                
                                    (7 ответов)
                                
                        
                                Closed 4 года назад.
            
                    
Зачем оборачивать блоки кода на JS в самовыполняющиеся функции?
    


Ответы

Ответ 1



Переменные, объявленные внутри функции, являются локальными (находятся в её области видимости). Это даёт как минимум 3 полезных момента: "Снаружи" не "достучаться" до того, что объявлено внутри функции. Не получится случайно затереть глобальную переменную, объявив переменную с таким же именем внутри функции. Глобальная область видимости не "захламляется" данными, которые не должны быть глобальными. Самовыполняющаяся функция (Immediately-Invoked Function Expression, IIFE) позволяет воспользоваться этими преимуществами, не создавая глобальную функцию. var x = 1; (function() { var x = 2; var y = 3; console.log("In: " + x); //In: 2 console.log("In: " + y); //In: 3 })(); console.log("Out: " + x); //Out: 1 console.log("Out: " + y); //ReferenceError: y is not defined Например, можно использовать самовыполняющуюся функции для того, чтобы сохранять данные, необходимые для работы функции, и которые при этом нужно хранить между вызовами функции: var test = (function() { var count = 0; return function() { count++; console.log("Count: " + count); }; })(); test(); //Count: 1 test(); //Count: 2 console.log(count); //ReferenceError: count is not defined Переменная count недоступна в глобальной области видимости, однако доступна внутри возвращаемой функции, так как та объявлена внутри самовыполняющейся функции, и поэтому имеет доступ к её области видимости. Также самовыполняющаяся функция может "помочь" с сохранением промежуточных значений данных при асинхронном выполнении кода. Например: for (var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 1000 * i); } Данный код будет выводить в консоль раз в секунду не числа по возрастанию, а число 10, потому что на момент вызова первой функции в setTimeout глобальная переменная i уже будет равна 10 (сначала проходят все итерации цикла, а уже потом вызывается первая функция). Если же обернуть setTimeout в функцию и передавать ей i в качестве аргумента, то вывод будет от 0 до 9: for (var i = 0; i < 10; i++) { (function(i) { setTimeout(function() { console.log(i); }, 1000 * i); })(i); } В данном случае переменная i в setTimeout уже не является глобальной переменной и не зависит от её изменений. Однако тут не нужно забывать о том, что если переменная является объектом, то изменение значения поля объекта "снаружи" приведёт и к изменению значения поля объекта "внутри".

Шаблонная виртуальная функция

#cpp #cpp11


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

Нашел следующее объяснение:


  Member function templates cannot be declared virtual. This constraint
  is imposed because the usual implementation of the virtual function
  call mechanism uses a fixed-size table with one entry per virtual
  function. However, the number of instantiations of a member function
  template is not fixed until the entire program has been translated.
  Hence, supporting virtual member function templates would require
  support for a whole new kind of mechanism in C++ compilers and
  linkers. In contrast, the ordinary members of class templates can be
  virtual because their number is fixed when a class is instantiated


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


Ответы

Ответ 1



Простой ответ: В С++ шаблон функции не является функцией, поэтому шаблон не может быть виртуальным. В C#/Java/etc используются не шаблоны, а generics. Generic-функция это (одна) функция, поэтому там такой проблемы нет. Сложный ответ: В С++ виртуальные функции сделаны так, что их количество прописано в определении базового класса. Это позволяет присвоить функции некоторый индекс в базовом классе и быстро находить ее по этому индексу. struct Base { func_t* vft; // скрытый член класса - массив виртуальных функций virtual void f(); }; Base* x = new Derived; x->f(); // компилируется в x->vft[0](); Если шаблоны будут виртуальными, то вместо перечисления функций в базовом классе надо искать все подстановки шаблона при вызовах функции. Для этого вместо индексов надо использовать имена, и искать эти имена в хеш-таблице. struct Base { hash_map vft; // скрытый член класса - хеш-таблица виртуальных функций template virtual void f(); }; Base* x = new Derived; x->f(); // компилируется в x->vft["f"](); Скорость вызова значительно упадет, т.к. надо будет разрешать коллизии. Можно использовать идеальную хеш-функцию (без коллизий). struct Base { func_t* vft; // скрытый член класса - массив (sic!) виртуальных функций virtual void f(); }; Base* x = new Derived; x->f(); // компилируется в x->vft[ideal_hash("f")](); // ideal_hash(name) выдает индекс массива, без коллизий Но из-за динамической линковки (.so/.dll) весь исходный код программы недоступен, и при каждой загрузке SO/DLL надо останавливать всю программу, менять хеш-функцию и перестраивать все таблицы, чтобы учитывались типы, которые добавились в этой SO/DLL. Использование JIT-компилятора может заменять виртуальные вызовы на обычные, и тогда никаких проблем с производительностью вызова не будет. // вместо x->f(); генерируется x->Derived::f(); // если доказано что тут может быть только Derived Но девиртуализация работает только если количество классов мало, и на данный момент эффективных JIT-компиляторов нет. (Те что есть, например в LLVM, не показывают хороших результатов.)

Ответ 2



Это невозможно сделать в рамках существующих реализаций С++. Так как виртуальные функции реализованы через таблицы указателей на них, компилятор должен иметь возможность сгенерировать функцию при ее определении - чтобы получить указатель. Так как код шаблонных функций генерируется только при инстанциировании шаблона, компилятор не может заполнить таблицу - у него просто нет указателя. Шаблонные виртуальные функции потребовали бы полного пересмотра подхода к полиморфизму, и для полной реализации потребовали бы "исполняющей машины" - примерно как Java или С#. Простой пример (не компилирующийся, естественно): // file base.h struct Base { template virtual void foo(T ) { } }; // file derived.h #include struct Derived : Base { template virtual void foo(T ) { }; }; // file foo.cpp #include void foo(Base* b) { base->foo(42); } // file main.cpp #include int main() { Base* d = new Derived; foo(d); } В приведенном примере очевидно, что компилятор не может сформировать правильный вызов функции foo(). В комментариях приводится такой аргумент - "А давайте заставим пользователя включать все заголовки всех потомков перед использованием шаблонной функции, а компилятор генерировать все таблицы виртуальных методов для всего дерева base которое он увидел in-place". Но у переданного foo() указателя уже должны быть сформированная таблица. Переформировать ее уже не получится!