C ++从多行字符串中删除新行
Posted
技术标签:
【中文标题】C ++从多行字符串中删除新行【英文标题】:C++ Remove new line from multiline string 【发布时间】:2010-12-02 02:32:40 【问题描述】:从 std::string 中删除“换行符”最有效的方法是什么?
【问题讨论】:
是否希望换行符出现在特定位置,例如字符串末尾? 没有;它可能在任何地方 【参考方案1】:关于答案 3 仅删除最后一个 \n 关闭字符串代码:
if (!s.empty() && s[s.length()-1] == '\n')
s.erase(s.length()-1);
如果字符串真的为空,if条件会不会失败?
这样做不是更好吗:
if (!s.empty())
if (s[s.length()-1] == '\n')
s.erase(s.length()-1);
【讨论】:
不,第一个版本应该在字符串为空时中止if语句【参考方案2】:在 for 循环中的另一种方法
void rm_nl(string &s)
for (int p = s.find("\n"); p != (int) string::npos; p = s.find("\n"))
s.erase(p,1);
用法:
string data = "\naaa\nbbb\nccc\nddd\n";
rm_nl(data);
cout << data; // data = aaabbbcccddd
【讨论】:
【参考方案3】:这是 DOS 或 Unix 换行符:
void chomp( string &s)
int pos;
if((pos=s.find('\n')) != string::npos)
s.erase(pos);
【讨论】:
将if
更改为while
循环,您就有了一个很好的解决方案。【参考方案4】:
如果它在字符串中的任何位置都比你不能做得比 O(n) 更好。
唯一的方法是在字符串中搜索'\n'并删除它。
for(int i=0;i<s.length();i++) if(s[i]=='\n') s.erase(s.begin()+i);
换行符多于:
int n=0;
for(int i=0;i<s.length();i++)
if(s[i]=='\n')
n++;//we increase the number of newlines we have found so far
else
s[i-n]=s[i];
s.resize(s.length()-n);//to delete only once the last n elements witch are now newlines
它会删除所有换行符一次。
【讨论】:
这个实现不能正确处理连续的换行符,因为i
不管元素是否被删除都会递增。【参考方案5】:
所有这些答案对我来说似乎有点沉重。
如果您只是完全删除“\n”并将其他所有内容移回一个位置,您很可能会以一种看起来很奇怪的方式将一些字符拼凑在一起。那么为什么不干脆做最简单(也是最有效)的事情:用空格替换所有 '\n's?
for (int i = 0; i < str.length();i++)
if (str[i] == '\n')
str[i] = ' ';
可能有一些方法可以提高边缘的速度,但它比在内存中移动整个字符串块要快得多。
【讨论】:
【参考方案6】: std::string some_str = SOME_VAL;
if ( some_str.size() > 0 && some_str[some_str.length()-1] == '\n' )
some_str.resize( some_str.length()-1 );
或(在末尾删除几个换行符)
some_str.resize( some_str.find_last_not_of(L"\n")+1 );
【讨论】:
【参考方案7】:#include <algorithm>
#include <string>
std::string str;
str.erase(std::remove(str.begin(), str.end(), '\n'), str.end());
std::remove 的行为可能不是您所期望的。请参阅 here 的解释。
【讨论】:
如果其他平台有换行的机会,也可以删除'\r'字符。第二次调用 erase 和 std::remove 等在性能方面没什么大不了的。替代方法,例如将 std::remove_if 与谓词函数一起使用,可能会更慢。 如果您的数据最初是从以文本(ascii,非二进制)模式打开的文件加载的,我相信它会自动将所有换行符约定转换为简单的 '\n'。我正在寻找一个明确的参考来证实。 msdn.microsoft.com/en-us/library/kt0etdcs%28VS.71%29.aspx -- 那是 fread(),但我相信 iostream 读取和写入具有相同的行为。std::remove
引用中的关键语句是 “调用 remove 之后通常会调用容器的擦除方法,该方法会擦除未指定的值并减小容器以匹配其新的逻辑大小。”
最后一行的最后一个参数可以是cend()
,如str.erase(std::remove(str.begin(), str.end(), '\n'), str.cend());
【参考方案8】:
代码从字符串str
中删除所有 个换行符。
O(N) 实现最好在 SO 上不使用 cmets 并且在生产中使用 cmets。
unsigned shift=0;
for (unsigned i=0; i<length(str); ++i)
if (str[i] == '\n')
++shift;
else
str[i-shift] = str[i];
str.resize(str.length() - shift);
【讨论】:
【参考方案9】:s.erase(std::remove(s.begin(), s.end(), '\n'), s.end());
【讨论】:
【参考方案10】:使用 std::算法。这个问题有一些适当的可重复使用的建议Remove spaces from std::string in C++
【讨论】:
【参考方案11】:您应该使用erase-remove idiom,寻找'\n'
。这适用于任何标准序列容器;不仅仅是string
。
【讨论】:
【参考方案12】:如果换行符应该在字符串的末尾,那么:
if (!s.empty() && s[s.length()-1] == '\n')
s.erase(s.length()-1);
如果字符串可以在字符串的任何位置包含许多换行符:
std::string::size_type i = 0;
while (i < s.length())
i = s.find('\n', i);
if (i == std::string:npos)
break;
s.erase(i);
【讨论】:
第一个版本完美。第二个版本会更容易使用 std::erase(std::removr(XXX)) 我从来没有对 remove() 的语义感到非常满意,并且总是不得不查找它,因为它并不明显。我上面的实现简单直接,但不是最有效的。如果效率很重要,则需要稍微不同的解决方案。 问题是,“什么是最有效的方法......”,所以我想效率很重要;)以上是关于C ++从多行字符串中删除新行的主要内容,如果未能解决你的问题,请参考以下文章