Страницы

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

понедельник, 17 декабря 2018 г.

Как проигнорировать фигурные скобки в функции string.Format

Как проигнорировать фигурные скобки в функции string.Format? Пример:
string.Format("{Name:{0}}", "Value");
В результате выполнения данного кода мы получим исключение
An unhandled exception of type 'System.FormatException' occurred in mscorlib.dll Additional information: Input string was not in a correct format.
Что нужно сделать, для того, чтобы избавится от ошибки и получить в результате строку:
{Name:Value}


Ответ

Открытие и закрытие скобок интерпретируется как начальный и конечный элемент для функции форматирования строки. Для того чтобы вывести фигурную скобку в строке нужно ее продублировать {{ для открытия скобки и }} для ее закрытия. Исправленный вариант будет выглядеть следущим образом:
string.Format("{{Name:{0}}}", "Value");
Детали можно посмотреть на MSDN, а также тут

Как передать все значения item в RecycleView?

У меня есть recycleview с данными и мне надо передать все данные items в другое активити,как мне это реализовать?


Ответ

Зачем делать такой костыль как в предыдущем ответе, если любую модель можно сделать сериализуемой (implements Parcelable) и передавать всю модель целиком?
Кладем в intent: intent.putExtra("parcelable", myParcelables.get(position))
Берем из intent: MyParcelable model = getIntent().getParcelableExtra("parcelable")
пример реализации:
public class Country implements Parcelable {
private String code;
private String name;
private String tag;
private int limit;
private String image;
public Country(JSONParser data) { code = data.getString("code"); name = data.getString("value"); tag = data.getString("flag"); image = data.getString("image"); if (data.contains("limit")) { limit = data.getInt("limit") - code.length(); } }
public Country(Parcel in) { code = in.readString(); name = in.readString(); tag = in.readString(); image = in.readString(); limit = in.readInt(); }
public static final Creator CREATOR = new Creator() { @Override public Country createFromParcel(Parcel in) { return new Country(in); }
@Override public Country[] newArray(int size) { return new Country[size]; } };
@Override public int describeContents() { return 0; }
@Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(code); dest.writeString(name); dest.writeString(tag); dest.writeString(image); dest.writeInt(limit); }
public String getClearCode() { return code; }
public String getCode() { return "+" + code; }
public String getName() { return name; }
public String getTag() { return tag; }
public int getLimit() { return limit; }
public String getImage() { return image; } }
P.S.
Чтобы не словить BadParcelableException при передаче между активностями Parcelable-конструктор должен инициализировать данные в том же порядке, в котором они были записаны в Parcel в методе void writeToParcel(Parcel, int)

Не находит std::begin, std::end

Пишу простую шаблонную функцию in_array. По замыслу, она должна работать с любыми типами. Вот код:
template bool in_array(T needle, const T* haystack) { T *e = std::find(std::begin(haystack), std::end(haystack), needle); if (e != std::end(haystack)) return true; else return false; }
Получаю ошибки:
std::begin: не найдена соответствующая перегруженная функция
То же для std::end. В чем моя ошибка?


Ответ

Для указателей стандартные функции std::begin и std::end не определены.
Имея указатель, в общем случае, нельзя определить, указывает ли он на одиночный объект или на первый объект некоторой последовательности объектов. В виду этого нельзя определить функцию std::end для указателей, так как неизвестно число элементов, которые могут адресоваться указателем.
Вы могли бы свою функцию определить следующим образом
template bool in_array(T needle, T ( &haystack )[N] ) { auto e = std::find(std::begin(haystack), std::end(haystack), needle);
return e != std::end(haystack); }
Либо вы можете эту функцию определить как
template bool in_array(T needle, T *haystack, size_t n ) { auto e = std::find( haystack, haystack + n, needle);
return e != haystack + n; }
включив в объявление функции еще один параметр, задающий число элементов в массиве.

