Страницы

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

вторник, 18 декабря 2018 г.

Неожиданное переполнение константы там, где его быть не должно

Почему, когда я пишу вот такой код:
size_t VRamSize = 2048 * 1024 * 1024;
то получаю предупреждение "Переполнение константы"?
warning C4307: '*' : integral constant overflow
size_t у меня unsigned long long (самый большой тип), у него диапазон, внимание,
0 to 18,446,744,073,709,551,615
2048 * 1024 * 1024 = 2147483648 (посчитайте, насколько меньше знаков).
Что значит это предупреждение?


Ответ

В процессе самого умножения, вы перемножаете константы типа int, и только потом приводите результат к типу ull. Так что используйте соответствующие суффиксы (не знаю, какие они точно в студии), типа 1024llu
Или можно явно приводить тип сразу size_t(1024)*1024*2048

нажатие на Listview закрывает приложение при попытке обратиться к разметке элемента списка

У меня проблема с нажатием в Listview после прокрутки. То есть, если я нажимаю на содержимое, которое было изначально видно, то все ок. Но если я нажимаю прокрутив список (то есть нажимаю на позицию, которая видна не была), то программа вылетает вот с таким текстом в логах:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
Кто сталкивался?
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View itemClicked, int position, long id) { TextView tp = (TextView)listView.getChildAt(position).findViewById(R.id.userid); Log.v("mes",tp.getText().toString()); } });


Ответ

Ваша ошибка в том, что вы пытаетесь получить View из ListView. Так не надо. Нужное вам View, т.е. разметка элемента списка - уже передано в виде второго аргумента метода onItemClick(AdapterView parent, View itemClicked, int position, long id). Сделайте так:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View itemClicked, int position, long id) { TextView tp = (TextView)itemClicked.findViewById(R.id.userid); Log.v("mes",tp.getText().toString()); } });
А ещё лучше - повесьте слушатель внутри адаптера. А ещё лучше - перепишите под RecyclerView

Алгоритм перевода номера телефона

Сервер принимает ответ вида : +79521134356 Пользователь в EditText можент ввести , как 11 значный номер, так и 12 значный. Всего 3 типа.
+79521134356 - тогда гуд.
79521134356 - надо добавить +
89521134356 - надо изменить 8 на 7 и приписать +
Как это все реализовать?Помогите написать алгоритм или поделитесь им.


Ответ

public static void main(String[] args) { System.out.println(formatNumber("+79521134356")); System.out.println(formatNumber("79521134356")); System.out.println(formatNumber("89521134356")); System.out.println(formatNumber("+7-952-113-43-56")); System.out.println(formatNumber("+7 952 113 43 56")); System.out.println(formatNumber("+7?952.113.43:56")); System.out.println(formatNumber("+7_LOL_952_LOL_1134356")); System.out.println(formatNumber("12345")); }
private static String formatNumber(String s) { s = s.replaceAll("(\\D)*", ""); int len = s.length(); if (len >= 10) { s = s.substring(len - 10); s = "+7" + s; } else { System.out.println("Cлишком короткий номер: " + s); s = null; } return s; }
Вывод:
+79521134356
+79521134356
+79521134356
+79521134356
+79521134356
+79521134356
+79521134356
Cлишком короткий номер: 12345
null

Зачем нужен оператор default(T)?

При попытке вернуть из метода return new Size(); вылетает ошибка Do not use default value type constructor и предлагает заменить строку на return default(Size);. Как бы не проблема использовать default(T), только хочется понять какая разница?


Ответ

Вот связанное обсуждение: https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/1482
Дело в том, что для структур переопределение конструктора по умолчанию на текущий момент не разрешено. У структур всегда есть начальное значение (инициализированное нулями), которое может представлять собой «плохое», неправильное значение. Например, CancellationToken: его начальное значение совпадает с CancellationToken.None
Если вы используете синтаксис с new, это выглядит так, как будто бы вы создаёте хорошее, пригодное к использованию как и все другие значение. Синтаксис с default позволяет подчеркнуть, что это специальное неинициализированное значение.

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

