LINUX.ORG.RU

[c++][switch] как юзать свитч для char *?


0

0

Я считаю, что вопрос не достоин девелопмента, потому запостил сюда.

Вот пример кода:

#include <iostream>
using namespace std;

int main(){
const char *a = "b";


switch(a){

    case "a":
        cout << "a = a" << endl; break;
    case "b":
        cout << "a = b" << endl; break;
    }
}


А компилятор какбы говорит: switch.cpp:8: error: switch quantity not an integer


[c++][switch] как юзать свитч для char *?

Коротко - никак. Только для фундаментальных вроде int/char/enum можно.

loveless ()
Ответ на: [c++][switch] как юзать свитч для char *? от Elverion

[c++][switch] как юзать свитч для char *?

switch(*a){

Ага, пробуем скомпилить:

#include <iostream>
using namespace std;

int main(){
const char *a = "b";


switch(*a){

    case "a":
        cout << "a = a" << endl; break;
    case "b":
        cout << "a = b" << endl; break;
    }
}

Получаем ошибки: switch.cpp:10: error: case label does not reduce to an integer constant switch.cpp:12: error: case label does not reduce to an integer constant

ShTH ()

[c++][switch] как юзать свитч для char *?

Самое интересное, что в макроаасемблерах обычно больше можно было, и со сладким синтаксисисом.

madcore ★★★★★ ()
Ответ на: [c++][switch] как юзать свитч для char *? от loveless

[c++][switch] как юзать свитч для char *?

>> хешики сравнивай

>Плохой совет. Хорошим может быть использование кодогенерации на темплейтах.

Темплейты со стрингами не работают. Вообще, насколько я понимаю оптимально тут каким-то макаром интернить строки чтобы сравнивать их указатели.

Absurd ★★★ ()
Ответ на: [c++][switch] как юзать свитч для char *? от ShTH

[c++][switch] как юзать свитч для char *?

    void Npc::damage(int damage_type, int damage_sum){


    switch(damage_type){
        case 1:
        cout << "Урон SMG. Одно попадание забирает 5 очков. Попаданий:" << damage_sum  << endl;
        health -= (5 * damage_sum);
        break;

        case 2:
        cout << "Урон AR2. Одно попадание забирает 9 очков. Попаданий:" << damage_sum << endl;
        health -= (9 * damage_sum);
        break;

        default:
            cerr << "!!!!|       Оружие не известно! Ошибка" << endl << endl;
        break;
        }

}

Хотел как damage_type указывать не номера, а слова, например «ar2».

ShTH ()

[c++][switch] как юзать свитч для char *?

switch не нужен. Юзай полиморфизм или ассоциативные контейнеры

yoghurt ★★★★★ ()
Ответ на: [c++][switch] как юзать свитч для char *? от ShTH

[c++][switch] как юзать свитч для char *?

Потому что это сравнение строк. Которое требует дофига операций. Когда строки будут символов под сто, а условий будет под сотню, а вызовов в секунду будет...

Xellos ★★★★★ ()
Ответ на: [c++][switch] как юзать свитч для char *? от ShTH

Re: [c++][switch] как юзать свитч для char *?

>Ладно, буду использовать нагромождения из конструкций if(), else if(). Проект не большой, просто учусь писать и использовать классы.

Не совсем ясна задача.

Если на входе слова из известного словаря и требуется очень быстрая обработка, то следует использовать любую библиотеку вычисления perfect hash.

Если требования по скорости более низкие или словарь заранее неизвестен, то можно использовать дерево поиска.

Если требований по скорости нет вообще - то можно использовать последовательный перебор строк. Например, можно хранить нужные слова в массиве вместе с указателеми на функцию обработки.

sign ()

[c++][switch] как юзать свитч для char *?

Вариант: взять дистанцию левенштейна, и свитч делать уже по ней :)

dannie ()

[c++][switch] как юзать свитч для char *?

Это development

svu ★★★★★ ()

[c++][switch] как юзать свитч для char *?

По теме. В жабке такую фичу (свитч по строкам) обещают добавить в 1.7

svu ★★★★★ ()
Ответ на: [c++][switch] как юзать свитч для char *? от namezys

[c++][switch] как юзать свитч для char *?

>Как такая конструкция

мне вот просто интересно - а что ты, собственно, хотел этой конструкцией сказать? что switch - это такой goto? что в нём можно забыть написать break? или что-то третье?

jtootf ★★★★★ ()
Ответ на: [c++][switch] как юзать свитч для char *? от svu

[c++][switch] как юзать свитч для char *?

>В жабке такую фичу (свитч по строкам) обещают добавить в 1.7

