[C++ / 초보자 / 코드첨부] Switch - Case 문에서 무한로프를 도는 이유를 모르겠습니다.


현재 fstream 공부 하던 중 아래와 같이 앞글자 키워드를 입력하면 해당기능이 수행되는 프로그램을 만들어 보고 있는데요.

각 함수를 만들다가 막혀서 일단 테스트해보면서 만들어 나아가보려고 메인 함수부터 만들고 있습니다.

어찌된 일인지 'B'와 같이키워드를 입력하면 "hi" 와 같이 해당 케이스의 기능이 수행되는 것이 아니라 디폴트 케이스의 "Wrong Input" 이 무한으로 나옵니다. 코드를 어찌 고쳐야할까요?... 빠른 답변 주시면 감사하겠습니다.

(초보자인지라 글만 봐서는 이해가 잘 안가서 코드로 설명해주시면 더욱 감사하겠습니다 ㅎㅎ)

이미지 이미지

아래는 코드입니다.

//header.h
#include <iostream>

class BookData
{
public:
    // default ClientData constructor
    BookData(int = 0, const std::string & = "", int = 0, double = 0.0);
    // accessor functions for lastName
    void setProductNumber(int);
    int getProductNumber() const;
    void setProductName(const std::string &);
    std::string getProductName() const;
    void setQuantity(int);
    int getQuantity() const;
    void setPrice(double);
    double getPrice() const;
private:
    int ProductNumber;
    char ProductName[15];
    int Quantity;
    double Price;
}; // end class ClientData

//header.cpp
#include <iostream>
#include "header.h"

BookData::BookData(int ProductNumValue,
                   const std::string &ProductNameString,
                   int QuantityValue,
                   double PriceValue)
            : ProductNumber(ProductNumValue), Quantity(QuantityValue), Price(PriceValue)
{
    setProductName(ProductNameString);
}

void BookData::setProductNumber(int ProductNumValue ) {
    this->ProductNumber = ProductNumValue;
}

int BookData::getProductNumber() const {
    return ProductNumber;
}

void BookData::setProductName(const std::string &ProductNameString) {
    int length = ProductNameString.size();
    length = (length < 15 ? length : 14);
    ProductNameString.copy(ProductName, length);
    ProductName[length] = '\0';
}

std::string BookData::getProductName() const {
    return ProductName;
}

void BookData::setQuantity(int QuantityValue) {
    this->Quantity = QuantityValue;
}

int BookData::getQuantity() const {
    return Quantity;
}

void BookData::setPrice(double PriceValue) {
    this->Price = PriceValue;
}

double BookData::getPrice() const {
    return Price;
}


// source.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include "header.h"
using namespace std;


void outputLine(ostream &output, const BookData &record) { // 출력시 단위 line
    double total = record.getQuantity() * record.getPrice();
    output << setfill(' ') << left << setw(10) << record.getProductNumber()
        << setw(15) << record.getProductName()
        << setw(15) << record.getQuantity()
        << setw(10) << record.getPrice()
        << setw(10) << total;
}

