LINUX.ORG.RU

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

 


2

2

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

	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 ★★★
() автор топика