UnworthyToast
UnworthyToast

Reputation: 825

How do I check the end of a string in C++?

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

Answers (5)

MSalters
MSalters

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

Avi Tevet
Avi Tevet

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

user1817574
user1817574

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

Mikescher
Mikescher

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

TNA
TNA

Reputation: 2745

Another solution is to use Regex.

regex url("http//\w*pdf",icase);

Upvotes: 0

Related Questions