LINUX.ORG.RU

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

 


2

4

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

	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! Короче, степень двойки. Я один такой упоротый или такое где-нибудь применяется?

★★★
Ответ на: комментарий от bugfixer

Приводил выше. Лучше вы при всём желании не сделаете

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

anonymous
()
Ответ на: комментарий от anonymous
Оптимизация для

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


if( phonebookEntry->index >= 0 && phonebookEntry->telNo ) {

 if ( !phonebookEntry->name ) 
  индекс и телефон
 else 
  индекс, телефон и имя

}
anonymous
()
Ответ на: комментарий от anonymous

Немного о читабельности кода

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{
//недопустимое сочетание
}
anonymous
()
Ответ на: комментарий от yars068

нужно писатьbreak;

Это понятно, речь то шла об использовании меток при преобразовании в ассемблер.

Грубо говоря, если мы положили яблоко на стол и потом подносим к нему другие яблоки и сравниваем то создаётся ощущение что первое сравниваемое яблоко ложится 1 раз, а другие подносим, вроде как экономнее, чем каждый раз подносить по два яблока, как в условии else ifгде нужно каждый раз указывать обе переменные. Но на самом деле это кажущаяся экономия, в ассемблере это всё равно будут прыжки между метками и сравнение обоих переменных, там нет switch.

AZJIO
()

На мой взгляд, если дать битовым маскам внутри свитча нормально читаемые названия, то код будет лучше, чем пачка условий в else if’ах. И лучше, и читаемее.

Но это если не оставлять в метках месиво из 0 и 1 и всё через enum’ы использовать, чтобы не надо было туда-сюда прыгать, чтобы понять, что происходит.

Ivan_qrt ★★★★★
()
Ответ на: комментарий от u5er

snprintf возвращает число байт в буфере, которое займёт выражение. Это делает его удобным для собирания строк в буфере. Так что я бы сделал что-то вроде

res = 0;

#define append(format, ...) \
  do { \
    int r = snprintf(gsmService->atCmdBuffer + res, AT_CMD_BUFFER_SIZE - res, format, __VA_ARGS__); \
    res += r; \
    if (r < 0 || res > AT_CMD_BUFFER_SIZE) return -1; \
  }

append("AT+CPBW=");

if (phonebookEntry->index >= 0)
  append("%i", phonebookEntry->index);
  
if (phonebookEntry->telNo)
  append(
      ",%s,%i",
      phonebookEntry->telNo,
      phonebookEntry->telNo == '+' ? 145 : 129
  );

if (phonebookEntry->name) {
  if (packUtf82Ucs2(phonebookEntry->name, gsmService->codecBuffer, CODEC_BUFFER_SIZE) < 0)
    return -1;
  append(",\"%s\"", gsmService->codecBuffer);
};

append("\r");

#undef append
Jini ★★
()
Ответ на: комментарий от Jini

Так а я в курсе. Такой вариант я бы предпочёл в том случае, если бы вариантов было бы больше. Поскольку вариантов не так много, то я решил печатать всю команду целиком.

u5er ★★★
() автор топика

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

Я один такой упоротый или такое где-нибудь применяется?

Только тут https://ru.wikipedia.org/wiki/International_Obfuscated_C_Code_Contest

vtVitus ★★★★★
()
Ответ на: комментарий от vtVitus

Первый вариант плохой, второй вариант безобразный.

Про второй вариант я соглашусь, но что не так с пераый? Если он плохой, то как должен выглядеть хороший и отличный?

u5er ★★★
() автор топика
Ответ на: комментарий от unC0Rr

while(false) забыл. И запятые лишние в строке, если первое условие не выполняется.

while (false) забыл, да. Но запятые были в исходном сообщении — наверное, такой синтаксис у AT-команды.

Jini ★★
()
Ответ на: комментарий от u5er

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

if( __hasPhoneOnly(phonebookEntry) ){}
else if( __hasPhoneWithName(phonebookEntry) ){}
else if( __hasIndexOnly(phonebookEntry) ){}
else if( __hasPhoneWithIndex(phonebookEntry) ){}
else if( __hasFull(phonebookEntry) {}else{
__logFail()
}

Прозрачнее, комментарии не нужны, и т.д. 25 лет назад я бы написал как-нить так -

Error r = !__phoneOnlyInfo(phonebookEntry) &&
!__phoneWithNameInfo(phonebookEntry) && 
!__indexOnlyInfo(phonebookEntry) &&
!__fullPhoneInfo(phonebookEntry);
if (r) {
__logFail(r);
}

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

vtVitus ★★★★★
()
Последнее исправление: vtVitus (всего исправлений: 2)
Ответ на: комментарий от vtVitus

Но гораздо проще выставлять клоунов :-)))

