我有一个看似很直接的问题,但我找不到一个干净简单的解决方案。
我有一些自由格式化的文字。此文本可能很长,包含各种长度(> 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.
有人有什么想法吗?
答案 0 :(得分:5)
第一阶段
第2阶段
答案 1 :(得分:1)
假设您使用的是单个非比例字体,(因此行的宽度指定为字符数而不是厘米数)...
您的问题有几个部分。
首先,您希望将文本段落自动换行为不超过 n 个字符的行。基本方法是首先处理每个段落,使其成为单行文本(如果您还没有该表单中的输入),则使用变量作为“游标” - 将其放在索引 n 然后向后退一步,直到找到一些空格。这是适合该行的最后一个单词的结尾。将此行复制到行列表中,然后重复以将字符串分解为单词包装段落。
(注意:在某些情况下,您必须在此处理:您可能必须使用标点字符和连字符进行拆分,并且您可能必须处理比格式化宽度更长的“单个单词”。高级格式化您可能想要添加连字词典,以便您可以用连字符分割单词
获得段落后,您需要应用类似的算法将文档分成一页一页。再次,从 m 行的“光标”位置开始进入行列表(其中 m 是页面长度)。但是,您需要“寡妇和孤儿”控制,因此您需要添加一些逻辑,例如:
从根本上讲,这个过程非常简单,但是有很多关于你想要如何处理自动换行和换页的复杂性。一个简单的算法不会花费很长时间来敲门,但你可以花很多时间调整和改进它以达到“最好”(在你眼中,最少)的结果。
答案 2 :(得分: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;
}
正如您所看到的,我没有使用内部数组缓冲区,因此该程序可用于任何大型文件,但可能不如内存中的字符串算法快。
长于行的单词会写入自己的行(请参阅Main)。
只有空格和CRLF被视为单词分隔符。在实际情况中,您应该将此扩展到TAB或其他空格。