如何从字符串 c++ 中删除子字符串

发布于 2024-11-26 22:50:22 字数 438 浏览 1 评论 0原文

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

我想在 s1="home/dir/folder" 中拆分 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=names2 怎么样?

I have a string s="home/dir/folder/name"

I want to split s in s1="home/dir/folder" and s2="name";

I did:

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

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

now s1=name. What about s2?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

如梦亦如幻 2024-12-03 22:50:22

我建议不要使用 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;
}

I'd recommend against using strtok. Take a look at Boost Tokenizer instead (here are some examples).

Alternatively, to simply find the position of the last '/', you could use 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;
}
我要还你自由 2024-12-03 22:50:22

如果您的目标只是获取 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));
}

当然,您也可以修改此函数以抛出错误,而不是在路径不具有预期格式时优雅退出。

If your goal is only to get the position of the last \ or / in your string, you might use string::find_last_of which does exactly that.

From there, you can use string::substr or the constructor for std::string that takes iterators to get the sub-part you want.

Just make sure the original string contains at least a \ or /, or that you handle the case properly.

Here is a function that does what you need and returns a pair containing the two parts of the path. If the specified path does not contain any \ or / characters, the whole path is returned as a second member of the pair and the first member is empty. If the path ends with a / or \, the second member is empty.

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

Of course you might as well modify this function to throw an error instead of gracefully exiting when the path does not have the expected format.

雪花飘飘的天空 2024-12-03 22:50:22

几点:第一,你使用strtok是未定义的行为;在
对于 g++ 来说,它甚至可能导致一些非常奇怪的行为。你
无法修改字符串后面的 std::string 的内容
并期望能够逃脱惩罚。 (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() );

Several points: first, your use of strtok is undefined behavior; in
the case of g++, it could even lead to some very strange behavior. You
cannot modify the contents of an std::string behind the strings back
and expect to get away with it. (The necessity of a const_cast should
have tipped you off.)

Secondly, if you're going to be manipulating filenames, I'd strongly
recommend boost::filesystem. It knows all about things like path
separators and the like, and the fact that the last component of a path
is generally special (since it may be a filename, and not a directory).

Thirdly, if this is just a one-of, or for some other reason you can't or
don't want to use Boost:

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

will give you an iterator to the first character after the last '/', or
to the first character in the string if there isn't one. After that,
it's a simple to use the two iterator constructors of string to get the
two components:

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

And if you later have to support Windows, just replace the find with:

static std::string const dirSeparators( "\\/" );
std::string::const_iterator pivot
    = std::find_first_of( s.rbegin(), s.rend(),
                          dirSeparators.begin(), dirSeparators.end() );
江湖彼岸 2024-12-03 22:50:22

查看Boost 字符串分割

例子:

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" }

Check out boost string split.

Example:

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" }
茶花眉 2024-12-03 22:50:22

您不能在 std::string 上使用 strtok
strtok 将修改字符串。它破坏了 c_str() 契约。

执行 const_cast<> 是错误的一个重要标志。

You can't use strtok on std::string.
strtok would modify the string. It break the c_str() contract.

Doing const_cast<> is a big sign for error.

想挽留 2024-12-03 22:50:22

只需使用字符串方法:

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
  • 如果您正在使用文件系统路径,请查看 boost::filesystem
  • 如果您想一般使用标记化,请使用流运算符
  • 或 boost::tokenizer

Just use the string methods:

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

Two bits of advice:

  • Don't use strtok EVER
  • If you are playing with file system paths look at boost::filesystem
  • If you want to play generally with tokenization use the stream operators
  • Or boost::tokenizer
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文