簡體   English   中英

如何從字符串c ++中刪除子字符串

[英]how to remove substring from string c++

我有一個string s="home/dir/folder/name"

我想在s1="home/dir/folder"s2="name";拆分s s2="name";

我做了:

char *token = strtok( const_cast<char*>(s.c_str() ), "/" );
std::string name;
std::vector<int> values;
while ( token != NULL )
{
    name=token;

    token = strtok( NULL, "/" );
}

現在s1=name s2怎么樣?

我建議不要使用strtok 請改為使用Boost Tokenizer (以下是一些示例 )。

或者,要簡單地找到最后一個'/'的位置,您可以使用std::string::rfind

#include <string>
#include <iostream>

int main() {
  std::string s = "home/dir/folder/name";
  std::string::size_type p = s.rfind('/');
  if (p == std::string::npos) {
    std::cerr << "s contains no forward slashes" << std::endl;
  } else {
    std::string s1(s, 0, p);
    std::string s2(s, p + 1);
    std::cout << "s1=[" << s1 << "]" << std::endl;
    std::cout << "s2=[" << s2 << "]" << std::endl;
  }
  return 0;
}

如果您的目標只是獲取string最后一個\\/的位置,則可以使用string :: find_last_of來完成該操作。

從那里,您可以使用string :: substrstd::string的構造函數,它將獲取迭代器以獲取所需的子部分。

只需確保原始字符串至少包含\\/ ,或者您正確處理案例。

這里是做你需要什么,並返回一個功能pair包含路徑的兩個部分。 如果指定的路徑不包含任何\\/字符,則整個路徑將作為該對的第二個成員返回,並且第一個成員為空。 如果路徑以/\\結尾,則第二個成員為空。

using std::pair;
using std::string;

pair<string, string> extract_filename(const std::string& path)
{
  const string::size_type p = path.find_last_of("/\\");

  // No separator: a string like "filename" is assumed.
  if (p == string::npos)
    return pair<string, string>("", path);

  // Ends with a separator: a string like "my/path/" is assumed.
  if (p == path.size())
    return pair<string, string(path.substr(0, p), "");

  // A string like "my/path/filename" is assumed.
  return pair<string, string>(path.substr(0, p), path.substr(p + 1));
}

當然,您也可以修改此函數以拋出錯誤,而不是在路徑沒有預期格式時正常退出。

查看提升字符串拆分

例:

string str1("hello abc-*-ABC-*-aBc goodbye");
typedef vector< iterator_range<string::iterator> > find_vector_type;
find_vector_type FindVec; // #1: Search for separators
ifind_all( FindVec, str1, "abc" ); // FindVec == { [abc],[ABC],[aBc] }
typedef vector< string > split_vector_type;
split_vector_type SplitVec; // #2: Search for tokens
split( SplitVec, str1, is_any_of("-*"), token_compress_on ); 
// SplitVec == { "hello abc","ABC","aBc goodbye" }

幾點:首先,你使用strtok是未定義的行為; 在g ++的情況下,它甚至可能導致一些非常奇怪的行為。 你不能修改std::string后面的std::string的內容,並希望能夠逃脫它。 const_cast的必要性應該讓你const_cast 。)

其次,如果您要操作文件名,我強烈建議使用boost::filesystem 它知道所有關於路徑分隔符之類的東西,以及路徑的最后一個組件通常是特殊的(因為它可能是文件名,而不是目錄)。

第三,如果這只是一個,或者由於其他原因你不能或不想使用Boost:

std::string::const_iterator pivot
    = std::find( s.rbegin(), s.rend(), '/' ).base();

將為最后一個'/'后面的第一個字符提供一個迭代器,如果沒有一個字符串,則為字符串中的第一個字符。 之后,使用string的兩個迭代器構造函數來獲取兩個組件是一件簡單的事情:

std::string basename( pivot, s.end() );
std::string dirname( s.begin(), pivot == s.begin() ? pivot : pivot - 1 );

如果您以后必須支持Windows,只需將find替換為:

static std::string const dirSeparators( "\\/" );
std::string::const_iterator pivot
    = std::find_first_of( s.rbegin(), s.rend(),
                          dirSeparators.begin(), dirSeparators.end() );

你不能在std::string上使用strtok strtok會修改字符串。 它打破了c_str()契約。

執行const_cast<>是出錯的重要標志。

只需使用字符串方法:

std::string  s="home/dir/folder/name"
std::string::size_type n = s.find_last_of("/");
std::string  s1 = s.substr(0,n);

if (n != std::string::npos) // increment past the '/' if we found it
{  ++n;
}
std::string  s2 = s.substr(n);

兩點建議:

  • 不要使用strtok EVER
  • 如果您正在使用文件系統路徑,請查看boost :: filesystem
  • 如果您想通常使用標記化來使用流運算符
  • 或者boost :: tokenizer

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM