PHP换行和非打印字符串


PHP wordwrap and non-printing strings

我卡住了,卡住了,卡住了。

我正在写一个需要一个方法的类,我找不到一个完全通过我写的所有单元测试的解决方案,每个解决方案都有一些小问题。

该方法正在换行文本(但带有catch),并有三个参数:

  • $text(需要换行的字符串)
  • $width(换行宽度)
  • $markup -一个标记字符串数组,可以在$text的不同位置随机放置,并将用于稍后对文本进行风格化(因此被删除)。

例如,如果有一组标记字符串[“!!”,”<lime>”](它们可以是任何东西),并且文本“This is a !!word!!! and this is some <lime>fruit<lime>.”将其换行为宽度为25个字符:

1234567890123456789012345
This is a word and this 
is some fruit.

这将是正确的包装,但为了使wordwrap工作,我必须删除标记并运行PHP的wordwrap(它将'n适当地放入文本字符串中),然后返回标记以供稍后处理。

所以,这里是问题,我宁愿使用php的wordwrap函数,而不是滚动我自己的,作为最佳实践。以下是我到目前为止尝试过的解决方案,但在单元测试中失败了:
  • 将$标记字符串替换为' 'a ' (beep -的转义序列)使用我认为不会使用的字符),跟踪在一个单独的数组中,运行自动换行,然后将$标记字符串放回现在带文字包装的字符串

    • 失败,因为换行将'a视为一个字符,因此更多
  • 将标记及其位置保存在一个单独的数组中,并尝试重建字符串

    • 越来越好,但我存储的位置是相对的,这意味着当我开始恢复标记值时,字符串正在拉伸,位置值无效

我开始保留两根弦,剥离的和原始的,然后沿着每根弦重建原始的,但这看起来……很丑。这让我相信我一定错过了什么。

任何想法?

下面是用于剥离和替换的第二个解决方案辅助函数:

/* **获取文本并替换所有标记,并存储标记和*它们在markupInText中的位置供以后使用** @param $text* @返回字符串-文本与所有标记切换到/a*/{

// if there are any markups
if ($this->markupStyles) {

    // get all the markups
    $markups = array_keys($this->markupStyles);
    // go through each markup
    foreach ($markups AS $nextMarkup) {
        // search through the string
        $offset = 0;
        // search for the next markup
        while (($pos = strpos($text, $nextMarkup, $offset)) !== false) {
            // add the position to the array of position for the markup
            $this->markupInText[$nextMarkup][] = $pos;
            // move the offset as far as the next markup
            $offset = $pos + strlen($nextMarkup);
        }
    }
    // strip out the markup
    foreach ($markups AS $nextMarkup) {
        // replace each string with blank
        $text = str_replace($nextMarkup,"",$text);
    }
}
return $text;

}

/**
 * Return the markup that was stripped of markup to its former glory
 * @param $text
 * @return string - the restored text
     */
public function returnMarkup($text) {

// go through each markup
foreach ($this->markupInText AS $markup => $posArray) {
    // go through the range of positions
    foreach ($posArray AS $pos) {
        // put back the markup
        $text = substr($text,0,$pos) . $markup . substr($text,$pos);
    }

}
// reset the markup in text
$this->markupInText = [];
// return the restored text
return $text;

}

// part of the suite of test cases that fails:
        $original = "This<red> is<red> !s!o!m!e text.";
        $answer = $markup->stripMarkup($original);
        $this->assertSame("This is some text.",$answer);
        $answer = $markup->returnMarkup($answer);
        $this->assertSame($original, $answer);
// phpunit failure
Failed asserting that two strings are identical.
Expected :This<red> is<red> !s!o!m!e text.
Actual   :This <red>is <red>some text.!!!!

越来越好了,但是我存储的位置是相对的,意思是当我开始恢复标记值时,字符串正在拉伸和位置值无效

如果您将它们存储在原始字符串中的绝对位置,那么您可以递归地(即每次更新新字符串后)将它们添加回原始位置。你唯一需要考虑的是wordwrap新增的'n字符。假设原始字符串不包含任何换行字符,在插入时,您还将计算'n s出现的次数,直到您要插入的位置,并通过添加该数字重新计算其余的插入点。