2016-11-14 6 views
-3

코드 테이블을 따라 파일에 저장된 문자 문자열을 문자 코드 문자열 (프로그래밍 코드)로 프로그래밍 방식으로 변환하려고합니다. 바이너리 코드 문자열은 파일로 이동해야하는데, 나중에이 파일을 다시 캐릭터 라인으로 되돌릴 수 있습니다 (디코딩). 코드 테이블의 코드는 허프만 알고리즘을 사용하여 생성되었으며 코드 테이블은 파일에 저장됩니다.사용자 지정 코드 테이블이 지정된 문자열 인코딩

E 110 
H 001 
L 11 
O 111 

부호화 「HELLO」 "0011101111111"

내 C++ 코드로서 출력 수가 없어한다 : 예를 들어, 문자 및 대응하는 코드는 다음과 같이 이격 단일되는 코드 테이블을 따라

인코딩 된 문자열을 완성합니다. 여기에 내 코드입니다 : "The_Quick_brown_fox_jumps_over_the_lazy_dog"의 입력 문자열을

int main 
{ 
    string English; 
    ifstream infile("English.txt"); 
    if (!infile.is_open()) 
    {  
     cout << "Cannot open file.\n";  
     exit(1); 
    } 

    while (!infile.eof()) 
    { 
     getline (infile,English); 
    } 
    infile.close(); 
    cout<<endl; 
    cout<<"This is the text in the file:"<<endl<<endl; 
    cout<<English<<endl<<endl; 

    ofstream codefile("codefile.txt"); 
    ofstream outfile ("compressed.txt"); 
    ifstream codefile_input("codefile.txt"); 
    char ch; 
    string st; 

    for (int i=0; i<English.length();) 
    { 
     while(!codefile_input.eof()) 
     { 
      codefile_input >> ch >> st; 
      if (English[i] == ch) 
      { 
       outfile<<st; 
       cout<<st; 
       i++; 
      } 
     } 
    } 
    return 0; 
} 

는, 출력 문자열은 011,100,110입니다,하지만 그것은 더 이상보다해야합니다!

output image

도와주세요! 내가 놓친 것이 있습니까? 다음 codefile_input을 통해 한 번 읽어

for (int i=0; i<English.length();) 
{ 
    while(!codefile_input.eof()) 
    { 
     codefile_input >> ch >> st; 
     if (English[i] == ch) 
     { 
      outfile<<st; 
      cout<<st; 
      i++; 
     } 
    } 
} 

귀하의 코드 것이고, :

+0

디버거에서 코드를 단계별로 실행 해 보았습니까? –

+1

첫 번째 문자의 인코딩 된 값을'codefile.txt'에서 찾은 후 그것을 써내고 두 번째 문자의 인코딩 된 값을 찾아야한다고 생각하십니까? 당신의'codefile_input'은 여전히 ​​파일의 중간에 있고 어딘가에 두번째 문자의 인코딩 된 값을 찾기 위해 마술처럼 파일의 처음으로 돌아 가지 않을 것입니다. –

+0

+ Sam 그래서 codefile_input을 어떻게 파일의 시작 부분으로 되돌릴 수 있습니까? –

답변

0

가의 메인 루프를 살펴 보자 (내 C++ 코드가없는 구문 오류가 없습니다 NB) , 당신은 당신의 일을하고있다 codefile_input.eof() == true 상태에서 멈추고 i가 증가하는 코드 경로가 없으므로 과 같은 값에 도달하지 않습니다. 따라서 for (int i=0; i<English.length();)은 무한 루프가됩니다.

보조 메모로 Why is iostream::eof inside a loop condition considered wrong?을 읽으십시오.

위에서 설명한 문제를 피하려면 사전 파일을 데이터 컨테이너 (예 : std::map)로 읽은 다음 인코딩 할 문자열을 반복하면서 사용하십시오. 예를 들어

:

std::ifstream codefile_input("codefile.txt"); 
char ch; 
std::string str; 
std::map<char, std::string> codes; 
while (codefile_input >> ch >> str) 
    { 
    codes[ch] = str; 
    } 

codefile_input.close(); 

for (int i=0; i<English.length(); ++i) 
    { 
    auto it = codes.find (English[i]); 
    if (codes.end() != it) 
     { 
     outfile << codes->second; 
     cout << codes->second; 
     } 
    } 

참고 std::map를 사용하는 #include <map>해야합니다. 다른 모든 라인을 폐기하면서

while (!infile.eof()) 
{ 
    getline (infile,English); 
} 

만, 파일의 마지막 줄을 읽 문제를 해결하는 것 외에도


는, 귀하의 질문에 대해, 대한, 루프는 사실이었다 그것보다 먼저 왔어.당신이 파일의 모든 라인을 처리 할 경우, 해당 루프를 변경하는 것을 고려 보낸 사람, 당신의 사전이 다른 라인에 대해 서로 다른 수 없을 수도 있습니다,

while (std::getline (infile, English)) 
    { 
    /* Line processing goes here */ 
    } 

, 당신은의 앞에, 그 논리를 이동할 수 있습니다 이 루프는 :

std::ifstream codefile_input("codefile.txt"); 
char ch; 
std::string str; 
std::map<char, std::string> codes; 
while (codefile_input >> ch >> str) 
    { 
    codes[ch] = str; 
    } 

codefile_input.close(); 

ifstream infile("English.txt"); 
if (!infile.is_open()) 
    {  
    cout << "Cannot open file.\n";  
    exit(1); 
    } 

ofstream outfile ("compressed.txt"); 
string English; 
while (std::getline (infile, English)) 
    { 
    for (int i=0; i<English.length(); ++i) 
     { 
     auto it = codes.find (English[i]); 
     if (codes.end() != it) 
      { 
      outfile << codes->second; 
      cout << codes->second; 
      } 
     } 
    } 

또한, 열려있는 모든 파일을 검사 오류를 추가하는 것이 좋습니다. 파일 English.txt을 열 수 있는지 확인한 다음 취소 할 수 있으면 종료하지만 다른 파일을 열 수 있는지 확인하지 않습니다. Why is “using namespace std” considered bad practice?을 읽는 고려 관련이없는 노트 # 2에


, (당신은 제가 추가 한 코드에서 명시 적으로 std::를 사용하여 참조 그 이유는).