Клоуна я поставил не сразу - это раз. А два - я поставил его с целью добиться от тебя пояснений, почему первый код плохой. Потому что я видел, что ты заходил на лор после того, как я задал вопрос, а ответа так и не дал. Как видишь - это сработало ;) Так что спасибо за развёрнутый ответ.

u5er ★★★
() автор топика
Ответ на: комментарий от qulinxao3

проверка многих условий на алгол-68 (стр.65/350 из книжки Pame.pdf «Programming algol-68 made easy», с примерами под Algol68toc реализацию)

полная форма:

IF n = 1  THEN action1
ELIF n = 2 THEN action2
ELIF n = 3 THEN action3
ELSE action4
FI

сокращенная форма:

(n=1|action1|(n=2|action2|(n=3|action3|action4)))

вариант с CASE:

 CASE n IN
   action1, action2, action3
 OUT action4
 ESAC

сокращенная форма:

(n|action1,action2,action3|action4)

вариант с вложенным CASE типа

CASE n MOD 4 
IN print("case 1"), 
   print("case 2"),
   print("case 3")
OUT
 CASE (n-10) MOD 4
 IN 
  print("case 11"),
  print("case 12"),
  print("case 13")
 OUT
  print("other case")
 ESAC
ESAC

можно заменить как с ELIF конструкцию OUT CASE ... ESAC ESAC на сокращенную: OUSE ... ESAC
и получается

CASE n MOD 4 
IN print("case 1"), 
   print("case 2"),
   print("case 3")
OUSE (n-10) MOD 4
 IN 
  print("case 11"),
  print("case 12"),
  print("case 13")
 OUT
  print("other case")
ESAC

вычисление дней в календаре:

INT days = CASE month IN
              31,
              IF year MOD  4 = 0 & year MOD 100 /= 0 OR year MOD 400=0
              THEN 29
              ELSE 28
              FI,
              31,30,31,30,31,31,30,31,30,31
              OUT -1
          ESAC

или сокращ:

 INT days = (month|31,(year%*4=0 & year%*/=100 OR year%*400=0|29|28),31,30,31,30,31,31,30,31,30,31|-1)
;

мало где в современных недоязычках можно сокращ так. крч, кртксть -стср тлнт!
битхаки сишки на BITS строках алголистых это жалкая имитация левой ноги алголистой!

anonymous
()
Ответ на: комментарий от qulinxao3

Btree алголистое сбалансированное сортировки строк по частоте (Pame.pdf, pg.211/350):

MODE WORD = STRUCT(STRING wd, INT ct, REAL fq),
     TREE = STRUCT(REF WORD w, REF TREE left,right);

 REF TREE leaf = NIL
 
PROC add word = (REF REF TREE root, REF WORD w)VOID:
  IF root IS leaf THEN root:=HEAP TREE:=(w,leaf,leaf)
  ELIF wd OF w < wd OF w OF root
  THEN add word(left OF root,w)
  ELIF wd OF w > wd OF w OF root
  THEN add word(right OF root,w)
  ELSE ct OF w OF root+:=1
  FI

PROC print tree=(REF FILE f, REF REF TREE root)VOID:
 IF root ISNT leaf
 THEN print tree(f,left OF root);
      put(f,(wd OF w OF root, ct OF w OF root, newline));
      print tree(f,right OF root)
 FI

переписать в сокращ форме – как упражнение для сознательного читателя (там очевидно, лолЪ) :)))

(?:) можно ли тогда битхаки флагов свитчкейзов с 2^n состояний задавать сразу текстом дерева?

в общем, у алгола-60 хоть и есть ООП (который называется симула-67) – но алголу-68 явно не хватает лисповых AST макросов, dyadic операторами тут не сильно отделаешься :))))

сразу видно откуда у баша ноги растут :)) а все эти сишкопаскали по сути есть лишь недоделанный алгол-68, зело упрощ но не сокращ AST :)

anonymous
()
Ответ на: комментарий от qulinxao3

STRING тут сам по себе всего лишь динамический массив байтолитер:

REF STRING s = LOC STRING

~

REF FLEX[]CHAR s = LOC FLEX[1:0]CHAR

с индексами от единицы, или [@0] с индексами от нуля:

[]CHAR digits="0123456789abcdef"[@0];
PROC itostr=(INT n,r)STRING:
(n<r|digits[n]|itostr(n%r,r)+digits[n%*r])

тащемта, зело на блямбды похоже.

anonymous
()

Я один такой упоротый или такое где-нибудь применяется?

switch-технологию А.Шалыто хочешь ты.
чтобы флаги в схему связей конечного автомата в функцию с переменными единообразно, а не как-то так.

anonymous
()
Ответ на: комментарий от qulinxao3