Программа потребляет много cpu

Небольшое отступление
У нас в фирме используется одна очень древняя программа с одним недостатком. После работы с ней надо чистить за ней файлы и в одном файле менять значения на первоначальные. Иначе при следующем запуске программа работает некорректно.
Итак решение - пишем программу в виде виндоуз формы, а потом форму удаляем, и кидаем ее в автозагрузку. В программе запущен таймер который проверяет если та древняя программа была закрыта пользователем он файлы приводит в первоначальный вид.
Но так форму я удалил (пользователям о ней знать не обязательно), что бы моя программа не завершала работу в ней стоит бесконечный цикл. Вот код:
private static void Main() { TimerCallback timer= new TimerCallback(Run);
System.Threading.Timer time = new System.Threading.Timer(timer, null, 0, 2000); for(;;) } static void Run(object state) {....}
но как оказалось он потребляет 20-30 процентов ресурсов проца именно из за бесконечного цикла. Есть у кого нибудь идеи как уменьшить нагрузку на проц?
Да и не хотелось бы использовать форму пусть и полностью прозрачную.


Ответ

Это у вас 3-4 ядра, вот оно и потребляет всего 20-30 процентов. Будет одно ядро - будет жрать 100, я думаю. Поставьте в этот цикл хотя бы Sleep(100) и будет счастье. А вообще надо нормально переписывать, а не костыли использовать...

Скобки () {} при инициализации внутри класса

Подскажите пожалуйста, а есть ли разница между использованием круглых и фигурных скобок при инициализации конструктора внутри класса. Оба варианта работают корректно.
class A { public: char c; int d;
A(char ch) :c(ch) {} A(char ch, int i) :c{ch}, d{i} {} };
int main() { A first = A('a'); A second = A('b', 1);
cout << "First: " << first.c << endl; cout << "Second: " << second.c << ' ' << second.d << endl;
return 0; }


Ответ

