2011-01-20 4 views
1

나는 아주 솔직하게 보이는 문제가 있지만 깨끗하고 간단한 솔루션을 찾을 수 없습니다.고정 텍스트 형식으로 자유 텍스트 다시 형식화 (C#)

  • 자유롭게 서식이 지정된 텍스트가 있습니다. 이 텍스트는 상당히 길 수 있으며 다양한 길이 (> 120 자)의 단락, 단락 및 빈 줄이 들어 있습니다.

  • 이 텍스트를 고정 된 형식 (예 : 120 자의 줄과 25 줄의 줄)으로 표시해야합니다. 그러나 단락과 빈 줄에 원래 서식을 유지.

한 마디가 중간에 없어야합니다. 우리는 페이지 하단에 새 단락의 단일 라인을 피하고 오히려 다음 페이지 등으로 전체 단락을 이동할 수 있도록 이상적으로 페이지 나누기가 배치해야

단순화 된 샘플 (입력 텍스트) :


Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec at magna at tellus vehicula eleifend. Vivamus at est erat. Phasellus eget tincidunt tellus. Integer ultrices dolor a magna congue imperdiet. 

Duis est sem, aliquet id fermentum sed, mollis nec metus. Phasellus porttitor porttitor sodales. Aliquam tincidunt convallis massa, sed tempus erat ornare in. Sed scelerisque, lorem accumsan imperdiet accumsan, mauris turpis molestie augue, vehicula egestas tellus quam ac nulla. 

In porta augue ac dolor imperdiet semper. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin lacus neque, tempor nec feugiat sed, posuere sed lorem. 

Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nulla metus neque, volutpat vitae pharetra rutrum, malesuada in dolor. 


Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
Donec at magna at tellus vehicula eleifend. Vivamus at 
est erat. Phasellus eget tincidunt tellus. Integer 
ultrices dolor a magna congue imperdiet. 

Duis est sem, aliquet id fermentum sed, mollis nec metus. 
Phasellus porttitor porttitor sodales. Aliquam tincidunt 
convallis massa, sed tempus erat ornare in. Sed scelerisque, 
lorem accumsan imperdiet accumsan, mauris turpis molestie 
augue, vehicula egestas tellus quam ac nulla. 
[pagebreak] 
In porta augue ac dolor imperdiet semper. Vestibulum ante 
ipsum primis in faucibus orci luctus et ultrices posuere 
cubilia Curae; Proin lacus neque, tempor nec feugiat sed, 
posuere sed lorem. 

Class aptent taciti sociosqu ad litora torquent per conubia 
nostra, per inceptos himenaeos. Nulla metus neque, volutpat 
vitae pharetra rutrum, malesuada in dolor. 

누구나 어떤 아이디어가 :

"고정"너비가 페이지 나누기 (프로그램의 출력)으로 포맷?

+1

여기 정확히 무슨 문제가 있습니까? 그것은 분명하고 쉽게 내게 보인다. 어디서부터 시작해야할지 몰라요. –

+2

@Al과 동의; 지나치게 가혹한 것은 아니지만이 작업의 특정 측면에 대해 혼란 스럽습니까? 아니면 다른 사람을 찾고 있습니까? –

+0

먼저 MAX_LINE_LENGTH 이상으로 올라갈 때까지 단어를 추가하여 시도해 보았습니다. 그런 다음 줄 바꿈을 삽입했습니다. 원본 텍스트의 줄 바꿈은 두 개가 아닌 경우 (즉, 새 단락) 무시됩니다. 줄 바꿈 횟수> MAX_LINES_ON_PAGE 페이지 나누기를 삽입하고 카운터를 재설정하고 계속합니다. 그것은 작동하지만 코드가 정확히 내가 아름답다고 부르는 것은 아닙니다. 그 이유는 누군가가 더 나은 솔루션을 가지고 있는지 물어보고 싶었습니다 :) – Paaland

답변

5

단계 나는

  1. 하나의 문자열에 텍스트를 읽어보십시오.
  2. 줄 바꿈 문자 (\ n)의 줄 (줄 [])로 줄을 나눕니다.

단계 2 명의

  1. 은 모두 StringBuilder를 초기화합니다.
  2. 회선 컬렉션을 반복하고 각 줄을 공백 문자의 단어 배열로 나눕니다. 그런 다음 단어 배열을 반복하고 각각을 문자열 작성기에 추가하십시오. 행 길이가 임계 값을 초과하면 개행 문자를 삽입하십시오. 줄 배열이 끝났 으면 줄 바꿈 문자와 함께 stringbuilder! Ends와 함께 마지막 줄이 정확히 임계 길이인지 확인한 다음 단락 나누기에 두 개의 줄 바꿈 문자를 추가하십시오.
1

가정 단일 비례 폰트를 사용하고 있기 때문에 (라인의 너비는 센티미터가 아닌 문자 수로 지정됩니다) ...

먼저 텍스트 단락을 n 자 이상의 행으로 줄 바꿈하려고합니다. 기본 접근법 ch는 먼저 각 단락을 처리하여 한 줄의 텍스트가되게하고 (그 형식으로 입력이없는 경우) 변수를 '커서'로 사용 - 색인 n에 놓은 다음 당신이 공백을 찾을 때까지 뒤로 물러서십시오. 이 줄에 들어갈 마지막 단어의 끝입니다. 이 줄을 줄 목록에 복사하고 반복하여 줄을 단어 줄 바꿈 단락으로 나눕니다.