char enterChoice(void) {
    char choice;

    // 메뉴 문구를 수정하여도 문구가 자동으로 정렬되도록 하기위해 문구를 변수로 저장
    string title = "Main Menu";
    string menu_1 = "(S)how records on Screen";
    string menu_2 = "(U)pdate a Book";
    string menu_3 = "(A)dd a new Book";
    string menu_4 = "(D)elete a Book";
    string menu_5 = "(B)uild a File";
    string menu_6 = "(Q)uit";

    cout << endl;
    cout << '\t' << setfill('-')
        << setw(18 + title.length() / 2)
        << title    // 제목 출력(자동 가운데 정렬)
        << setw(18 - title.length() / 2)
        << ' ' << endl;
    cout << '\t' << 'I' << setfill(' ') << setw(34) << 'I' << endl;
    cout << '\t' << 'I'
        << setfill(' ') << setw(16 + menu_1.length() / 2)
        << menu_1       // 메뉴 1 출력(자동 가운데 정렬)
        << setw(18 - menu_1.length() / 2)
        << 'I' << endl;
    cout << '\t' << 'I'
        << setfill(' ') << setw(16 + menu_2.length() / 2)
        << menu_2       // 메뉴 2 출력(자동 가운데 정렬)
        << setw(18 - menu_2.length() / 2)
        << 'I' << endl;
    cout << '\t' << 'I'
        << setfill(' ')
        << setw(16 + menu_3.length() / 2)
        << menu_3       // 메뉴 3 출력(자동 가운데 정렬)
        << setw(18 - menu_3.length() / 2)
        << 'I' << endl;

    cout << '\t' << 'I'
        << setfill(' ')
        << setw(16 + menu_4.length() / 2)
        << menu_4       // 메뉴 4 출력(자동 가운데 정렬)
        << setw(18 - menu_4.length() / 2)
        << 'I' << endl;
    cout << '\t' << 'I'
        << setfill(' ')
        << setw(16 + menu_5.length() / 2)
        << menu_5       // 메뉴 5 출력(자동 가운데 정렬)
        << setw(18 - menu_5.length() / 2)
        << 'I' << endl;
    cout << '\t' << 'I'
        << setfill(' ')
        << setw(16 + menu_6.length() / 2)
        << menu_6       // 메뉴 6 출력(자동 가운데 정렬)
        << setw(18 - menu_6.length() / 2)
        << 'I' << endl;
    cout << '\t' << 'I' << setfill(' ') << setw(34) << 'I' << endl;
    cout << '\t' << 'I' << setfill('-') << setw(34) << 'I' << endl;

    /*do {
        cout << "\n? ";
        cin >> choice;
    } while (choice != ('S' || 's' || 'U' || 'u' || 'A' || 'a' ||
                        'D' || 'd' || 'B' || 'b' || 'Q' || 'q'));*/

    cout << '\t'; cin >> choice;
    return choice;
}

void showRecords(fstream &input) {
    ifstream inCredit("book.dat", ios::in | ios::binary);
    if (!inCredit) {
        cerr << "File could not be opened." << endl;
        exit(EXIT_FAILURE);
    }

    cout << left
        << setw(10) << "BkNum"
        << setw(15) << "ProdNum"
        << setw(15) << "Quantity"
        << setw(10) << "Price"
        << setw(10) << "Total"
        << endl;
    cout << setfill('-') << setw(60) << endl;

    BookData record;
    inCredit.read(reinterpret_cast <char *> (&record), sizeof(BookData));

    while (inCredit && !inCredit.eof()) {
        if (record.getProductNumber() != 0) {
            outputLine(cout, record);
        }
    }

    inCredit.read(reinterpret_cast <char *> (&record), sizeof(BookData));


    //double totalAmount;
    //cout << "Total Amount   : " << totalAmount;
}

void updateRecord(fstream &output) {
    int prodnum;
    cout << "------------------EDIT RECORD------------------" << endl << endl;
    cout << "Enter prod number to edit : " << prodnum;
}

void neweRecord(fstream &output) {
    int productNum;
    string productName;
    int quantity;
    double price;

    fstream outCredit1("book.dat", ios::in | ios::out | ios::binary);
    BookData record;

    // exit program if fstream cannot open file
    if (!outCredit1)
    {
        cerr << "File could not be opened." << endl;
        exit(EXIT_FAILURE);
    } // end if

    cout << "Enter product number (1 to  50, 0 to end input)" << endl << "?";
    //cout << "Enter product number (1 to " << recordsize << ", 0 to end input)" << endl << "?";
    cin >> productNum;

    while (productNum > 0 && productNum <= 50) {
        cout << "Enter product Name, quantity, price\n";
        cin >> productName;
        cin >> quantity;
        cin >> price;

        record.setProductNumber(productNum);
        record.setProductName(productName);
        record.setQuantity(quantity);
        record.setPrice(price);
    }

    outCredit1.seekp((record.getProductNumber() - 1) * sizeof(BookData));
    outCredit1.write(reinterpret_cast <const char *> (&record), sizeof(BookData));

    cout << "Enter product number (1 to  50, 0 to end input)" << endl << "?";
    //cout << "Enter product number (1 to " << recordsize << ", 0 to end input)" << endl << "?";
    cin >> productNum;

}

void deleteRecord(fstream &out) {

}

