Оператор Switch: синтаксис с несколькими переменными

bifurkas
Offline
Зарегистрирован: 27.10.2013

Подскажите пожалуйста, можно ли этим оператором проверять несколько переменных? Каков тогда будет синтаксис Switch и case?

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

нет, либо переменная, либо выражение

http://cppstudio.com/post/306/

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А можно уточнить, что Вы понимаете под выражением "проверять несколько переменных"? Пример можно?

bifurkas
Offline
Зарегистрирован: 27.10.2013

ЕвгенийП пишет:

А можно уточнить, что Вы понимаете под выражением "проверять несколько переменных"? Пример можно?

Ну типа:

Switch (A, B, C...)

case (1, 5, 3...):

case (3, 2, 4...):

Но собственно я уже понял, что нельзя.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Почему сразу и нельзя? Огласите весь список! В смысле детальнее что хотелось-то .. что такое в вашем понимании 1,5,3 и особенно многоточие в данном синтаксисе? Значения переменной А или это тройки значений? А многоточие?

Araris
Offline
Зарегистрирован: 09.11.2012

Господа хорошие, что ж вы паритесь-то ?

В описании явно написано, "оператор switch сравнивает значение переменной со значением, определенном в операторах case. Когда найден оператор case, значение которого равно значению переменной, выполняется программный код в этом операторе."

Ну всё же ясно и однозначно прописано, или как ?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Araris пишет:

В описании явно написано, "оператор switch сравнивает значение переменной со значением, определенном в операторах case. Когда найден оператор case, значение которого равно значению переменной, выполняется программный код в этом операторе."

Ну всё же ясно и однозначно прописано, или как ?

Конечно, "или как". Жизнь сложна. Ну, например, ситнтаксис, предложенный ТС (только без многоточий) вполне приемлем. Что будет при этом делаться - другой вопрос, но мы ведь и не понимаем чего он хочет, чтобы делалось! Потому и хочется понять, что именно нужно ТС. Беда только в том, что он, похоже, сам этого не понимает.

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

bifurkas,

что значит "ну, типа". Может Вы объясните что Вы хотите сделать? Сравнить несколько чисел по-отдельности или там сравнить их среднее или сравнить их с датой Пасхи в 2345 году? Что Вам нужно-то?

А вообще, лучший способ что-то узнать - поэкспериментировать.

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

int a = 1, b = 2, c = 3;
switch (a,b,c) {
	case 1 :
		Serial.println("Point #1");
		break;
	case 2 :
		Serial.println("Point #2");
		break;
	case 3 :
		Serial.println("Point #3");
		break;
	default:
		Serial.println("Point #4");
		break;
}

Запустите и посмотрите, что выдастся в Serial. Подумайте. Поменяйте код и проверьте адекватно ли он работает (и, стало быть, правильно ли Вы его понимаете). Если нет - подумайте ещё. Так Вы гораздо быстрее научитесь, чем задавая вопросы которые толком не можете сформулировать и ответы на которые (уверен) толком не можете понять.

 

bifurkas
Offline
Зарегистрирован: 27.10.2013

ЕвгенийП пишет:

Araris пишет:

В описании явно написано, "оператор switch сравнивает значение переменной со значением, определенном в операторах case. Когда найден оператор case, значение которого равно значению переменной, выполняется программный код в этом операторе."

Ну всё же ясно и однозначно прописано, или как ?

Конечно, "или как". Жизнь сложна. Ну, например, ситнтаксис, предложенный ТС (только без многоточий) вполне приемлем. Что будет при этом делаться - другой вопрос, но мы ведь и не понимаем чего он хочет, чтобы делалось! Потому и хочется понять, что именно нужно ТС. Беда только в том, что он, похоже, сам этого не понимает.

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

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так Вы получили грубый ответ (без тонксотей). А если учесть тонкости, то (если я правильно понимаю, чего Вы хотите), всё "более чем возможно". Впрочем, я не навязываюсь. Вам жить.

Duino A.R.
Offline
Зарегистрирован: 25.05.2015

ЕвгенийП пишет:

А если учесть тонкости, то (если я правильно понимаю, чего Вы хотите), всё "более чем возможно