(참고 : 여기서 처리해야하는 경우가 있습니다. 구두점 및 하이픈으로 분리해야 할 수 있으며 서식 너비보다 긴 "한 단어"를 처리해야 할 수도 있습니다. 보다 고급 형식의 하이픈 넣기 사전을 추가하여 하이픈으로 단어를 나눌 수 있습니다.)

단락이 있으면 비슷한 알고리즘을 적용하여 한 번에 한 페이지 씩 문서를 나눌 필요가 있습니다. 다시 말하지만, m 라인 목록 (여기서 m은 페이지 길이 임) 인 '커서'위치부터 시작하십시오. 그러나 "과부와 고아"제어하려면, 그래서 당신은 어떤 논리를 추가해야합니다 예 : 페이지의 첫 줄 (들)이 비어있는 경우

  • , 삭제 (그래서 당신은 공백을하지 않습니다 페이지 상단). 이것은 물론 더 많은 줄이 페이지의 맨 아래로 흐르게됩니다.
  • 페이지의 첫 번째 줄이 단락의 끝 부분 인 경우 (즉, 페이지의 두 번째 줄이 비어있는 경우) 이전 페이지의 마지막 줄을 위로 이동하여 고아 줄을 수정할 수 있습니다 페이지. (단, 매우 짧은 단락이 아닌 단락의 경우 고아가 꼬리 인 경우에만 해당)
  • 페이지의 마지막 줄이 새 단락의 시작 인 경우 (즉, 두 번째 줄부터 마지막 ​​줄이 비어 있음) 다음 페이지의 시작 부분으로 이동하십시오.

기본적으로 프로세스는 매우 간단하지만 단어 감싸기와 페이지 감싸기를 어떻게 처리 할 것인지에 대해서는 약간의 복잡성이 있습니다. 간단한 알고리즘으로는 노크하는 데 시간이 오래 걸릴 수는 없지만, "최상의"(눈을 감안할 때) 결과를 얻으려면 많은 시간을 조정하고 개선해야합니다.

+0

"monowidth font"라고합니다. – Andrey

+0

좋은 통찰력과 생각. 나는 간단한 알고리즘으로 시작된 것이 몬스터로 성장했다는 것을 경험으로 알고 있습니다. 당신은 나에게 새로운 아이디어를 주었고, 내일 다시 시도 할 것입니다. – Paaland

+0

@Andrey : 많은 동의어/별칭이 있습니다. 모노 폭, 모노 스페이스, 고정 피치 또는 비 비례가 모두 일반적입니다. –

0

좋아, 우리는 단어와 문단에 텍스트를 분할하는 경우, 우리는 단순히 출력에 단어 단어를 추가 할 수 있습니다

const int linewidth = 50; 

static void Main(string[] args) { 

    using(StreamReader r = new StreamReader("text1.txt")) { 
    using(StreamWriter w = new StreamWriter("text2.txt")) { 

     int written = 0; 

     while(true) { 
     string word = ReadWord(r); 
     if(word == null) break; //end of file 
     if(word == "") { 
      //end of paragraph 
      w.Write("\r\n\r\n"); 
      written = 0; 
     } 

     if(written + word.Length > linewidth) { 
      //endline 
      w.Write("\r\n"); 
      written = 0; 
      int i = 0; 
      while(word[i] == ' ') i++; 
      w.Write(word.Substring(i)); 
      written = word.Length - i; 
     } else { 
      w.Write(word); 
      written += word.Length; 
     } 
     } 
    } 
    } 
} 

그래서 우리는 몇 가지 스마트 "단어 리더"가 필요합니다

static int c = -1; 

static string ReadWord(StreamReader r) { 
    string word = ""; 
    bool started = false; 

    if(c == -1) c = ReadChar(r); 

    while(true) { 
    if(c == -1) { 
     //eof 
     if(word == "") return null; 
     return word; 
    } 
    word += (char)c; 
    c = r.Read(); 
    if(c != ' ') started = true; 
    else if(started) break; 
    } 

    return word; 
} 

이 단어 판독기에는 모든 행 끝을 공백으로 처리하고 빈 줄을 단락으로 인식하는 스마트 문자 판독기가 필요합니다.

static bool lineend = false; 

static int ReadChar(StreamReader r) { 
    int c = r.Read(); 
    if(c == '\n') c = r.Read(); 
    if(c == '\r') { 
    if(lineend) return '\r'; 
    lineend = true; 
    return ' '; 
    } 
    lineend = false; 
    return c; 
} 

보시다시피, 나는 내부 배열 버퍼를 사용하지 않으므로, 프로그램은 어떤 큰 파일에도 사용될 수 있지만, 문자열로 메모리에있는 알고리즘만큼 빠르지는 않습니다.

줄보다 긴 단어는 해당 줄에 쓰여집니다 (주 참조).

공백과 CRLF 만 단어 구분 기호로 취급됩니다. 실제 단어 상황에서는 이것을 TAB 또는 다른 공백으로 확장해야합니다.

관련 문제