а Tcl умеет свитчится по glob-style паттернам и регекспам:

http://www.tcl.tk/man/tcl8.5/TclCmd/switch.htm

завидуйте

jtootf ★★★★★ ()
Ответ на: [c++][switch] как юзать свитч для char *? от jtootf

[c++][switch] как юзать свитч для char *?

вот и займись этим

Заколебали. Вот идея. Именно этот код не тестировал, но рабочая 100%:

#include <boost/mpl/vector.hpp>
#include <boost/mpl/begin.hpp
#include <boost/mpl/deref.hpp>

#define ADDCASE(Name, Label, Function) \
class Name\
{\
public:\
String label_;
Name() : label_(Label){}\
void execute() { Function(); return true; }\
};

Потом в коде:

void function1()
{ printf("Hello from switch"); }

ADDCASE(CASEBLOCK1, "label1" , function1)

И так - сколько нужно кейсов.

Потом кладем кейсы в контейнер:

typedef boost::mpl::vector<CASEBLOCK1, CASEBLOCK2, CASEBLOCK3> CASES;

Сам свитч:

template <class Begin, class End>
struct SWITCH
{
static bool doswitch(const String& s)
{
  typedef typename boost::mpl::deref<Begin>::type deref;
  dereft ex;
  if( ex.label_ == s )
    return ex.execute();
  else
    return Iteratorhelper<typename boost::mpl::next<Begin>::type, End >::doswitch(s); 
}
};

template <class End>
struct SWITCH<End, End>
{
static  bool doswitch(const String& s)
{
  bool false;
}
};

template<typename Container>
static QString PERFORMSWITCH(const String& s)
{
return SWITCH<typename boost::mpl::begin<Container>::type, typename boost::mpl::end<Container>::type>::switch(s);
}

Как пользоваться:

PERFORMSWITCH<CASES>("blabla");

Теперь компилятор сгенерит нам статическую функцию PERFORMSWITCH<CASES>, которая будет то же самое, что много if/else, но куда проще для расширения, доработки, создания новых кейсов.

loveless ()
Ответ на: [c++][switch] как юзать свитч для char *? от loveless

[c++][switch] как юзать свитч для char *?

>которая будет то же самое

