LINUX.ORG.RU

Сообщения u5er

 

Проверка большого числа условий на си

Сейчас я пишу такой код:

	if( phonebookEntry->index < 0 && phonebookEntry->telNo && !phonebookEntry->name ){
		//только телефон
	}else if( phonebookEntry->index < 0 && phonebookEntry->telNo && phonebookEntry->name ){
		//телефон и имя
	}else if( phonebookEntry->index >= 0 && !phonebookEntry->telNo && !phonebookEntry->name ){
		//только индекс
	}else if( phonebookEntry->index >= 0 && phonebookEntry->telNo && !phonebookEntry->name ){
		//индекс и телефон
	}else if( phonebookEntry->index >= 0 && phonebookEntry->telNo && phonebookEntry->name ){
		//индекс, телефон и имя
	}else{
		//недопустимое сочетание
	}

И я заметил, что в каждом условном операторе сразу проверяется случая и подумал, а что если поступить вот так:

	unsigned int condition = 0;
	
	if( phonebookEntry->index >= 0 ) condition |= 1;
	if( phonebookEntry->telNo      ) condition |= 1 << 1;
	if( phonebookEntry->name       ) condition |= 1 << 2;

И дальше переменную condition запихнуть в switch или вообще использовать в качестве индекса в массиве указателей? Мой случай ещё пограничный, но если добавить ещё один параметр, то вариантов уже будет 16! Короче, степень двойки. Я один такой упоротый или такое где-нибудь применяется?

 

u5er
()

Функции с переменным числом аргументов: va_arg vs void*

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

int api1( unsigned int id, ... );
int api2( unsigned int id, const void* arg );

В случае api1 предполагается передавать набор аргументов в зависимости от id.

В случае api2 предполагается передавать указатель на некую структуру, которая будет отличаться в зависимости от id и в которой будет виден весь список аргументов.

Пока что склоняюсь ко второму способу, потому что, во-первых, структуру можно будет объявить заранее статически, а во-вторых, виден список аргументов. Цена вопроса - размер указателя.

А какой вариант предпочли бы вы? Или может существуют ещё способы?

 

u5er
()

Рисовалка битмапов на тикле

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

Перемещение фукуса стрелочками. Для рисования/стирания пикселя используется пробел. По нажатию кнопки «Dump» в консоль выплёвывается последовательность 0 и 1 в виде текста, которую дальше можете сконвертировать в тот формат, который вам нужен.

Пример использования https://0x0.st/Kf8v.png

#!/usr/bin/wish

##########################
###   settings start   ###


set bitmapWidth  32
set bitmapHeight 32


###    settings end    ###
##########################

set currentFocusX 0
set currentFocusY 0

set verticalSymmetry   0
set horizontalSymmetry 0
set diagonalSymmetry   0


ttk::style layout pixel.TCheckbutton {
	Checkbutton.indicator
	Checkbutton.focus
}


proc focusUp { } {
	
	if { $::currentFocusY > 0 } {
		incr ::currentFocusY -1
	}
	
	focus .checkboxArea.pixelr${::currentFocusY}c${::currentFocusX}
}

proc focusDown { } {
	
	if { $::currentFocusY < [expr $::bitmapHeight - 1] } {
		incr ::currentFocusY
	}
	
	focus .checkboxArea.pixelr${::currentFocusY}c${::currentFocusX}
}

proc focusLeft { } {
	
	if { $::currentFocusX > 0 } {
		incr ::currentFocusX -1
	}
	
	focus .checkboxArea.pixelr${::currentFocusY}c${::currentFocusX}
}

proc focusRight { } {
	
	if { $::currentFocusX < [expr $::bitmapWidth - 1] } {
		incr ::currentFocusX
	}
	
	focus .checkboxArea.pixelr${::currentFocusY}c${::currentFocusX}
}

proc shiftUp { } {
	
	for { set rowNo 1 } { $rowNo < $::bitmapHeight } { incr rowNo } {
		
		set rowNoTo [expr $rowNo - 1]
		
		for { set colNo 0 } { $colNo < $::bitmapWidth } { incr colNo } {
			set ::pixelr${rowNoTo}c${colNo} [ set ::pixelr${rowNo}c${colNo} ]
		}
	}
}