Начнем с того, что имеются случаи, когда нельзя применять инициализацию одного из видов к членам данных класса.
Например, если у вас имеется член класса, который является агрегатом (структурой или массивом), то возможные виды инициализации ограничены.
Рассмотрим несколько примеров.
В данном примере внутри структуры A объявляется агрегатный член данных B, имеющий тип структуры. Тогда данное объявление конструктора будет некорректныым
struct A { A(int x) : b( x ) {}
struct B { int x; } b; };
int main() { A a( 10 ); }
Компилятор выдаст сообщение об ошибке, говорящее о том, что он не может преобразовать объект типа int в объект типа struct B. Однако если вы замените круглые скобки на фигурные,
struct A { A(int x) : b{ x } {}
struct B { int x; } b; };
int main() { A a( 10 ); }
то код будет успешно компилироваться, так как объект b будет инициализирован как агрегат.
Теперь если в конструкторе заменить тип у параметра с int на A::B, то ситуация изменится.
Данная программа будет успешно компилироваться
struct A { struct B;
A(B x) : b( x ) {}
struct B { int x; } b; };
int main() { A::B b = { 10 }; A a( b ); }
так как структуры, которые являются агрегатами, имеют конструктор копирования, создаваемый компилятором неявно.
Иная ситуация складывается, когда членом данных, который представляет собой агрегат, является массив. Как и в случае со структурой, данная программа не будет компилироваться
struct A { struct B;
A(int x) : b( x ) {}
int b[1]; };
int main() { int b = 10; A a( b ); }
так как нет преобразования из целочисленного типа в массив.
Однако если заменить параметр на массив, не важно, является он ссылкой или нет, как показано ниже
struct A { struct B;
A(int x[1]) : b( x ) {}
int b[1]; };
int main() { int b[1] = { 10 }; A a( b ); }
или
struct A { struct B;
A(int ( &x )[1]) : b( x ) {}
int b[1]; };
int main() { int b[1] = { 10 }; A a( b ); }
то программа не будет компилироваться, так как в первом случае нет преобразования из указателя в массив, а во втором случае, когда параметр объявлен как ссылка, массивы не имеют конструктора копирования.
Для инициализации члена данных, который является массивом, можно использовать следующую запись
struct A { struct B;
A(int x) : b{ x } {}
int b[1]; };
int main() { int b = 10; A a( b ); }
Данная программа успешно скомпилируется. Однако вы не можете запись с фигурными скобками заключить еще в круглые собкки, как показано ниже
struct A { struct B;
A(int x) : b({ x }) {}
int b[1]; };
int main() { int b = 10; A a( b ); }
Компилятор выдаст сообщение об ошибке, так как, опять-таки, для массивов нет конструктора копирования. Однако для структур такая запись инициализации будет успешно воспринята компилятором, так как структуры, как агрегаты, имеют неявно объявленный компилятором конструктор копирования.
struct A { A(int x) : b({ x }) {}
struct B { int x; } b; };
int main() { int b = 10; A a( b ); }
Данная программа успешно скомпилируется.
Для арифметических типов инициализация с фигурными скобками не разрешает "сужение" значения, то есть использовать в качестве инициализатора значение, которое потенциально не может разместиться в инициализируемом объекте. Поэтому следующая программа не будет компилироваться
struct A { A(int x) : b{ x } {} short b; };
int main() { int b = 10; A a( b ); }
Причиной ошибки будет то, что объект типа short не в состоянии разместить все значения объекта типа int, то есть будет иметь место "сужение" инициализирующего значения.
Однако если заменить фигурные скобки на круглые, то программа успешно скомпилируется
struct A { A(int x) : b( x ) {} short b; };
int main() { int b = 10; A a( b ); }
Когда инициализируемый член класса является определенный пользователем тип, то в дело вступают конструкторы, которые имеют параметр типа std::initializer_list
Например, в приведенной ниже программе, когда нет такого конструктора, можно инициализировать член класса как b( x ), или как b{ x }, или даже как b( { x } )
struct A { A(int x) : b({ x }) {}
struct B { B(int x) { std::cout << "B( int )" << std::endl; } } b; };
int main() { int b = 10; A a(b); }
Однако если в классе присутствует конструктор с параметром типа std::initializer list, то для инициализаций вида b{ x } и b( { x } ) будет вызван именно он. А для инициализации вида b( x ) будет вызван другой конструктор.
Например, для этой программы
struct A { A(int x) : b( x ) {}
struct B { B(int x) { std::cout << "B( int )" << std::endl; } B(std::initializer_list) { std::cout << "B( std::initializer_list )" << std::endl; } } b; };
int main() { int b = 10; A a(b); }
будет выведено сообзение
B( int )
А для этой программы
struct A { A(int x) : b{ x } {}
struct B { B(int x) { std::cout << "B( int )" << std::endl; } B(std::initializer_list) { std::cout << "B( std::initializer_list )" << std::endl; } } b; };
int main() { int b = 10; A a(b); }
будет выведено сообщение
B( std::initializer_list )
Вообще, эта тема достаточно обширная.
О некоторых причудах инициализации я написал на своем сайте в конце темы Шутка - ложь, но в ней намек, добрым молодцам урок.

Корректировка анимации в Google Chrome

Задача перед мной стояла такая, скрыть 3 первых столбца в таблице, в итоге скрыл. Но отображение в Chrome странное, как только открываю страницу с таблицей примерно на 1 секунды появляются первые 3 столбца которые я скрыл, и как только 1 секунда проходит столбцы скрываются. Попробовал открыть в Мозиле там идеально работает, то есть открыл таблицу первых 3 столбцов не видно. Встречаюсь с таким впервые, как можно решить проблему ?
$(document).ready(function(){ $('#table td:nth-child(1)').css("display", "none"); $('#table td:nth-child(2)').css("display", "none"); ('#$table td:nth-child(3)').css("display", "none"); });