что и сравнение по хешикам, с той лишь разницей, что ты их считаешь статически (рукми объявляешь все CASEBLOCK'и). расширяемость, читаемость (как реализации так и использования), зависимости - всё на уровне плинтуса. вопорос дня: а в чём профит-то?

jtootf ★★★★★ ()
Ответ на: [c++][switch] как юзать свитч для char *? от jtootf

[c++][switch] как юзать свитч для char *?

что и сравнение по хешикам

Нет, в данном случае будет вызываться оператор сравнения для строки. Можно и хэши сделать (если постараться, то и статические). В doswitch можно делать все, что хочешь.

Читаемость отличная. Профит в том, что компилятор напишет за тебя очень много кода (и сделает это оптимально), скорости, расширяемости. Сам свитч можно вынести в отдельный хидер. Тогда для написания новых свитчей тебе достаточно сделать

void function1() { printf("Hello from switch"); }
void function2() { printf("Hello from switch"); }

ADDCASE(CASEBLOCK1, "label1" , function1) 
ADDCASE(CASEBLOCK2, "label2" , function1) 
ADDCASE(CASEBLOCK3, "label3" , function2) 

void test( )
{
...
typedef boost::mpl::vector<CASEBLOCK1, CASEBLOCK2, CASEBLOCK3> CASES2;
String mystr("label3");
PERFORMSWITCH<CASES2>(mystr);
...
}

Отличная читаемость, отличная расширяемость. И самое главное - это только идея, можно очень красиво ее доработать.

loveless ()
Ответ на: [c++][switch] как юзать свитч для char *? от jtootf

[c++][switch] как юзать свитч для char *?

Это как? Так?

(defgeneric switch-test (switch-case value)
            (:method (x y) (equal x y))
            (:method ((switch-case (eql T)) value) T))

(defmacro switch (value &rest cases)
  (let ((value-var (gensym)))
    (labels ((process-switch (cases)
               (if (null cases)
                 nil
                 (destructuring-bind
                   ((current-case &body body) &rest cases) cases
                   `(if (switch-test ,current-case ,value-var)
                      (progn ,@body)
                      ,(process-switch cases))))))
      `(let ((,value-var ,value))
         ,(process-switch cases)))))

(use-package :cl-ppcre)

(defstruct regex (pattern ".*" :type string))

(set-dispatch-macro-character
  #\# #\" (lambda (s c n)
            (declare (ignore n))
            (unread-char c s)
            `(make-regex :pattern ,(read s t nil t))))

(defmethod switch-test ((case-of regex) (value string))
  (cl-ppcre:scan (regex-pattern case-of) value))

(defun main (s)
  (switch s
    (#"(?i)[A-Z]" (format t "String contains letters~%"))
    (#"[0-9]" (format t "String contains at least one digit and no letters~%"))
    (T (format t "The value is not a string"))))

Love5an ()
Ответ на: [c++][switch] как юзать свитч для char *? от Love5an

[c++][switch] как юзать свитч для char *?

между вторым и третьим случаями туда неплохо бы "(#".*" (format t "String contains no letters or digits"))", но суть и так понятна, думаю :)

Love5an ()

[c++][switch] как юзать свитч для char *?

если один символ, то

#include <iostream> 

using namespace std;

int main() 
{ 
    const char *a = "b";

    switch(*a) {                  /* или a[0] вместо *a */
      case 'a': 
        cout << "a = a" << endl; 
        break; 
      
      case 'b': 
        cout << "a = b" << endl; 
        break; 
    } 
}
ono ()
Ответ на: [c++][switch] как юзать свитч для char *? от Absurd

[c++][switch] как юзать свитч для char *?

Оптимально построить finite state machine по данным строкам на этапе компиляции. Она будет небольшой, и поиск будет занимать O(N) (N - длина входной строки) или даже меньше.

Legioner ★★★★★ ()
Ответ на: [c++][switch] как юзать свитч для char *? от kemm

[c++][switch] как юзать свитч для char *?

> Уййййоооооо...

Что не так?

Вдогонку: вместо [code] return Iteratorhelper<typename boost::mpl::next<Begin>::type, End >::doswitch(s); [/code] следует читать [code] return SWITCH<typename boost::mpl::next<Begin>::type, End >::doswitch(s); [/code]

loveless ()
Ответ на: [c++][switch] как юзать свитч для char *? от Legioner

[c++][switch] как юзать свитч для char *?

> Оптимально построить finite state machine

Какие мы умные. Конечно можно, но делать ты это будешь приблизительно так же. Только добавится еще функция, возвращающая указатель на себя же.

loveless ()
Ответ на: [c++][switch] как юзать свитч для char *? от loveless

[c++][switch] как юзать свитч для char *?

В лиспе можно сделать при желании примерно так:

(case (var)
  ("abc[de]+f" 'first-string)
  ("abc[fg]" 'second-string)
  (else 'third))

В С++ без препроцессора я бы не стал этого делать вообще (если только не очень жётские требования к производительности). В D можно сделать.

А говорить про твоё нагромождение капслока, что оно отлично читается - нельзя.

Legioner ★★★★★ ()
Ответ на: [c++][switch] как юзать свитч для char *? от Legioner

[c++][switch] как юзать свитч для char *?

Капслок здесь необязателен, препроцессор для удобства. Это вообще демонстрация идеи. И неоптимальная, за счет создания временного объекта.

loveless ()
Ответ на: Re: [c++][switch] как юзать свитч для char *? от loveless

[c++][switch] как юзать свитч для char *?

Не смотрел реализацию тикля, но мой комментарий относился не конкретно к тиклю, и компиляции там ничего не мешает. Вообще реализация case-а по строкам с использованием FSM идеологически очень похожа на реализацию case-а с использованием таблицы переходов.

Legioner ★★★★★ ()

[c++][switch] как юзать свитч для char *?

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

inline bool _IsEqu(const char* s1,const char* s2) { return (strcmp(s1,s2)==0); };

void Process(const char* text)
{
	if(_IsEqu(text,"aaa"))
	{
		//do some ...
	}
	else if(_IsEqu(text,"bbb"))
	{
		//do some ...
	}
	else if(_IsEqu(text,"ccc"))
	{
		//do some ...
	}
	else
	{
		pAnIc();
	}
}
З.Ы. Без _IsEqu можно было обойтись, но мне кажется, что так легче читается, а назначение этой функции можно понять из названия.

pathfinder ★★★ ()
Ответ на: [c++][switch] как юзать свитч для char *? от pathfinder

[c++][switch] как юзать свитч для char *?

>Чем плох такой вариант?


void Process(const char* text)
{
if(_IsEqu(text,"aaa"))
{
//do some ...
}
else if(_IsEqu(text,"bbb"))
{
//do some ...
}
else if(_IsEqu(text,"ccc"))
{
//do some ...
}
else if(_IsEqu(text,"ccc"))
{
//do some ...
}
else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
}
{
//do some ...
} else if(_IsEqu(text,"ccc"))
{
//do some ...
}
else
{
pAnIc();
}
}

madcore ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.