я наверное, на новый год зимними холодными вечерами поставлю Debian 12 bookworm «книгочей» WindowMaker LiveCD и из Debian Sid gcc-snapshot-…*.deb со всеми конпеляторами: c,c++,obj c/c++,gccrs,gccgo,gdc,gm2 (modula-2), gnat(ada),gcobol,ga68(algol-68) и до кучи, старый каноничный gpc/fpc и p2,p3,p4,p5,pascaline, standard pascal буду себе невозбранно переписывать перевод литературно-грамотный tex.web и tangle.web/weave.web с Pascal-H на модулу и алгол (там в ga68 модули завезли, почти что паскаль :)))

подглядывая в gpc/fpc.ch change-файлы с паскалевским переводом , в модулу аду или алголо коболо раст из tectonic Pascal-H на AST макросах растишки, или CTFE pegged/pascal.d из D2, вот это вот всё :)))

в общем, зачем нужен алгол-68? потому что прост как кирпич.

и в algol68toc/algol68g-genie/gcc 15+/16+ ga68 реализациях – есть и PAR/SEQ семафоры многопоточные, и каналы и сокеты и FFI с сишкой, и вот это все…

… затем можно читануть диссер (?докторскую?) Э.Дейкстры про реализацию конпелятора алгола на паскале (изначально вроде все-таки на алголе), и переписать назад на алгол.

… алгол нужен чтобы на нем написать паскаль!

затем P2,P3,P4,P5,P6,Pascaline, и CTFE PEG реализации на AST макросах на ржавом и D.

… а паскаль – чтобы написать на нем TeX ! :)

затем – переписать ещё раз под модульную модулу и адскую аду и сравнить ощущения.

после чего вместо bash взять bush/sparforte (интерпретируемый AdaScript) и переписать PKGBUILD-ы из NuTyx/CRUX/Arch с баша на это.

после чего собрать свой литературно-грамотный LFS и сделать слаку из дебиана, распаковав дебы вручную через ar x gcc-snapshot-*.deb content.tgz,data.tgz -> debchroot и фигурно расставив симлинки на эдакий debchroot.

в общем, будет чем заняться холодными зимними вечерами на НГ :))

anonymous
()
Ответ на: комментарий от anonymous

gcobol тоже кстати интересно потыкать под Libero как DSL для конечных автоматов который DSL для SWITCH-технологии… то есть, слепить бы этакий CTFE AST макрос который бы одно в другое перегонял, и написать на нем свой asciidoc и noweb :))

anonymous
()
Ответ на: комментарий от anonymous

незна

мне чёт Computer history museum и прочая литра про историю вт с интервью очевидцев как то ща угарней

в частности называние эвм 60ых тогда-же квантовыми компьютерами - с обоснованием что полупроводников и вообще сбис не может без квантовой физики

ну али всеми захваленный отчёт Неймана где буквально мозг копутерный который по факту был ожелезячиванием сложившийся практики вычислений стадами коров - и как раз пока память не была бутылочным горлышком по причине что всё состояние машины это 20 регистров и принудительное стробирование что-бы было понимание как часть паралельной фигни «имеет эстафету»

ваще первоисточники ядрёней - современность сплошное эпигонство хоть и не без прелести t3x.org

qulinxao3 ★☆
()
Ответ на: комментарий от qulinxao3

алгол-68 – наверное единственный язык, где допустимы многословные идентификаторы с пробелами…

их бы еще посклонять по падежам в именные формы: родительные винительно дательно творительные о предложных звательных двойственных для симулообъектов типа абстрактной фабрики всех фабрик метакласса всея метаклассов :))

anonymous
()
Ответ на: комментарий от anonymous

да не - вроде варианты первофортранов игнорировали пробелы :)

знаменитая ошибка где вместо цикла из из точки вместо запятой получаетя присвоение флоата переменной DOI

qulinxao3 ★☆
()
Ответ на: комментарий от qulinxao3

в частности называние эвм 60ых тогда-же квантовыми компьютерами - с обоснованием что полупроводников и вообще сбис не может без квантовой физики

читанул вот как-то девида нашего дойча «структура реальности» про то что «квантовая физика это реальная физика структуры реального мультиверса» и элайзера юдковски lesswrong про парадоксы квантовой физики где эксперимент зависит от наблюдателя – и завис…

а, я же еще сета ллойда «программируем вселенную не привлекая внимания санитаров» не дочитал, пойду дочитаю

anonymous
()
Ответ на: комментарий от qulinxao3

отчёт Неймана

описывающий архитектуру Эккрета и Мочли, почему-то называющегося фон-неймановской, который разрекламировал?

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

Bob_Everett_DEC_History_talk_900315.pdf про Whirlwind machine

anonymous
()
Ответ на: комментарий от qulinxao3

первофортран с вычисляемыми GOTO кстати есть рядом там же, где и Algol-68G (Genie). потом можно взять фокал интерпретируемый фортран и летать на луну в LUNAR LANDER и ADVENTURE-ить зорка :)

ЗЫ: это правда, что если там в первофортранах указать отрицательные индексы в массивах – можно было делать PEEK и POKE памяти в любой адрес?

anonymous
()