proc shiftLeft { } {
	
	for { set colNo 1 } { $colNo < $::bitmapWidth } { incr colNo } {
		
		set colNoTo [ expr $colNo - 1 ]
		
		for { set rowNo 0 } { $rowNo < $::bitmapHeight } { incr rowNo } {
			set ::pixelr${rowNo}c${colNoTo} [ set ::pixelr${rowNo}c${colNo} ]
		}
	}
}
proc shiftRight { } {
	
	if { $::bitmapWidth < 2 } return
	
	for { set colNo [expr $::bitmapWidth - 2] } { $colNo >= 0 } { incr colNo -1 } {
		
		set colNoTo [ expr $colNo + 1 ]
		
		for { set rowNo 0 } { $rowNo < $::bitmapHeight } { incr rowNo } {
			set ::pixelr${rowNo}c${colNoTo} [ set ::pixelr${rowNo}c${colNo} ]
		}
	}
}

proc shiftDown { } {
	
	if { $::bitmapHeight < 2 } return
	
	for { set rowNo [expr $::bitmapHeight - 2] } { $rowNo >= 0 } { incr rowNo -1 } {
		
		set rowNoTo [ expr $rowNo + 1 ]
		
		for { set colNo 0 } { $colNo < $::bitmapWidth } { incr colNo } {
			set ::pixelr${rowNoTo}c${colNo} [ set ::pixelr${rowNo}c${colNo}]
		}
	}
}



proc setAllPixelsValue { value } {
	for { set rowNo 0 } { $rowNo < $::bitmapHeight } { incr rowNo } {
		for { set colNo 0 } { $colNo < $::bitmapWidth } { incr colNo } {
			set ::pixelr${rowNo}c${colNo} $value
		}
	}
}

proc verticalSymmetryHandler { rowNo colNo } {
	set mirrorCol [ expr $::bitmapWidth - $colNo - 1 ]
	set ::pixelr${rowNo}c${mirrorCol} [ set ::pixelr${rowNo}c${colNo} ]
}

proc horizontalSymmetryHandler { rowNo colNo } {
	set mirrorRow [ expr $::bitmapHeight - $rowNo - 1 ]
	set ::pixelr${mirrorRow}c${colNo} [ set ::pixelr${rowNo}c${colNo} ]
}

proc diagonalSymmetryHandler { rowNo colNo } {
	
	set diagonalRow [ expr $::bitmapWidth - $rowNo - 1 ]
	set diagonalCol [ expr $::bitmapWidth - $colNo - 1 ]
	
	set ::pixelr${diagonalRow}c${diagonalCol} [ set ::pixelr${rowNo}c${colNo} ]
}
 
proc symmetryHandler { rowNo colNo } {
	
	if { $::verticalSymmetry } {
		verticalSymmetryHandler $rowNo $colNo
	}
	
	if { $::horizontalSymmetry } {
		horizontalSymmetryHandler $rowNo $colNo
	}
	
	if { $::diagonalSymmetry } {
		diagonalSymmetryHandler $rowNo $colNo
	}
}

proc dumpPixelmap { } {
	
	puts ""
	
	for { set rowNo 0 } { $rowNo < $::bitmapHeight } { incr rowNo } {
		for { set colNo 0 } { $colNo < $::bitmapWidth } { incr colNo } {
			puts -nonewline [set ::pixelr${rowNo}c${colNo}]
		}
	}
	
	puts ""
	puts ""
}

proc buildCheckboxArea { } {
	
	for { set rowNo 0 } { $rowNo < 32 } { incr rowNo } {
		
		for { set colNo 0 } { $colNo < 32 } { incr colNo } {
			
			ttk::checkbutton .checkboxArea.pixelr${rowNo}c${colNo} -style pixel.TCheckbutton -variable pixelr${rowNo}c${colNo} -command "symmetryHandler $rowNo $colNo"
			grid .checkboxArea.pixelr${rowNo}c${colNo} -row $rowNo -column $colNo
			
			set ::pixelr${rowNo}c${colNo}  0
			
		}
	}
}