Это просто мои мысли вслух, а не замечания участникам дискуссии. На мой взгляд, рассматриваемый пример - типичный вариант "недокументированных возможностей", порожденных ошибками входного контроля компиллятора. В языке четко задана конструкция оператора. Программист нарушает синтаксис оператора, а компиллятор, вместо того, чтобы выявить недопустимую конструкцию, пропускает ее и КАК-ТО транслирует. МК это "как-то" отрабатывает. Пусть результат будет любопытен или даже приемлем, я категорически рекомендую избегать таких ситуаций, а сам факт пропуска компиллятором недопустимой конструкции заносить в "чек лист" для исправления в следующем релизе компиллятора. Нет никаких гарантий, что мы зарегистрировали весь объём результатов "недобросовестной компилляции", а не какую-то его часть. Плюс к этому, в следующем релизе компиллятора его реакция на тот же самый "кривой" исходный текст может быть совершенно другой.

Клапауций 666
Offline
Зарегистрирован: 10.11.2015
switch(abc){
case a: 
  switch(a){
  case a1:
    // 
    break;
  case a2:
    // 
    break;
  case a3:
    // 
    break;
  }
  break;
case b: 
  switch(b){
  case b1:
    // 
    break;
  case b2:
    // 
    break;
  case b3:
    // 
    break;
  }
  break;
case c: 
  switch(c){
  case c1:
    // 
    break;
  case c2:
    // 
    break;
  case c3:
    // 
    break;
  }
  break;
}

 

Radjah
Offline
Зарегистрирован: 06.08.2014

Сова, а как мы всё это в 32КБ флеша поместим?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Duino A.R. пишет:
ЕвгенийП пишет:

А если учесть тонкости, то (если я правильно понимаю, чего Вы хотите), всё "более чем возможно

На мой взгляд, рассматриваемый пример - типичный вариант "недокументированных возможностей", порожденных ошибками входного контроля компиллятора. В языке четко задана конструкция оператора. Программист нарушает синтаксис оператора, а компиллятор, вместо того, чтобы выявить недопустимую конструкцию, пропускает ее и КАК-ТО транслирует. МК это "как-то" отрабатывает.
Если Вы о моём примере со switch(a,b,c), то Вы совершенно неправы. Там нет ничего недокументированного и нестандартного.

В switch допускается выражение и это документировано. Запись a,b,c является абсолютно нормальным выражением, использующим вполне себе докуметированную операцию "запятая". Результатом этого выражения будет результат последнего из разделённых запятыми подвыражений. Это абсолютно чётко документировано в языке. Точно также (и по тем же причинам) допустимо, например, switch (a, b+c). Выражение в скобках опять же использует операцию "запятая" и его результатом будет результат последнего, то бишь b+c.

Для чего такие конструкции нужны? Обычно для "побочных эффектов" вычисления первого выражения. Ну. вот, например, не лишённые какого-то смысла примеры:

