2009-09-28 41 views
39

從std :: string中刪除'newline'的最有效方法是什麼?C++從多行字符串中刪除新行

+7

是換行預計將在一個特定的地方,如在字符串的結束? – 2009-09-28 19:02:26

+0

否;它可能在任何地方 – shergill 2009-09-28 19:32:53

回答

78
#include <algorithm> 
#include <string> 

std::string str; 

str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); 

性病的行爲::刪除可能不太是你所期望的東西。看到它的解釋here

+3

如果有其他平臺換行的機會,也許可以刪除'\ r'字符。第二次調用擦除和std :: remove等並不是什麼大問題。替代方法,如使用帶謂詞函數的std :: remove_if,可能會變慢。 – Steve314 2009-09-28 19:46:25

+0

如果您的數據最初是以文本(ascii,非二進制)模式打開的文件加載的,我相信它會自動將所有換行約定轉換爲簡單的'\ n'。我正在尋找確切的參考來證實。 – luke 2009-09-29 13:56:30

+0

http://msdn.microsoft.com/en-us/library/kt0etdcs%28VS.71%29.aspx - 這對於fread(),但我相信iostream讀取和寫入具有相同的行爲。 – luke 2009-09-29 14:06:01

0

如果它在字符串中的任何地方比你做不到比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 

它會刪除所有新行一次。

+1

這個實現不會正確處理連續的換行符,因爲無論元素是否被擦除,i都會遞增。 – 2009-09-28 19:08:21

+0

我剛剛注意到,我會編輯這個 – csiz 2009-09-28 19:27:20

5

如果換行預計將在字符串的結尾,則:

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); 
} 
+2

第一個版本完美。第二個版本更容易使用std :: erase(std :: removr(XXX)) – 2009-09-28 19:13:21

+0

我從來沒有對remove()的語義非常滿意,並且總是不得不查看它,因爲它不明顯。我上面的實現很簡單直接,但不是最高效的。如果效率很重要,則需要稍微不同的解決方案。 – 2009-09-28 19:57:20

+1

問題是「什麼是最有效的方法......」,所以我認爲效率很重要;) – Pieter 2009-09-28 22:53:31

6

您應該使用erase-remove idiom,正在尋找'\n'。這將適用於任何標準順序容器;不只是string

1
s.erase(std::remove(s.begin(), s.end(), '\n'), s.end()); 
1

的代碼刪除從字符串str所有換行符。

O(N)實現最佳服務沒有對​​SO的評論和評論在生產中。

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); 
0
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); 
-1

所有這些問題的答案似乎有點重了我。

如果你只是扁平地移除'\ n'並將其他所有東西都移回一個地方,那麼你很可能會以怪異的方式將一些角色撞在一起。那麼爲什麼不做簡單的(也是最有效的)呢:把所有'\ n's替換爲空格?

for (int i = 0; i < str.length();i++) { 
    if (str[i] == '\n') { 
     str[i] = ' '; 
    } 
} 

有可能提高這一邊緣處的速度的方式,但它會比在內存中移動字符串的整個拿去方式更快。

4

這是一個DOS或Unix新行:

void chomp(string &s) 
    { 
      int pos; 
      if((pos=s.find('\n')) != string::npos) 
        s.erase(pos); 
    } 
+1

將'if'改爲'while'循環,你有一個很好的解決方案。 – CaptainBli 2015-05-01 17:26:38

1

另一種方式來做到這一點在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 
0

關於答案3只刪除最後\ n off字符串代碼:

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); 
}