C++에서 switch문 제거하는 방법이 없을까요?

bluemoon의 이미지

url로 넘어온 값에따라 여러모듈로 분기하는 루틴이 있는데 이걸
switch 문으로 처리하면 편하긴 한데 C 냄새가 많이 풍기네요.
예전에 case구문의 순서상의 문제로 논리적 오류가 발생했던 경험도 있었고..
그래서 좀 더 스마트하게 처리하는 방법이 있을까해서 질문드립니다.

winner의 이미지

요새 C++ 논쟁이 많아서 생각나는 건데...
함수 pointer 나 C++ 의 상속다형성을 사용하는 것은 어떨까요?... -_-

URL 의 자식 class 에 protocal(예: http://), site(kldp.org), path(/index.html)

조금 지나친 걸까요?

monpetit의 이미지

함수 배열 같은 건 어떨까요...

cdpark의 이미지

C++ 식이라면, 함수 배열보다는 함수 map이... :)

corba의 이미지

State Pattern을 써보시는 것이 어떨까요 ?

죠커의 이미지

저도 State Pattern에 한표올립니다. :-)

cinsk의 이미지

Keep it simple, Sxxxx.

switch로 간단히 빠르게 되는데 왜 어렵게 다른 방식을 쓰려 하죠? 특별히 switch가 비효율적이거나 단점이 있으면 모를까, 단순히 C에서 많이 쓰인다는 이유로 다른 방식을 쓴다는 건 C++이라고 해도 납득이 가지 않는군요.

onemind555의 이미지

왜 굳이 switch를 없애냐구요..
이유는 간단 합니다... switch있으면 소스 보기 너무 힘들어 집니다.. 복잡한 소스를 다형성을 이용해서 간단하게 해서 만들어 보면 c방식으로는 정말로 하기 싫어 질 겁니다..

state패턴도 있지만 테이블 구동 방식도 있습니다. 테이블 구동도 state패턴이라고 할 수 있습니다..

-----------^^ ^^ ^^ ^^ ^^ ----------
..........................................................

winner의 이미지

Design Pattern 은 이름만으로 개발자들간의 의사소통을 하는데 유용하다고 하는데 정말로 이런 답변을 볼 줄이야... -_-.

C++ 는 C 의 programming paradigm 을 포함하고 있습니다.
switch 가 있는 것이 괜히 있는 것이 아닙니다.
switch 를 제거하고 다른 방식을 도입하고 싶다면 합당한 이유가 있어야 할텐데 위에 적어 놓으신 것만으로는 판단이 어렵습니다.

고로 위에 제가 적어놓은 글은 반은 농담이었습니다.

bluemoon의 이미지

사용자가 선택할 수 있는 메뉴가 1, 2, 3... 이 있다면,
프로그램은 1을 받아들였을때 proc_func1 을 호출하고
2를 눌리면 proc_func2 를 호출하고..
가장 쉽게 떠올릴수 있는게 분기방식의 구조인데요.

switch ( menu )
{
    case 1: proc_func1();
        switch ( i )
        {
              ...... blahblah....
        }
        break;
    case 2: proc_func2();
         if ..
         else...

     case 3:
     case 4:
          break;
    .
    .
}

간단한 프로그램이라면 상관없는데 이런 구조는 한번의 분기로 끝나는게
아니라 분기된 곳에서 내부적으로 다시 분기가 이뤄지는 형태를 띄게되더군요.
(처음 개발할땐 안그랬지만 시간이 지나면서 그렇게 되어가더군요)
이런 구조는 winapi 프로그래밍에서 자주 볼수있는데 MFC만 가봐도
저런식의 프로그램 구조는 못봤거든요.
뭐.. switch문이 아예 없는 언어도 있고요. 예를 들면 다들 아실만한
python이 있겠네요. 모르긴 몰라도 없어도 될만하니까 없앤것 아니겠습니까.. :)

ps. 패턴에 관한 애기가 나오는데 참고할 만한 책이라도 좀 알려주심 고맙겠네요.

bluemoon의 이미지

지금 기존에 윈도우상에서 구동되던 프로그램을 웹으로 옮기고자 하는데요.
이 프로그램의 메뉴가 엄청나게 많습니다. 1024x768 해상도를 모두 다
채울만큼 메뉴가 많은데요.

윈도우기반의 프로그래밍이라면 내부적으로 switch를 쓰건 말건간에
저는 그런걱정없이 메뉴 리소스 파일만 작성해주면 나머지는 윈도우가
알아서 다 처리해주니 저는 해당 메뉴의 구현부분만 작성해주면 되거든요.
이런건 VC++의 클래스 마법사를 사용하면 정말 쉽죠.

근데 웹에선 어떻게 해야할지 잘 모르겠습니다.
각 모듈을 호출하는 switch가 있고 다시 모듈별로 각 모듈내에 switch를 두고..
그렇게 해야 할지.. 다른분들의 고견을 들어보고자 질문드렸습니다.

jj의 이미지

동일한 형태의 switch가 세번이상 반복되는게 아니라면 가만 두는데 한표.

--
Life is short. damn short...

죠커의 이미지

jj wrote:
동일한 형태의 switch가 세번이상 반복되는게 아니라면 가만 두는데 한표.

멋집니다. :-)

winner의 이미지