switch (DebugPrint("Switch with: %d", a), a) {

switch (++gCounter, Calculate()) { // глобальный gCounter увеличивается до вызова Calculate()

switch (a = digitalRead(3), b = digitalRead(4), (a<<1) + b) {

Если Вы о моих словах "возможны нюансы", так опять же никаких недокументированных фокусов. Например, если надо чтобы case сравнивал сразу три константы с тремя заданными в switch переменными, это легко делается путём введения векторного типа данных (абсолютно легальными и документированными средствами).  

Araris
Offline
Зарегистрирован: 09.11.2012

Вау, а тема-то не такая простая оказалась.. Спасибо, узнал новое.

Maverik
Offline
Зарегистрирован: 12.09.2012

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

sandr4
sandr4 аватар
Offline
Зарегистрирован: 11.02.2015

Maverik пишет:

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

ЕвгенийП в какой-то ветке писал, что он профессиональный програмист. Его точно не возьмёшь.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Чем проще код, тем меньше шансов допустить ошибку. switch(a,b,c) безусловно писать можно, только код это усложняет, а не упрощает. Читается код с запятыми сложнее, а значит и больше шансов допустить ошибку. Поскольку мы работаем группами, я бы за такой код своим сотрудникам кое что оторвал. Впрочем уговаривать не вижу смысла, каждый мочит как он хочет. Или лучше так: грабли у каждого свои! :)

 

Клапауций 666
Offline
Зарегистрирован: 10.11.2015

sandr4 пишет:

ЕвгенийП в какой-то ветке писал, что он профессиональный програмист. Его точно не возьмёшь.

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

советовал он мне вписать в класс для кнопки частный случай - аргументировать причину непонятного не смог.

поэтому, гложут меня смутные сомнения по поводу профессионализьму.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

kisoft пишет:
Чем проще код, тем меньше шансов допустить ошибку. 

Эт точно!

kisoft пишет:
switch(a,b,c) безусловно писать можно, только код это усложняет, а не упрощает. Читается код с запятыми сложнее, а значит и больше шансов допустить ошибку.
Ну, это смотря как писать. Любой инструмент можно использовать с пользой, а можно ... Например, молотком можно забить гвоздь, а можно разбить себе палец.

Например, как Вам вот такой макрос с активным использованием запятой:

#ifdef DEBUG
	#define TRACED(v,MivV,MaxV) ((v < MivV || v > MaxV) ? Serial.print("*** v вылезло за границы:"),Serial.print(v):0), v
#else
	#define TRACED(v, ...) v
#endif

Теперь, везде, где допустимо писать целочисленную переменную (в том числе и в switch), я могу заодно указывать её допустимые границы (т.е. вместо просто n писать TRACED(n, 10, 40), например. Если в моём коде DEBUG не определён, то это абсолютно всё равно, что писать просто n, а если я вставлю #define DEBUG, то породится код проверки переменной на допустимость границ и если она вылезла - пойдёт сообщение в Serial.

Не скажете же Вы, что это бесполезно или что это ухудшает читабельность кода? И полезно и не ухудшает ни читабельности, ни эффективности (если убрать "#define DEBUG", так как будто ничего и вовсе не было).

А вот написать такое без операции "запятая" было бы проблематично. По крайней мере, написать так, чтобы это можно было использовать везде, где допустима численная переменная.

Так что, весьма полезная конструкция, если пользовать с умом.

 
Duino A.R.
Offline
Зарегистрирован: 25.05.2015

ЕвгенийП пишет:

Если Вы о моём примере со switch(a,b,c), то Вы совершенно неправы. Там нет ничего недокументированного и нестандартного.

Duino A.R. пишет:

Это просто мои мысли вслух, а не замечания участникам дискуссии.

На правоту претендовать не берусь, поскольку не сишник ни разу. Мой пост не претензия, а ассоциация, навеянная опытом "прошлой жизни".

kisoft пишет:

Чем проще код, тем меньше шансов допустить ошибку. switch(a,b,c) безусловно писать можно, только код это усложняет, а не упрощает.

100%

kisoft пишет:

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

200% :))

Опять же ассоцияция, теперь с уже более милым моему сердцу "железным" подтекстом. Схема, где на один единственный операционник навешаны: его собственная частотная коррекция, П-регулятор, И-регулятор, Д-регулятор, сумматор, коррекция нуля. Можно так? Да. Даже серийные изделия выпускались с таким решением. После наладки в цеховых условиях возникает однозначное желание "зачистить" автора.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Поддержу Евгения П. А ведь есть ещё "препроцессор", с помощью которого можно и ваще иной смысл этому синтаксису задать. В смысле switch с переменными через запятые .. ну вызовется требуемый макрос .. делов-то. Впрочем, один из вариантов его применения он тут уже описал. :)

Вот поэтому и спросил "чего хочет афтар" ..

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Клапауций 666 пишет:

советовал он мне вписать в класс для кнопки частный случай - аргументировать причину непонятного не смог.

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

По-поводу того случая, действительно я не смог объяснить (раз Вы не поняли, значит не смог). Но это не значит, что совет был плохим. Я Вам советовал вставить виртуальные функции для различных событий - это абсолютно стандартная схема для реализации любых классов с событиями. Я не знаю ни одной профессиональной системы, где этого бы не было.