void buildFile()
{
    system("cls");
    cout << "\n----------------BUILD THE FILE---------------------" << endl;
    cout << "\nEnter number of records :";
    int recordsize;
    cin >> recordsize;

    ofstream outCredit1("book.dat", ios::out | ios::binary);

    // exit program if ofstream could not open file
    if (!outCredit1)
    {
        cerr << "File could not be opened." << endl;
        exit(EXIT_FAILURE);
    } // end if

    BookData blankbook; // constructor zeros out each data member
                        /*cout<<sizeof(blankbook)<<endl;*/

                        // output blank records to file
    for (int i = 0; i < recordsize; ++i)
        outCredit1.write(reinterpret_cast<const char *>(&blankbook),
            sizeof(BookData));

    outCredit1.close();
} // end main


int main() {
    char input = enterChoice();

    while (input = ('S' || 's' || 'U' || 'u' || 'A' || 'a' || 'D' || 'd' || 'B' || 'b' || 'Q' || 'q')) 
    {
        switch (input) {
            case 'S' :
            case 's' :
                //
                break;
            case 'U' :
            case 'u':
                //
                break;
            case 'A':
            case 'a':
                //
                break;
            case 'D':
            case 'd':
                //
                break;
            case 'B':
            case 'b':
                cout << "hi";
                //buildFile();
                //enterChoice();
                break;
            case 'Q':
            case 'q':
                input = false;
                break;
            default:
                cout << "Wrong Input" << endl;
                break;
        }
    }
}
  • 2016년 11월 01일에 작성됨

조회수 104


2 답변


좋아요
0
싫어요
채택취소하기
         default:
                cout << "Wrong Input" << endl;
                input = false;
                break;

위와 같이 input=false를 추가해보세요.

default일 경우에도 종료하는 것이라면, Q를 입력했을 때의 처리루틴이 포함되어야 합니다.

그렇지 않은 경우라면, 새로운 입력(input이 변경안됨.)을 받는 루틴이 없어서 발생하는 문제입니다.

  • 2016년 11월 01일에 작성됨
    리눅스(유닉스) 기반의 시스템에서 웹 서비스를 개발하고 있습니다.

  • 답변 감사합니다. 시도해보았지만 여전히 같은 증상이 발생합니다ㅠㅠ    이성우   2016.11.1 14:55     
  • 조건부분을 수정해보니 해결되었습니다. 조건 부분이 문제였던 것 같네요 ㅎㅎ 감사합니다.    이성우   2016.11.1 16:30     

먼저 질문자 분의 의도가

'Q' 혹은 'q' 를 입력 받기 전까지는 반복해서 입력을 받는다. 라면,

while 문 안에서 입력을 받아야 합니다.

그리고 'Q'혹은 'q'를 입력 받았아면, 반복문을 멈춰주시면 됩니다.

그리고 저도 c++안한지 오래돼서 잘모르겠지만.. while 문 안에 들어가는 조건문이 틀린것 같습니다.

위의 조건대로 main 함수를 수정해보면

int main() {
    char input;
    int flag = 1;

    while (flag) 
    {
        input  = enterChoice();

        switch (input) {
            case 'S' :
            case 's' :
                // 'S' or 's'
                cout << "in s" << endl;
                break;
            case 'U' :
            case 'u':
                // 'U' or 'u'
                cout << "in u" << endl;
                break;
            case 'A':
            case 'a':
                // 'A' or 'a'
                cout << "in a" << endl;
                input = 'w';
                break;
            case 'D':
            case 'd':
                // 'D' or 'd'
                cout << "in d" << endl;
                break;
            case 'B':
            case 'b':
                // 'B' or 'b'
                cout << "in b" << endl;
                cout << "hi";
                //buildFile();
                //enterChoice();
                break;
            case 'Q':
            case 'q':
                // 'Q' or 'q' quit
                cout << "in q" << endl;
                flag = 0;
                break;
            default:
                // default
                cout << "Wrong Input" << endl;
                break;
        }
    }
}

이렇게 하면 될 것 같습니다.

코드를 돌려보진 않아 오타가 있을 수 있고 기본적인 문법이 틀렸을 수도 있지만, 대략적으로 이렇게 돌아가는게 맞는것 같습니다.

  • 2016년 11월 01일에 작성됨

  • 감사합니다. 답변 잘 보았습니다.    이성우   2016.11.2 00:37     

로그인이 필요한 기능입니다.

Hashcode는 개발자들을 위한 무료 QnA사이트 입니다. 작성한 답변에 다른 개발자들이 댓글을 작성하거나 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.
► 로그인
► 계정만들기
Close