Reputation: 825
I have a rudimentary program I'm trying to implement that asks for a URL of a .pdf file and then downloads it and shows it through Xming. First, I want to check to make sure the user actually put in a URL with 'http://' at the front and 'pdf' or 'PDF' at the end. I suppose this might be a typical problem from someone coming from Python, but how do I check end of the string the user inputs. Using the method below (which I used with my Python-oriented-brain) I get a
Range error: -3
So how do ACTUAL C++ programmers accomplish this task? Please and thank you.
if (file[0]=='h' && file[1]=='t' && file[2]=='t' && file[3]=='p' && file[4]==':'
&& file[5]=='/' && file[6]=='/' && (file[-3]=='p' || file[-3]=='P')
&& (file[-2]=='d' || file[-2]=='D') && (file[-1]=='f' || file[-1]=='F'))
Upvotes: 0
Views: 1766
Reputation: 179917
There are probably quite a few C++ programmers who have a bool endsWith(std::string const& input, std::string const& suffix)
function in their toolkit.
It's easy to write this in a non-performing way. Calling substr
is a common cause of this. A regex is even less performant. Here's one implementation that avoids temporaries and copies:
bool endsWith(std::string const& input, std::string const& suffix)
{
if (input.size() < suffix.size()) return false; // "a" cannot end in "aa"
return std::equal(begin(suffix), end(suffix), end(input)-suffix.size());
}
Upvotes: 1
Reputation: 818
There's a bunch of different ways using various string methods. If you really cared about performance you could benchmark the various ways. Here's an example with find & substr.
#include <algorithm>
#include <string>
std::string file = "http://something.pdf";
std::transform(file.begin(), file.end(), file.begin(), ::tolower); // lowercase the data, see http://stackoverflow.com/questions/313970/stl-string-to-lower-case
if (file.find("http://") == 0 && (file.substr(file.length() - 3) == "pdf")) {
// valid
}
Upvotes: 0
Reputation:
Or you can use regex:
#import <regex>
using namespace std;
...
std::string str = "http://www.example.com/myFile.PDF";
std::regex rx("http(s)?:(www\.)?.+/[pP][dD][fF]");
return regex_match(str.begin(), str.end(), rx)
..
Where:
"http(s)?
- matches http or https
(www\.)?
- matches a single or 0 apparitions of www. such as 'www.example.com' or 'example.com'
.+/
- matches any character
/[pP][dD][fF]
- the end of url can by any combination of small and capital letters that form whe word 'pdf'
You can check out more here and here
Upvotes: 0
Reputation: 893
In C++ you cant access negative indizies. You would have to manually calculate the position of the laste element:
int s = file.size();
(file[s-3]=='p' || file[s-3]=='P')
&& (file[s-2]=='d' || file[s-2]=='D')
&& (file[s-1]=='f' || file[s-1]=='F')
I'm assuming that file is a C++ - string, if its not you have to use a other way to get the length
You could also simplify your code by using build in string-functions:
int s = file.size();
if (s > 10 && file.find("http://") == 0 && file.substr(s-3, 3) == "PDF") //...
Or just use Regex like another comment suggested (probably the nicest way)
Upvotes: 2