bluemoon wrote:
뭐.. switch문이 아예 없는 언어도 있고요. 예를 들면 다들 아실만한 python이 있겠네요. 모르긴 몰라도 없어도 될만하니까 없앤것 아니겠습니까..

사실 switch - case 는 if - else 사슬과 동일한 code 를 생성해냅니다.
한가지 예외가 jump table 을 생성해 낼 수 있을 때이죠.
함수 pointer 의 배열과 동일한 방식입니다.
위에 bluemoon 씨가 작성한 code 는 함수 pointer 의 배열에 적당해 보입니다.

Python 의 질문답변을 보면 switch - case 가 없는 것은 if - else 사슬과 동일하기 때문에 없다고 합니다. 이 문제는 programming language 제작자의 선택이죠. 저는 switch - case 가 jump table 을 통한 속도 향상외에도 가독성 측면에서 도움을 줄 수 있다고 생각합니다만 Python 제작자는 도움은 커녕 어지럽히기만 한다라고 생각한 모양입니다.

kuma의 이미지

한번은 아주 다양한 경우가 나와서 이걸 switch ~ case 문장으로 만들면 위에 보여준 문장처럼 2중 switch ~ case 가 나와서 아예 2차원 table 로 돌려서 바로 얻는 방식을 사용했다가 가독성 ( Table 가독성 ) 때문에 다시 switch ~ case 로 바꾼적이 있습니다.

또한 아래의 경우 저는 if 문 대신 switch 문을 사용합니다.

꼬랑지 : switch ~ case 는 절대 낙후된 방식이 아니라고 생각합니다.

if( 1 == a || 5 == a || 9 == a ) {
궁시렁;
} else {
쩝쩝쩝;
}

switch( a )
{
case 1 :
case 5 :
case 9 :
궁시렁;
break;
default :
쩝쩝쩝;
}

mangg의 이미지

switch() 문을 굳이 쓰지 않으시려면
if 문을 쓰세요.

아니면 포인터 함수를 쓰시는게 어떨지
한번 생각해 보세요.

-------------------
나는 Copy&Paster 이다. 나의 화려한 기술 조합에 모두들 나를 두려워 한다. 나도 코드 Maker 이고 싶다.

레모네이드의 이미지

간단한 분기문 처리하는데에는 switch가 편리하고 가독성도 높고 좋죠...
그런데 복잡한 분기문 처리하는데는 좀 말리고 싶은데...
저같은 경우에는 위에 어느분 처럼 테이블 만들어서 사용하거든요...
코드 짧아지고 가독성 좋아집니다...
그렇다고 테이블 만들어서 함수 호출 하는 방식에서도 switch 않쓰느냐? 그건또 아니라고 생각되네요..
어느정도 테이블 만들어서 사용해도 상태에따라 호출하는 함수의 형태가 다르다면 그때는 짧으나마 switch로
간단히 처리할수 있다고 생각되네요....
그리고 복잡한 분기문 처리할때 상태에 따라 엄청나네 많은 분기가 있다면 테이블의 구조도 서치가 빠른 자료구조를
선택해서 하면(예를 들어 해시테이블 같은) switch 사용할때보다 성능면에서도 월등하겠죠...
그래도 간단한 구조의 분기일때는 오히려 이방법이 더 가독성이 떨어진다는거...
상황에 따라서 선택할 문제라는데에 한표 던집니다...

김일목의 이미지

State 패턴이 맞는지는 잘 모르겠는데요..
switch할 로직을 각각 다른 상태의 클래스로 만들어
그 로직이 수행 되어야 할때 해당하는 클래스의 객체를 만들어 수행하면 될것 같은데요..
인터페이스만 잘 만든다면 쉽게 할 수 있을것 같네요..

ikpil의 이미지

없애는 방법은 함수를 담은 자료구조가 있습니다.

저 같은 경우 switch도 꽤 좋다고 보기 때문에,
지저분해 보이지 않으면, 없애지 않습니다.

때론 switch 가 없어도 switch가 있으나 없으나, 크게 차이를 보이지 않을 때도 있습니다.
참조 링크 : http://lua-users.org/wiki/SwitchStatement -- 보시면 두 경우 다 루아 코드로 있습니다.

실험적으로 두 코드 다 유지해서 뭐가 더 좋은지 지켜 보는 것도 답이 될거 같네요.

ps.
제가 보기엔 세상에 존재하는 모든 코드는 다 지저분 합니다.
그 중에 제일 지저분하지 않는 것으로 선택하세요 :)

:wq

NN의 이미지

switch-case 자체는 가독성이 나쁘지 않습니다. indentation만 일관적으로 해주면 보기에 꽤 이쁘죠.

다만 case문 안의 내용들이 길어질때 가독성 문제가 대두될 수 있습니다.
그럴땐 case문 안의 내용들을 하나의 함수로 따로 빼서 call하세요.
안의 내용을 함수로 독립시키면 훨씬 가독성이 좋아질겁니다.

OO가 강제되지 않는 상황에서라면 다형성이나 패턴을 이용하는건 개인적으로 비추하고 싶습니다.
그런 방식들이 디자인적으로는 좋을지 몰라도 심리적으로는 직관적으로 와닿는 방식이 아니라서 말이죠.
게다가 불필요하게 코드의 복잡성을 가중시키는 측면이 있습니다.

객체지향이 심리적으로 직관적인가...하는 문제는 굉장히 논쟁적인 주제라 오프토픽으로라도 얘기 않으렵니다~

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.