proc buildGui { } {
	
	set buttonsPaddingY 30
	
	# window layout
	ttk::frame .checkboxArea
	ttk::frame .controlPanel
	grid .checkboxArea  -row 0 -column 0 -padx 10 -pady 10
	grid .controlPanel  -row 0 -column 1 -padx 10 -pady 10
	
	#chechbox area build
	buildCheckboxArea
	
	#control panel
	
	#sel clear
	ttk::button .controlPanel.allClear -text "All clear" -command { setAllPixelsValue 0 }
	ttk::button .controlPanel.allSet   -text "All set"   -command { setAllPixelsValue 1 }
	
	grid .controlPanel.allClear -row 0 -column 0
	grid .controlPanel.allSet   -row 10 -column 0
	
	
	#shift panel
	ttk::frame .controlPanel.shift
	grid .controlPanel.shift  -row 20 -column 0 -pady $buttonsPaddingY
	
	
	ttk::button .controlPanel.shift.up    -text "/\\" -command shiftUp 
	ttk::button .controlPanel.shift.left  -text "<"   -command shiftLeft
	ttk::button .controlPanel.shift.right -text ">"   -command shiftRight
	ttk::button .controlPanel.shift.down  -text "\\/" -command shiftDown
	
	grid .controlPanel.shift.up    -row 0 -column 1
	grid .controlPanel.shift.left  -row 1 -column 0
	grid .controlPanel.shift.right -row 1 -column 2
	grid .controlPanel.shift.down  -row 2 -column 1
	
	
	#symmetry settings
	ttk::frame .controlPanel.symmetry
	grid       .controlPanel.symmetry -row 30 -column 0 -pady $buttonsPaddingY
	
	ttk::checkbutton .controlPanel.symmetry.vertical   -text "Вертикальная симметрия"   -variable verticalSymmetry
	ttk::checkbutton .controlPanel.symmetry.horizontal -text "Горизонтальная симметрия" -variable horizontalSymmetry
	ttk::checkbutton .controlPanel.symmetry.diagonal   -text "Диагональная симметрия" -variable diagonalSymmetry
	
	grid .controlPanel.symmetry.vertical   -pady 5
	grid .controlPanel.symmetry.horizontal -pady 5
	grid .controlPanel.symmetry.diagonal   -pady 5
	
	
	#dump
	ttk::button .controlPanel.dump     -text "Dump"      -command { dumpPixelmap }
	grid .controlPanel.dump     -row 100 -column 0 -pady $buttonsPaddingY
	
}



buildGui


bind . <KeyPress-Up>    { focusUp    }
bind . <KeyPress-Left>  { focusLeft  }
bind . <KeyPress-Down>  { focusDown  }
bind . <KeyPress-Right> { focusRight }

 , ,

u5er
()

В каком формате вы пишете документацию к своим проектам?

Интересуюсь потому, что сам подумываю начать писать полноценную. Вопрос задан не в контексте «какие варианты возможны», а в контексте «какие варианты реально используются».

Сам пока поглядываю в сторону markdown, т.к. в нём в нём есть подсветка и можно вставлять картинки. Иногда в этом есть необходимость, т.к. они нагляднее, чем псевдографика.

 

u5er
()

Посоветуйте литературу по программированию qemu

Хочется почитать что-то вроде «Linux Device Drivers», но только для qemu. Хочу эмулировать свою кастомную плату с произвольной периферией, поэтому ищу «обзорную» информацию с объяснением общих принципов написания кода для qemu.

 , ,

u5er
()

Переносимость спецификаторов функций *printf

Есть некий код

uint32_t value;
...
printf( "FATAL: Unknown security result: %u\n", value );

Под одну архитектуру это собирается без ошибок. Под другую сборка падает с ошибкой вида

format '%u' expects argument of type 'unsigned int', but argument 2 has type 'uint32_t' {aka 'long unsigned int'}

Как быть в случаях, когда подобный код должен собираться под разные архитектуры? Заворачивать всё в препроцессор или засучить рукава и писать свою нестандартную библиотеку си?

 ,

u5er
()

Какие функции для работы с файлами на си вы предпочитаете?

И почему?

Те, которые работают с fd, или те, которые работают с FILE.

Чисто из любопытства.

 

u5er
()

А существуют ли в открытом доступе тесты для алгоритмов?

