2013-01-09 39 views
21

Trong C++, một cách dễ dàng là những gì để biến:loại bỏ khoảng trắng trong std :: string

std này :: string

\t\tHELLO WORLD\r\nHELLO\t\nWORLD  \t 

Into:

HELLOWORLDHELLOWORLD 
+1

@ tomislav-maric Tôi không nghĩ rằng đó là một bản sao của bài đăng đó, OP đã làm việc với một luồng 'cin', và do đó sử dụng các chức năng iostream. –

+0

tương tự nhưng không trùng lặp chính xác, vì vậy không bỏ phiếu để đóng. – CashCow

+0

@CashCow Tôi đã kiểm tra lại lần nữa .. bạn đúng, xin lỗi về điều đó. – tmaric

Trả lời

33

kết hợp đơn giản của std::remove_ifstd::string::erase.

Không hoàn toàn an toàn phiên bản

s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end()); 

Đối với phiên bản an toàn hơn thay thế ::isspace với

std::bind(std::isspace<char>, _1, std::locale::classic()) 

(Bao gồm tất cả tiêu đề có liên quan)

Đối với một phiên bản làm việc với các loại nhân vật khác thay thế <char> với <ElementType> hoặc bất kỳ loại ký tự templated nào của bạn. Bạn cũng có thể thay thế miền địa phương bằng ngôn ngữ khác. Nếu bạn làm điều đó, hãy cẩn thận để tránh sự kém hiệu quả của việc tái tạo lại khía cạnh vị trí quá nhiều lần.

Trong C++ 11 bạn có thể làm cho các phiên bản an toàn hơn vào một lambda với:

[](char ch) { return std::isspace<char>(ch, std::locale::classic()); } 
+0

@chris ':: isspace' bao gồm cũng như: http://www.cplusplus.com/reference/cctype/isspace/ –

+0

nó sẽ. isspace sẽ trả về true cho dòng mới. – CashCow

+4

'isspace' có UB cho tất cả các ký tự ngoại trừ những ký tự trong thứ gì đó cơ bản. C99 §7.4/1. –

2

Bạn có thể sử dụng Boost.Algorithm 's erase_all

#include <boost/algorithm/string/erase.hpp> 
#include <iostream> 
#include <string> 

int main() 
{ 
    std::string s = "Hello World!"; 
    // or the more expensive one-liner in case your string is const 
    // std::cout << boost::algorithm::erase_all_copy(s, " ") << "\n"; 
    boost::algorithm::erase_all(s, " "); 
    std::cout << s << "\n"; 
} 

LƯU Ý: như được đề cập trong các ý kiến: trim_copy (hoặc các anh em họ của nó trim_copy_lefttrim_copy_right) chỉ xóa khoảng trắng từ đầu và cuối của chuỗi.

+0

Tôi thấy một số giải pháp đã sử dụng Boost, nhưng tôi không tuân theo chức năng 'trim', trang trí mà tôi tin là đang làm điều gì đó như' XX ___ XX_' -> 'XX_XX' trong khi tôi muốn giải pháp cuối cùng là' XXXX'. –

+0

@ Mr.Smith Tnx, đã cập nhật. – TemplateRex

11

Nếu C++ 03

struct RemoveDelimiter 
{ 
    bool operator()(char c) 
    { 
    return (c =='\r' || c =='\t' || c == ' ' || c == '\n'); 
    } 
}; 

std::string s("\t\tHELLO WORLD\r\nHELLO\t\nWORLD  \t"); 
s.erase(std::remove_if(s.begin(), s.end(), RemoveDelimiter()), s.end()); 

Hoặc sử dụng C++ 11 lambda

s.erase(std::remove_if(s.begin(), s.end(), 
    [](char c){ return (c =='\r' || c =='\t' || c == ' ' || c == '\n');}), s.end()); 

PS. Erase-remove idiom được sử dụng

1

Bước qua ký tự đó theo ký tự và sử dụng string::erase() sẽ hoạt động tốt.

void removeWhitespace(std::string& str) { 
    for (size_t i = 0; i < str.length(); i++) { 
     if (str[i] == ' ' || str[i] == '\n' || str[i] == '\t') { 
      str.erase(i, 1); 
      i--; 
     } 
    } 
} 
+1

Không hoạt động khi có các ký tự khoảng cách liền kề. Cái đầu tiên bị xóa, di chuyển con thứ hai xuống vị trí 'i'. Sau đó, bạn đi vòng quanh, tăng 'i', và không bao giờ kiểm tra thứ hai. –

+0

Bạn nói đúng. Sửa lỗi. – SelectricSimian

2

C++ 11

std::string input = "\t\tHELLO WORLD\r\nHELLO\t\nWORLD  \t"; 

auto rs = std::regex_replace(input,std::regex("\\s+"), ""); 

std::cout << rs << std::endl; 

/tmp ❮❮❮ ./play

HELLOWORLDHELLOWORLD 
3

Trong C++ 11 bạn có thể sử dụng một lambda hơn là sử dụng std :: bind:

str.erase(
    std::remove_if(str.begin(), str.end(), 
     [](char c) -> bool 
     { 
      return std::isspace<char>(c, std::locale::classic()); 
     }), 
    str.end()); 
Các vấn đề liên quan