Ответ

Способ №1:
#table td:nth-child(1), #table td:nth-child(2), #table td:nth-child(3) {display:none;}

123

Способ №2:
$(function() { $('#table td:nth-child(1)').css("display", "none"); $('#table td:nth-child(2)').css("display", "none"); $('#table td:nth-child(3)').css("display", "none"); $('body').css("display", "block"); }); body {display:none;}
123

Освобождение памяти в Stack'e

Всем известно,что с Stack это некий участок памяти,который аллоцируется на каждый поток в виде размера 1МБ , в нем хранятся ссылки(ObjRef) на ReferenceType,пользовательские структуры,примитивные данные,ну и локальные переменные метода.
А теперь вопрос: что делает CLR, когда Stack полностью заполниться, и соответственно удалять по сути нечего.То бишь Stack переполнен?
Может ли CLR расширить его границы с 1МБ до 2МБ?(или это не возможно,в связи с чем,мы просто получим Exception, который оповестит нас о переполнении стека).
Другой вопрос: в контексте unsafe кода,unamanged участку памяти выделяется так же 1МБ или аллоцировать можно кастомный размер?


Ответ

Для начала стоит отметить что стек в момент выполнения кода - это не какой-то абстрактный safe-механизм. .NET использует JIT-компиляцию, так что в реальности выполняется код, привязанный к конкретной платформе, с использованием механизма стека этой платформы. В случае x86 - сегмент стека + пара регистров SS/ESP и операциями push/pop. Никакого отдельного стека для unsafe не создается.
Что происходит при заполнении стека и можно ли его увеличить по достижению лимита? Нет, в общем случае - нельзя.
Дело в том, что стек, по крайней мере в x86/64 - это структура данных, заполняемая с конца. Т.е. каждое помещение чего-то в стек сдвигает его указатель ближе к началу. Это идет из древних (еще до-.net) времен, когда памяти было мало, и стандартное разделение памяти выглядело так:
[код][данные-куча --> ....... пустое место....... <-- данные-стек]
Физическая память делилась между кучей и стеком, и у программиста всегда был выбор - выделить побольше памяти под что-то в куче, или положить побольше объектов в стеке. К тому же такая раскладка эффективно избавляла от необходимости контролировать размер отдельно кучи, и отдельно - стека. Т.к. если в ней куча и стек встретились - то памяти не осталось совсем.
С тех пор многое поменялось (хотя раскладка выше все еще актуальна на некоторых микроконтроллерах). В x86 Для стека теперь обычно выделен отдельный сегмент. Но он, по традиции, заполняется с конца. Т.е. каждая операция push уменьшает значение SP на размер положенного в стек.
По достижению ESP значения 0 - процессор выбрасывает ошибку. Механизма "довыделения памяти" в стеке в x86 нет - просто потому, что нельзя "довыделить" память в начало сегмента - а выделить память в конце и переложить все данные в стеке процессор не осмеливается - для него это слишком сложная операция. Это могла бы сделать операционная система, но по крайней мере Windows на x86 так не поступает.
На выходе по достижению 0 указателем стека вы получаете StackOverflowException в вашем коде .NET. Это индикатор достижения лимита "железного" стека, а не какого-то хитрого стека CLR.

Стоит отметить, что к StackOverflowException на x86 может привести также бесконечная рекурсия, причем даже в случае если вы не объявляете локальные переменные. Дело в том, что механизм вызовов методов на x86 (call) сохраняет в стеке адрес возврата из вызываемого метода. А оператор возврата (ret) достает адрес из стека. Поэтому слишком глубокая цепочка вызовов забивает стек.
Собственно, именно поэтому окно просмотра вызовов и называется Call Stack - информация цепочке возврата хранится только в стеке. Причем на x86 - в том же физическом стеке что и параметры фунций и локальные переменные.