2009-05-10 2 views
0

을 읽을 때 문자열의 beggining에서 캐리지 리턴을 추가 :C++ 나는이 개 질문이 파일

1) 왜 내 코드가 selected_line 문자열의 beggining에서 캐리지 리턴을 추가?
2) 파일에서 임의의 줄을 반환하는 데 사용하는 알고리즘이 충분히 좋다고해서 문제가 발생하지 않는다고 생각하십니까?

샘플 파일은 다음과 같습니다

line 
number one 
# 
line number two 

내 코드 : 당신의 도움에 미리

int main() 
{ 
    srand(time(0)); 
    ifstream read("myfile.dat"); 
    string line; 
    string selected_line; 
    int nlines = 0; 
    while(getline(read, line, '#')) { 
     if((rand() % ++nlines) == 0) 
      selected_line = line; 
    } 
    // this is adding a \n at the beggining of the string 
    cout << selected_line << endl; 
} 

감사합니다.

편집 : 좋아, 여러분 중 일부는 많은 의미가 있습니다. 이 문자열은 아마도 "\ nmystring"으로 읽혀질 것입니다. 그래서 내 질문에 지금 것 같아요 문자열에서 첫 번째 \ n 제거 할 것이라고?

+0

데이터는 무엇입니까? 파일 보이지? –

+0

Neil, fhe 데이터 파일은 단일 '#'문자가 포함 된 줄로 구분 된 단락으로 구성됩니다. –

답변

1

이 같은 당신이 아마 할 수 있습니다 :

std::vector<std::string> allParagraphs; 
std::string currentParagraph; 

while (std::getline(read, line)) {   
    if (line == "#") { // modify this condition, if needed 
     // paragraph ended, store to vector 
     allParagraphs.push_back(currentParagraph); 
     currentParagraph = ""; 
    else { 
     // paragraph continues... 
     if (!currentParagraph.empty()) { 
      currentParagraph += "\n"; 
     } 
     currentParagraph += line; 
    }   
} 

// store the last paragraph, as well 
// (in case it was not terminated by #) 
if (!currentParagraph.empty()) { 
    allParagraphs.push_back(currentParagraph); 
} 

// this is not extremely random, but will get you started 
size_t selectedIndex = rand() % allParagraphs.size(); 

std::string selectedParagraph = allParagraphs[selectedIndex]; 

더 나은 난수를 들어, 당신이 대신 선택할 수 있습니다 :

size_t selectedIndex 
    = rand()/(double) (RAND_MAX + 1) * allParagraphs.size(); 

이것은 rand()에 의해 반환되는 최하위 비트가 경향이 있기 때문에 무작위로 전혀 행동하지 마라.

+0

우수한 솔루션! 대단히 감사합니다! 나는 당신이 올린이 해결책으로 많은 것을 배웠다. 다시 한 번 감사드립니다! – nmuntz

+0

당신은 오신 것을 환영합니다. 나는 그것이 숙제가 아니기를 바란다. – Reunanen

+0

걱정이 없다, 나는 학생이 아니다. –

1

delimeter로 \n을 지정하지 않았기 때문에.

1

"임의"선택이 완전히 잘못되었습니다. 사실, 항상 첫 번째 라인을 선택합니다 : rand() % 1은 항상 0입니다.

존재하는 라인 수를 모른 채로 임의로 선을 일률적으로 선택하는 방법은 없습니다.

또한 왜 #을 구분 기호로 사용하고 있습니까? 기본적으로 Getline은 라인을 가져옵니다 (\ n로 끝남).

+0

아마도 파일을 두 번 읽어야합니다. 하나는 파일의 행 수이고, 다른 하나는 총 줄 수를 기준으로 임의의 줄을 읽어야합니다. 문단을 읽어야하기 때문에 #를 구분 기호로 사용하고, \ n에 도달하지 않으면 문단을 읽어야합니다. –

1

줄 바꿈은 인쇄하는 두 번째 줄부터 나타날 수 있습니다. 이는 getline 함수가 # 문자를 보았을 때 중지되고 다음에 입력 한 문자가 # 이후의 문자 인 줄 바꿈 문자 인 다음 문자부터 다시 호출 할 때 다시 시작하기 때문입니다. rand()을 사용하여 C FAQ 13.16을 효과적으로 읽으십시오.

하나의 제안은 한 파일에서 전체 파일을 읽고 vector에 줄을 저장 한 다음 필요에 따라 출력하는 것입니다.

+0

예 - 벡터에 선이 있으면 무작위로 선을 선택하기 쉽습니다. – Reunanen

0

#가 당신의 delimeter이기 때문에 그 delimeter 바로 다음에있는 \ n이 다음 행의 시작이되어 \ n이 당신의 줄 앞에 오게됩니다.

0

1) selected_line\n을 추가하지 않았습니다. 대신 '#'을 지정하면 파일에 여분의 \n자를 제거하지 않고있는 것입니다. 파일이 실제로이 같이 보입니다 참고 :

라인 \ n을 번호를 하나의 \ n을 # \ n을 라인의 두 번째 \ n 사전>

그래서 라인 두 번째는 실제로

"\ < \ nline number two \ n ".

2) 아니요. 임의로 줄을 선택하려면 먼저 파일의 줄 수를 결정해야합니다.

+0

나는 본다. 문자열의 시작점에서 "\ n"을 제거하는 쉬운 방법이 있습니까? –

+0

getline을 호출하기 전에 ifstream에서 공백을 제거하려면 다음과 같이하면됩니다. while (isspace (read.peek())) read.ignore(); – Naaff

0

당신은 \를 제거하기 위해 표준 : : 문자열 클래스의 SUBSTR 방법을 사용하여 N 후 사용할 라인을 결정할 수 :

등의
if (line.substr(0,1) == "\n") { line = line.substr(1); } 

는 말했다, 당신이 라인을 선택하려면 균일 한 무작위성을 얻으려면 먼저 모든 줄을 읽은 다음 줄 번호를 선택해야합니다. 1/2 확률로 라인 1을 선택하고 1/2 * 1/3 확률로 라인 2를 선택하는 if (rand() % (++ nlines + 1))를 사용할 수도 있습니다.