C++ 如何检查字符串是否以 .txt 结尾
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20446201/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to check if string ends with .txt
提问by Chronicle
I am learning basic C++, and right now I have gotten a string from a user and I want to check if they typed the entire file name (including .txt) or not. I have the string, but how can I check if the string ends with ".txt" ?
我正在学习基本的 C++,现在我从用户那里得到了一个字符串,我想检查他们是否输入了整个文件名(包括 .txt)。我有字符串,但如何检查字符串是否以 ".txt" 结尾?
string fileName;
cout << "Enter filename: \n";
cin >> fileName;
string txt = fileName.Right(4);
The Right(int)
method only works with CString, so the above code does not work. I want to use a regular string, if possible. Any ideas?
该Right(int)
方法仅适用于 CString,因此上述代码不起作用。如果可能,我想使用常规字符串。有任何想法吗?
回答by Dietrich Epp
Unfortunately this useful function is not in the standard library. It is easy to write.
不幸的是,这个有用的函数不在标准库中。写起来很容易。
bool has_suffix(const std::string &str, const std::string &suffix)
{
return str.size() >= suffix.size() &&
str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}
回答by erenon
Using boost ends_withpredicate:
使用boostends_with谓词:
#include <boost/algorithm/string/predicate.hpp>
if (boost::ends_with(fileName, ".txt")) { /* ... */ }
回答by Jerry Coffin
You've gotten quite a few answers already, but I decided to add yet another:
你已经得到了很多答案,但我决定再添加一个:
bool ends_with(std::string const &a, std::string const &b) {
auto len = b.length();
auto pos = a.length() - len;
if (pos < 0)
return false;
auto pos_a = &a[pos];
auto pos_b = &b[0];
while (*pos_a)
if (*pos_a++ != *pos_b++)
return false;
return true;
}
Since you have gotten quite a few answers, perhaps a quick test and summary of results would be worthwhile:
既然你已经得到了很多答案,那么快速测试和总结结果可能是值得的:
#include <iostream>
#include <string>
#include <vector>
#include <time.h>
#include <iomanip>
bool ends_with(std::string const &a, std::string const &b) {
auto len = b.length();
auto pos = a.length() - len;
if (pos < 0)
return false;
auto pos_a = &a[pos];
auto pos_b = &b[0];
while (*pos_a)
if (*pos_a++ != *pos_b++)
return false;
return true;
}
bool ends_with_string(std::string const& str, std::string const& what) {
return what.size() <= str.size()
&& str.find(what, str.size() - what.size()) != str.npos;
}
bool has_suffix(const std::string &str, const std::string &suffix)
{
return str.size() >= suffix.size() &&
str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}
bool has_suffix2(const std::string &str, const std::string &suffix)
{
bool index = str.find(suffix, str.size() - suffix.size());
return (index != -1);
}
bool isEndsWith(const std::string& pstr, const std::string& substr)
{
int tlen = pstr.length();
int slen = substr.length();
if (slen > tlen)
return false;
const char* tdta = pstr.c_str();
const char* sdta = substr.c_str();
while (slen)
{
if (tdta[tlen] != sdta[slen])
return false;
--slen; --tlen;
}
return true;
}
bool ends_with_6502(const std::string& str, const std::string& end) {
size_t slen = str.size(), elen = end.size();
if (slen <= elen) return false;
while (elen) {
if (str[--slen] != end[--elen]) return false;
}
return true;
}
bool ends_with_rajenpandit(std::string const &file, std::string const &suffix) {
int pos = file.find(suffix);
return (pos != std::string::npos);
}
template <class F>
bool test(std::string const &label, F f) {
static const std::vector<std::pair<std::string, bool>> tests{
{ "this is some text", false },
{ "name.txt.other", false },
{ "name.txt", true }
};
bool result = true;
std::cout << "Testing: " << std::left << std::setw(20) << label;
for (auto const &s : tests)
result &= (f(s.first, ".txt") == s.second);
if (!result) {
std::cout << "Failed\n";
return false;
}
clock_t start = clock();
for (int i = 0; i < 10000000; i++)
for (auto const &s : tests)
result &= (f(s.first, ".txt") == s.second);
clock_t stop = clock();
std::cout << double(stop - start) / CLOCKS_PER_SEC << " Seconds\n";
return result;
}
int main() {
test("Jerry Coffin", ends_with);
test("Dietrich Epp", has_suffix);
test("Dietmar", ends_with_string);
test("Roman", isEndsWith);
test("6502", ends_with_6502);
test("rajenpandit", ends_with_rajenpandit);
}
Results with gcc:
使用 gcc 的结果:
Testing: Jerry Coffin 3.416 Seconds
Testing: Dietrich Epp 3.461 Seconds
Testing: Dietmar 3.695 Seconds
Testing: Roman 3.333 Seconds
Testing: 6502 3.304 Seconds
Testing: rajenpandit Failed
Results with VC++:
VC++ 的结果:
Testing: Jerry Coffin 0.718 Seconds
Testing: Dietrich Epp 0.982 Seconds
Testing: Dietmar 1.087 Seconds
Testing: Roman 0.883 Seconds
Testing: 6502 0.927 Seconds
Testing: rajenpandit Failed
Yes, those were run on identical hardware, and yes I ran them a number of times, and tried different optimization options with g++ to see if I could get it to at least come sort of close to matching VC++. I couldn't. I don't have an immediate explanation of why g++ produces so much worse code for this test, but I'm fairly confident that it does.
是的,它们运行在相同的硬件上,是的,我运行了它们很多次,并尝试使用 g++ 尝试不同的优化选项,看看我是否可以让它至少接近匹配 VC++。我不能。我没有立即解释为什么 g++ 会为这个测试产生如此糟糕的代码,但我相当有信心。
回答by Erbureth says Reinstate Monica
if (filename.substr(std::max(4, filename.size())-4) == std::string(".txt")) {
// Your code here
}
回答by Caesar
bool has_suffix(const std::string &str, const std::string &suffix)
{
std::size_t index = str.find(suffix, str.size() - suffix.size());
return (index != std::string::npos);
}
回答by T-D
you can just use another string to verify the extension like this :
您可以使用另一个字符串来验证扩展名,如下所示:
string fileName;
cout << "Enter filename: \n";
cin >> fileName;
//string txt = fileName.Right(4);
string ext="";
for(int i = fileName.length()-1;i>fileName.length()-5;i--)
{
ext += fileName[i];
}
cout<<ext;
if(ext != "txt.")
cout<<"error\n";
checking if equals "txt."
cause i starts with the length of the filename so ext
is filled in the opposite way
检查是否等于,"txt."
因为我以文件名的长度开始,所以ext
以相反的方式填充
回答by Dietmar Kühl
The easiest approach is probably to verify that the string is long enough to hold ".txt"
at all and to see if the string can be found at the position size() - 4
, e.g.:
最简单的方法可能是验证字符串是否足够长以容纳".txt"
并查看是否可以在位置找到字符串size() - 4
,例如:
bool ends_with_string(std::string const& str, std::string const& what) {
return what.size() <= str.size()
&& str.find(what, str.size() - what.size()) != str.npos;
}
回答by NoSenseEtAl
2 options I can think of beside mentioned ones:
1) regex - prob overkill for this, but simple regexes are nice and readable IMHO
2) rbegin - kind of nice, could be I am missing something, but here it is:
除了提到的选项之外,我还能想到 2 个选项:
1) 正则表达式 - 对此
可能有点矫枉过正,但简单的正则表达式很好且可读,恕我直言2) rbegin - 不错,可能是我遗漏了一些东西,但它是:
bool ends_with(const string& s, const string& ending)
{
return (s.size()>=ending.size()) && equal(ending.rbegin(), ending.rend(), s.rbegin());
}
回答by 6502
This is something that, unfortunately enough, is not present in the standard library and it's also somewhat annoying to write. This is my attempt:
不幸的是,这是标准库中不存在的东西,而且编写起来也有些烦人。这是我的尝试:
bool ends_with(const std::string& str, const std::string& end) {
size_t slen = str.size(), elen = end.size();
if (slen < elen) return false;
while (elen) {
if (str[--slen] != end[--elen]) return false;
}
return true;
}
回答by kert
This should do it.
这应该这样做。
bool ends_with(const std::string & s, const std::string & suffix) {
return s.rfind(suffix) == s.length() - suffix.length();
}