Допустим, я решил реализовать какой-нибудь алгоритм. Например, декодер ogg, распаковщик gzip или ещё что-нибудь. Я полез читать документацию и писать код. Допустим, код не работает и я не знаю, где я допустил ошибку. Как правило, в документации описаны операции, которые нужно совершить над входными данными, а вот с примерами прям совсем туго.

Есть ли наборы тестов, которые содержат некие «референсные» данные, которые должны получаться после каждой операции? Для того, чтоб можно было ввести заранее известные данные, которые на каждом этапе в программе будут давать заранее известный результат, чтоб можно было найти то место в программе, где код написан с ошибкой. Если кто знает, поделитесь ссылками, пожалуйста.

u5er
()

Напоминание о необходимости отключать вентиляторы охлаждения при продувке от пыли

Не так давно купил себе салазки для жёстких дисков в отсек 5.25. В них есть вентилятор охлаждения и кнопка для отключения диска. Когда я отключаю диск кнопкой, то светодиод-индикатор питания светится в «полнакала» ещё полсекунды. Суть в том, что вентилятор будет работать как генераор, если его раскрутить.

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

Довольно давно читал в сети истории об убитых материнках при продувке воздухом. В них как раз описывался этот эффект. Теперь воочую убедился в этом сам и держу в курсе :)

 

u5er
()

Как добавить диск в steam, если он не добавляется через настройки.

На статью не тянет, но с этой проблемой сталкиваются часто, поэтому решил вкинуть немного полезной инфы, чтоб она была в рускоязычном сегменте сети.

Форматируете диск желательно в линуксовую файловую систему. Не используйте ntfs или fat32, иначе рискуете огрести проблем. Организовываете его постоянное монтирование. Монтирование должно выполняться без опции noexec, потому что для работы требуются права на выполнение. Для примера мы будем считать, что диск смонтирован /media/disk0.

Далее в /media/disk0 создаёте новую директорию, в которой будет библиотека стима. Для примера мы будем считать, что директория называется steamlib. Далее назначем владельцем этой директории того пользователя, который будет пользоваться этой библиотекой.

Теперь выключаем стим. В домашнем каталоге ищем файл libraryfolders.vdf по пути .steam/steam/steamapps. Открываем его текстовым редактором.

Вот его основной синтаксис:

"libraryfolders"
{
	"0"
	{
		"path"		"/media/hdd0/steam/.local/share/Steam"
		"label"		""
	}
	"1"
	{
		"path"		"/media/ssd0/steam/library"
		"label"		""
	}
}

Открыв реальный файл, вы увидите, что он несколько отличается: в нём есть гораздо больше информации, чем я привёл, но это не должно вас сбить с толку, поскольку вся остальная информация добавляется стимом динамически.

Уже на данном этапе должно быть понятно, что нужно сделать - дописать в файл путь до новой директории с библиотекой стим по аналогии с тем, что там уже есть. Пишете двойные кавычки и число в них на единицу больше от того, что в предыдущих двойных кавычках. Далее блок из фигурных скобок с полями path и label. label оставляете пустым, а в path прописываете путь до нового диска. В нашем случае это будет примерно так:

"libraryfolders"
{
	"0"
	{
		"path"		"/media/hdd0/steam/.local/share/Steam"
		"label"		""
	}
	"1"
	{
		"path"		"/media/ssd0/steam/library"
		"label"		""
	}
	"2"
	{
		"path"		"/media/disk0/steamlib"
		"label"		""
	}
}

Сохраняете изменения, запускаете стим. Больше ничего делать не нужно - новая директория уже будет доступна в библиотеке стима.

Еще один нюанс есть:

При ручном добавлении автоматически не будет создана /media/ssd0/steam/library/steamapps, из-за чего при попытке поставить игру на такой диск стим выгрунется ошибкой записи (хотя перенос игры через стим сработает и создаст эту директорию).

 

u5er
()

Почему удалили тему?

https://www.linux.org.ru/forum/general/17938729

Пользователя забанить - это одно, но в самой теме вроде нет никаких нарушений.

Чисто из любопытства интересуюсь.

 

u5er
()

tk scaling игнорируется