Вот, например, посмотрите, например, как это реализовано в браузере. Любой элемент имеет кучу связанных событий (onclick - нажали, onmouseover - мышом наехали, onchange - изменили содержимое и т.д. их там десятки - вот здесь есть  список http://www.irt.org/articles/js058/ ). Разбор событий производится всегда внутри класа, а когда программа класса посчитает, что событие произошло, она тупо вызывает соответсвующую виртуальную функцию. Внутри класса они (функции) все есть, но все пустые. Юзер может их определить, если они ему нужны, причём определить только те, которые ему нужны. Вот, допустим, нужно мне обрабатывать нажатие - я пишу свою  функцию onclick и обрабатываю как мне нужно, и никакх других функций я не пишу. И разбор IF'ами было нажатие или нет - не моё дело - класс сам это разберёт и вызовет мой обработчик. Так делают все и всегда. Разбор событию юзеру не оставляют - это делает класс сам.

Ну, а по самой истории, Вы тогда просили меня написать Вам пример класса - я написал, Вы попросили написать ещё пару примеров, я опять же их Вам написал. А потом Вы, когда Вы сделали класс с помощью этих примеров, но не поняли моих объясниений про виртуальные функции, Вы обозвали меня сами помните как. Я прошу Вам изиниться и хочу нормализовать отношения.

Клапауций 666
Offline
Зарегистрирован: 10.11.2015

ЕвгенийП пишет:

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

я с вами не ссорился - просто вы мне вынесли мосг странным.

по сути сабжа:

использовать класс первым предложил roman2712@ma #24

затем на бульдозере въехали вы, судя по вопросу, топик выше не читавший #31

затем, медленный вынос мосга - вам нравится эдкое в коде, но эдакое странно пока не знаешь нормального.

затем Tomasina дал ссылку на реальный пример #49

посидел я пытаясь понять, что не так в ваших примерах - плюнул и пошёл рыть интернет на тему.

*извиняться за что? я вас чем-то оскорбил? не наблюдаю - моя субъективная оценка, не более.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Клапауций 666 пишет:

*извиняться за что? я вас чем-то оскорбил? не наблюдаю - моя субъективная оценка, не более.

Ну, если слова долбо... и мудак по Вашему не оскорбление, то живите с этим дальше. Я Вас знать не знаю и не особо хочу. Успехов.

Клапауций 666
Offline
Зарегистрирован: 10.11.2015

ЕвгенийП пишет:
Ну, если слова долбо... и мудак по Вашему не оскорбление, то живите с этим дальше. Я Вас знать не знаю и не особо хочу. Успехов.

upd. помню, что посылал Дохтора с его свитчами - вас по поводу класса не помню. последнее ваше собщение не свидетельствует об оскорблении #81

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

ЕвгенийП пишет:

kisoft пишет:
switch(a,b,c) безусловно писать можно, только код это усложняет, а не упрощает. Читается код с запятыми сложнее, а значит и больше шансов допустить ошибку.
Ну, это смотря как писать. Любой инструмент можно использовать с пользой, а можно ... Например, молотком можно забить гвоздь, а можно разбить себе палец.

Например, как Вам вот такой макрос с активным использованием запятой:

#ifdef DEBUG
	#define TRACED(v,MivV,MaxV) ((v < MivV || v > MaxV) ? Serial.print("*** v вылезло за границы:"),Serial.print(v):0), v
#else
	#define TRACED(v, ...) v
#endif

Теперь, везде, где допустимо писать целочисленную переменную (в том числе и в switch), я могу заодно указывать её допустимые границы (т.е. вместо просто n писать TRACED(n, 10, 40), например. Если в моём коде DEBUG не определён, то это абсолютно всё равно, что писать просто n, а если я вставлю #define DEBUG, то породится код проверки переменной на допустимость границ и если она вылезла - пойдёт сообщение в Serial.

Не вижу особых причин, почему бы отдельной строкой написать TRACED (разумеется исправив его) и только там, где нужно, а не в куче мест, а 'n' использовать как обычно, без ..эээ.. особенностей. Это будет более читабельно, для любого человека, который будет разбирать Ваш текст. Ответ "пишу для себя" не катит.

Теперь, цитирую: "везде, где допустимо писать целочисленную переменную". Ок. Для разминки такой текст, всё таки не везде:

void loop() {
  int n = 20;
  TRACED(n,10,40) = 50;
  int a = TRACED(n,10,40);
  Serial.println(a);
}

Это же подтвердил и MS VS 2010.

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

В детстве я тоже любил навороченный код, вот только со временем стал писать даже простые операторы в фигурных скобках после if, for и т.п. В выражениях я теперь всегда пишу скобки, чтобы не парить мозг и коллег порядком вычисления. Конструкции типа switch(a++) тоже не пишу. Да и достаточно примеров, и так уже нанудил много.

Хоть я, наверное, повторюсь, но в МК #define может быть и нормально, на больших компах в C++ он не рекомендуется, хотя это совсем другая история и не для этого форума.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Вооббще-то, я писал лишь о полезности запятой и вовсе не писал, что использовать такую запись нужно везде. Разумеется, только там где действительно надо контролировать значение n. Ну, а про использование слева - молодец, что заметил :)))

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Привычка. Доверяй, но и сам не плошай :)
Пусть я буду нудным, но слово 'везде' я цитировал, я его не придумал и не вырвал из контекста.
Трюки в программировании хороши, пока проект выполняется в моно режиме, я сам так много работал и делал 'перлы', а потом понял, что это хорошо только для себя, типа я такой крутой. Почитал, пописал, повзрослел и понял Истину :)