我正在学习基本的C ++,现在我从用户那里得到了一个字符串,我想检查他们是否输入了整个文件名(包括.txt)。我有字符串,但如何检查字符串是否以" .txt"结尾? ?
string fileName;
cout << "Enter filename: \n";
cin >> fileName;
string txt = fileName.Right(4);
Right(int)
方法仅适用于CString,因此上述代码不起作用。如果可能的话,我想使用常规字符串。有什么想法吗?
答案 0 :(得分:37)
不幸的是,这个有用的功能不在标准库中。这很容易写。
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;
}
答案 1 :(得分:11)
使用提升ends_with谓词:
#include <boost/algorithm/string/predicate.hpp>
if (boost::ends_with(fileName, ".txt")) { /* ... */ }
答案 2 :(得分:11)
你已经得到了不少答案,但我决定添加另一个答案:
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;
}
由于你得到了不少答案,或许快速测试和结果总结是值得的:
#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);
}
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
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
是的,那些是在相同的硬件上运行的,是的,我运行了很多次,并尝试使用g ++进行不同的优化选项,看看我是否能够得到它至少接近匹配VC ++。我不能。我没有立即解释为什么g ++为这个测试产生了更糟糕的代码,但我相信它确实如此。
答案 3 :(得分:6)
if (filename.substr(std::max(4, filename.size())-4) == std::string(".txt")) {
// Your code here
}
答案 4 :(得分:3)
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);
}
答案 5 :(得分:3)
您可以使用另一个字符串来验证扩展名,如下所示:
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";
检查是否等于"txt."
因为我从文件名的长度开始,所以ext
以相反的方式填充
答案 6 :(得分:2)
最简单的方法可能是验证字符串足够长以容纳".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;
}
答案 7 :(得分:2)
遗憾的是,这在标准库中并不存在,而且写入也有点烦人。这是我的尝试:
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;
}
答案 8 :(得分: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());
}
答案 9 :(得分:1)
从 C++17 开始,您可以使用 path 中的 filesystem library 类。
#include <filesystem>
bool ends_with_txt(const std::string& fileName) {
return std::filesystem::path{fileName}.extension() == ".txt";
}
答案 10 :(得分:0)
这是“完全自编”的解决方案:
bool isEndsWith(const std::string& pstr, const std::string& substr) const
{
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;
}
答案 11 :(得分:0)
这应该做到。
bool ends_with(const std::string & s, const std::string & suffix) {
return s.rfind(suffix) == s.length() - suffix.length();
}