Заметьте, что если разрешат конструкторы структур без параметров, отличие между new T() и default(T) станет более серьёзным: default(T) будет означать неинициализированное, прописанное нулями значение, а конструктор сможет выполнить добавочную инициализацию.

Как в EditText отделить разряды?

EditText используется для вывода больших чисел. Как сделать отделение каждых трех разрядов числа пробелом? Например 9 999 999


Ответ

Можно сделать это с помощью TextWatcher
Например, для форматирования номера телефона можно использовать готовый класс PhoneNumberFormattingTextWatcher, реализующий интерфейс TextWatcher
EditText inputField = (EditText) findViewById(R.id.inputfield); inputField.addTextChangedListener(new PhoneNumberFormattingTextWatcher());
В итоге вводимый текст +375298076740 будет выглядеть как
+375 29 807-67-40
Если же Вам нужно выводить текст группами именно по три символа, можете воспользоваться следующим классом:
public class OwnWatcher implements TextWatcher {
// Change this to what you want... ' ', '-' etc.. private static final char space = ' ';
@Override public void onTextChanged(CharSequence s, int start, int before, int count) { }
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
@Override public void afterTextChanged(Editable s) { // Remove spacing char if (s.length() > 0 && (s.length() % 4) == 0) { final char c = s.charAt(s.length() - 1); if (space == c) { s.delete(s.length() - 1, s.length()); } } // Insert char where needed. if (s.length() > 0 && (s.length() % 4) == 0) { char c = s.charAt(s.length() - 1); // Only if its a digit where there should be a space we insert a space if (Character.isDigit(c) && TextUtils.split(s.toString(), String.valueOf(space)).length <= 3) { s.insert(s.length() - 1, String.valueOf(space)); } } } }
И присвойте его конкретному полю:
inputField.addTextChangedListener(new OwnWatcher());
Вывод получится как на картинке:

Как сделать нестандартную форма блока?

Как можно сделать такую форму с помощью CSS?


Ответ

Если это элемент дизайна, то есть минимум 2 простых способа:
transform: skewX(-20deg); background-image: linear-gradient(-20deg, grey 90%, transparent 90%);
Если в блоке планируется текст со скошенным правым выравниванием, то вам нужно использовать shapes. Но методика экспериментальная, мало каким браузерами поддерживается. Вот статья на эту тему http://frontender.info/css-shapes/

Как влияет статическая и динамическая линковка на размер приложения?

Как именно влияет статическая и динамическая линковка с .dll\.lib на размер приложения?


Ответ

При динамической компоновке используются динамические же библиотеки. Они имеют расширение .dll и ничем по внутренней структуре не отличаются от исполняемого .exe-файла. Когда компоновщик имеет дело с динамической библиотекой, то он не берёт оттуда никаких кусков кода (чревато, ибо код машинный), а просто вставляет в компилируемую программу указания типа: «При загрузке программы разместить в указанном месте оперативной памяти адрес функции по имени «XXX» из библиотеки «YYY».
Статическая же библиотека (.lib-файл) — это просто архив с объектными файлами внутри. А компоновщику абсолютно без разницы, чьи объектные файлы использовать при компиляции — из родного проекта или из какого-то внешнего источника (необязательно даже статической библиотеки, отдельно лежащий объектный файл тоже сгодится). Если эти файлы особым образом подготовлены, то включаются только используемые функции (если особым образом помечены границы функций) или даже выполняются так называемые межмодульные оптимизации (если вместо машинного кода использовано высокоуровневое представление). При отсутствии же подобной подготовки будет включено всё содержимое статической библиотеки, даже неиспользуемое.

Для тех, кто не понял, о чём речь: компилятор и компоновщик — это две различные, хоть и последовательно работающие, программы. Первая преобразует каждый .cpp файлы в полуфабрикатный объектный файл, а вторая собирает объектные файлы в итоговый исполняемый файл.

IDEA не распознает классы и пакеты в модуле

После попытки создать (а потом и удалить) папку в директории src IDEA перестала распознавать классы и пакеты, как директории, однако раньше - все было в порядке.


Почему так происходит и как это исправить?

UPD_0:


Ответ

Нужно каталог src пометить как источник исходного кода https://www.jetbrains.com/help/idea/2016.2/configuring-content-roots.html Правой кнопкой мыши на каталог src - mark directory as "sources"
Каталог должен подсветиться голубоватым цветом, по аналогии с каталогом "java" в вашем модуле чуть ниже

Флаги, или аналог множества в C#, как лучше реализовать?

Есть некий метод, пусть public static bool IsNewFileActual(sting oldFile, string newFile, ComparsionFlags flags) сравнивающий 2 файла по набору критериев. Сами критерии, для наглядности, например, такие: сравнение по дате последней записи в файл, версия файла, MD5-хэш, размер файла.
В зависимости от некоторых условий, должна формироваться переменная flags, которая будет задавать флаги для критериев проверки (например, флаг проверки по номеру версии будет справедлив для *.EXE и *.DLL, а вот для *.PNG или *.HTML он не нужен).
В паскале (Delphi), я бы работал примерно так:
type TComparsionFlags = set of (cfDate, cfVersion, cfHash, cfSize); var CF : TComparsionFlags; ... CF := []; CF := CF + [cfVersion]; ... СF := CF + [cfHash, cfSize]; ... CF := CF - [cfDate]; ... if (cfDate in CF) then begin ... end;
Иными словами, описал бы множество с возможными флагами, и использовал бы средства языка для достижения своих целей.
Насколько я знаю, аналога паскалевских множеств в C# в чистом виде нет, и в качестве замены можно использовать enum, что я и делаю:
[Flags] public enum ComparsionFlags : byte { cfVersion = 1, cfSize = 2, cfDate = 4, cfHash = 8, }
После чего перед вызовом метода IsNewFileActual объявляю переменную ComparsionFlags flags и далее задаю флаги так:
flags = ComparsionFlags.cfSize | ComparsionFlags.cfDate | ComparsionFlags.cfHash;
Как по мне, так это не очень удобно (по меньшей мере, как минимум, не лаконично), как для задания самой переменной flags, так и для проверок значений, которые переданы в этой переменной внутрь метода.
Собственно, вопрос и в заголовке, и вот, более детально:
Как наилучшим образом реализовать тип ComparsionFlags для использования переменных данного типа в качестве набора флагов?
Может быть есть альтернативные, более удобные способы выполнить описанную задачу?
Буду признателен за внимание и дельные советы/ответы. Спасибо.
P.S. Думал про List и HashTable, но есть ощущение, что это несколько не то... Например, ничто не мешает добавить в List какой-то флаг n раз, и при удалении этого флага из списка придется просматривать его весь, и удалять все вхождения этого флага (или флагов), т.е. получаем, что нужно довольно много обвязки вокруг списка делать.


Ответ

Использование флагов выглядит достаточно лаконично. Если переписать код с Delphi, получится примерно так:
ComparsionFlags CF = default(ComparsionFlags);
CF = CF | ComparsionFlags.cfVersion; ... СF = CF | ComparsionFlags.cfHash | ComparsionFlags.cfSize; ... CF = CF & ~ComparsionFlags.cfDate; ... if (CF.HasFlag(ComparsionFlags.cfDate)) { ... }
Если использовать using static, то имя enum можно опускать:
using static ComparsionFlags; ...
ComparsionFlags CF = default(ComparsionFlags);
CF |= cfVersion; ... СF |= cfHash | cfSize; ... CF &= ~cfDate; ... if (CF.HasFlag(cfDate)) { ... }
В противовес, можно использовать класс HashSet, как указано в соседнем ответе:
HashSet flags = new HashSet();
CF.Add(ComparsionFlags.cfVersion); ... СF.UnionWith(new[]{ComparsionFlags.cfHash,ComparsionFlags.cfSize}); ... CF.Remove(ComparsionFlags.cfDate); ... if (CF.Contains(ComparsionFlags.cfDate)) { ... }
Как можно заметить, в этом случае не обязательно делать значения enum флагами, то есть значения могут идти и подряд: 1,2,3..., а не 1,2,4...

Как узнать размер массива переданного в функцию? [дубликат]

На данный вопрос уже ответили: Передача статического одномерного массива определённого размера в функцию 6 ответов Необходимо определить размер массива, переданного в функцию. Пробовал вот так:
void foo(int* Array) { const unsigned int SIZE = sizeof(Array)/sizeof(int); }
но в SIZE сохраняется 1, независимо от размера массива. Можно, конечно, вместе с массивом передать в функцию и его размер, но может существует более изящное решение?
P.S.: Кстати, заметил нечто странное. Запускал эту программу через Visual Studio и Qt. В VS в SIZE сохраняется 1, а в Qt 2.


Ответ

У вас параметр функции foo объявлен как указатель типа int *
void foo(int* Array); ^^^^^^^^^^
Следовательно внутри функции выражение
sizeof(Array)/sizeof(int)
эквивалентно выражению
sizeof(int *)/sizeof(int)
Если, например, размер указателя, то есть типа int *, равен 8 байтам, а размер типа int равен 4 байтам, то в итоге вы получите 2. Если же при этом размер типа int равен также 8 байтам (64-битовая ОС), то вы получите в итоге 1.
Но даже если вы объявите эту функцию как
void foo(int Array[]);
или даже так
void foo(int Array[10]);
все равно параметр функции неявно преобразуется в указатель на элемент массива. То есть эти два объявления функции объявляют одну и ту же функцию и эквивалетны следующему объявлению
void foo(int* Array);
Так что внутри функции вы снова будете иметь дело с указателем.
Когда массив передается по значению, то вам следует также объявлять второй параметр, который задает размер массива.
Или массив должен иметь некоторый граничный элемент с уникальным значением, по которому можно определить число актуальных элементов, как это имеет место, например, со строками, когда строки завершаются нулем, то есть символом '\0'
То есть в общем случае вам следует объявлять функцию как
void foo(int* Array, size_t n);
где n - это размер массива.
Другой подход - это объявлять параметр как ссылку на массив. В этом случае длина массива будет известна внутри функции. Например
void foo( int ( &Array )[10] ) { const size_t = sizeof( Array)/ sizeof( *Array ); }
Недостаток этого объявления состоит в том, что эта функция может иметь дело только с массивами, заданного в ее параметре размера.
Чтобы обойти это ограничение, вы можете объявить шаблонную функцию. Например,
template void foo( int ( &Array )[N] ) { const size_t = N; }
В этом случае компилятор, используя шаблон, создаст столько функций, сколько массивов разной длины были использованы в качестве аргумента.

Как передать данные “загрузки” cpu в программу на с\с++?

Суть в следующем: я хочу передать в программу на с\с++ данные о загрузке cpu или gpu(например, температуру) на linux(ubuntu 16.04), но не используя при этом посторонних утилит типа lm sensors. Т.е. я хочу извлекать данные напрямую с датчиков(если это возможно) и передавать их в программу для дальнейших действий, либо как-то получать эти данные в процессе работы программы. Видел много ответов по поводу подобных действий с использованием winapi, но под linux что-то не нашел(или проглядел). А теперь, внимание, вопрос: мб кто-то сталкивался с этим\писал что-то подобное\знает что гуглить на эту тему или даже вдруг знает, как это реализовать? Заранее благодарен!


Ответ

Непосредственно с датчиков вы эти данные никак не получите. Ядро linux не позволит пользовательскому приложению обращаться напрямую к оборудованию. Кроме того, вам фактически придется реализовывать собственный lm_sensors, потому как на разных чипсетах данные получаются различным образом и по факту нужны драйвера для каждого конкретного датчика. Драйвера датчиков в linux уже есть и они как раз зовутся lm_sensors (ядерная часть, а не утилита). Обратите внимание, в windows точно так же, есть драйвера в ядре и есть интерфейс winapi.
В linux получить всю информацию от драйверов датчиков, а так же управлять некоторыми параметрами (скоростью вращения вентиляторов и пределами) можно через файловый интерфейс /sys/class/hwmon и /sys/bus/platform/devices/coretemp.0. Описание интерфейса можно найти в файле Documentation/hwmon/sysfs-interface исходников ядра.
Загрузку процессоров можно посчитать на основе данных из файла /proc/stat. Описание этого интерфейса можно найти в Documentation/filesystems/proc.txt исходников ядра.