Что бы я туда не прописывал - визуально ничего не меняется. Есть идеи, почему это может быть так?

Версия 8.6.14_1.

 

u5er
()

Нелогичная логика

Куприв!

Пишу я тут очередной ляс и в процессе компиляции компилятор и даже линковщик(!) выдаёт мне такие предупреждения:

cc -Wall -O2   -c -o sim7600-at.o sim7600-at.c
sim7600-at.c: In function 'simApplicationToolkit':
sim7600-at.c:1013:17: warning: implicit declaration of function 'gets'; did you mean 'fgets'? [-Wimplicit-function-declaration]
 1013 |                 gets( userAns );
      |                 ^~~~
      |                 fgets
cc -s  sim7600-at.o utils_pdu_sms.o   -o sim7600-at
/usr/bin/ld: sim7600-at.o: in function `simApplicationToolkit':
sim7600-at.c:(.text+0xf91): warning: the `gets' function is dangerous and should not be used.

Справедливо, но тогда почему нет подобного предупреждения при использовани strncpy, например, которая тоже дырявая, даже не смотря на n?

 

u5er
()

Вопрос по настройке полосы прокрутки gtk

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

Смотрел документацию.
https://docs.gtk.org/gtk3/class.Settings.html#properties
https://docs.gtk.org/gtk4/class.Settings.html#properties
Но не нашёл там подходящих настроек.

Каким образом можно отключить такое поведение?

 

u5er
()

uBlock Origin в хроме уже всё, а божья коровка ещё не готова

https://www.opennet.ru/opennews/art.shtml?num=62859

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

 

u5er
()

Кто-нибудь из форумчан на практике сталкивался с ошибкой при работе sprintf()?

Вопрос в заголовке. Если да, то распишите подробности. В манах пишут про отрицательное значение при ошибке, но списка errno нет.

Вопрос снят. Судя по ответам в теме и поиску в сети, есть смысл избегать следующих функций в критически важном коде: printf(), fprintf(), dprintf(), sprintf(), snprintf(), vprintf(), vfprintf(), vdprintf(), vsprintf(), vsnprintf(). Эти функции имеют общую man-страницу printf(3) и в ней указано, что эти функции могут завершаться с ошибкой, но при этом не приводится списка возможных ошибок, поэтому невозможно предусмотреть ошибки заранее.

 

u5er
()

Отрыгнула клавиатура - как такое возможно?

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

Поделитесь опытом - у кого-нибудь вот так запросто умирали клавы?

u5er
()

Как организовать автовыгрузку из свопа?

Ситуация следующая. Запускается программа А, которая занимает какую-то часть памяти. Запускается программа Б, которой не хватает оставшейся свободной памяти, поэтому программа А отправляется в своп. После закрытия программы Б, программа А остаётся в свопе и из-за этого люто тормозит. Приходится делать swapoff -a и swapon -a чтоб вернуть прежнюю отзывчивость.

Вопрос: есть ли способы настроить поведение таким образом, чтоб при освобождении памяти система автоматически доставала данные из свопа не дожидаясь момента, когда они понадобятся?

 

u5er
()

Ищу набор тестов для проверки парсера UTF-8

Организовал я свой велопарсер текста c кодировкой UTF-8. Теперь я хочу его проверить. Существуют ли в природе «эталонные» строки, по которым можно протестировать парсер? В сети нашёл только это https://www.w3.org/2001/06/utf-8-wrong/UTF-8-test.html

 ,

u5er
()

Подскажите по алгоритму обработки массива с дырками.

Допустим, есть некий массив вида

{ data, data, NULL, data, data, NULL, data }

То есть это как бы обычный массив с данными, но в нём есть «дырки». Пытаюсь организовать доступ к этому массиву так, чтоб он был виден как массив без дырок

{ data, data, data, data, data }

Моих куриных мозгов пока хватило только на то, чтоб организовать «транслятор» - массив, который будет содержать в себе индексы ячеек с данными

{ 0, 1, 3, 4, 6 }

В сети ничего путного не моуй найти. Подскажите, как грамотно называются такие массивы? Также буду благодарен, если накидаете умных слов по теме для самообучения и литературу, где описываются методы работы с такими данными.

 ,

u5er
()

RSS подписка на новые темы