• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 423
  • Last Modified:

Find last occurrence of any valid character in a string C++

I have a C++ project and I read a line from a file, I'm using fgets but I can use anything. With that line I would like to find the last position, in the string, that contains a valid character or number, i.e. 0-9 or a-Z. I don't really what to create a string that holds all the numbers and characters to use as a compare I would like the most eligant was to find the last vaild character/number in the string so I can extract a variable size word from the string.
Thanks
0
atomicgs12
Asked:
atomicgs12
  • 6
  • 4
  • 2
  • +1
1 Solution
 
phoffricCommented:
Without converting your char * to a string you could use strpbrk:
     http://www.cplusplus.com/reference/clibrary/cstring/strpbrk/
In their example, you would just keep track of the last non-NULL pointer which represents the last occurrence of "0123456789abc...xyzABC...XYZ"

You could also use strcspn repetively in a similar way.
    http://www.cplusplus.com/reference/clibrary/cstring/strcspn/

If you convert your char * to a C++ string, then you can use string::find_last_of without having to form your own loop, since it searches for your chars starting at the end of the string.
    http://www.cplusplus.com/reference/string/string/find_last_of/
0
 
Todd GerbertIT ConsultantCommented:
::isalnum in combination with phoffric's comment above would probably be the way to go.
0
 
phoffricCommented:
Since the comparison string is user defined, and only alphanumerics are included, then there should be no need to further test for alphanumerics.

However, you can write your own loop searching from the end of the string testing for alphanumerics using isalnum and not using the functions in the first post.
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

 
atomicgs12Author Commented:
Doesn't all these examples mean I have to create a comparison string of "0-9, a-z, A-Z", which is what I did NOT want to do?
Thanks
0
 
Todd GerbertIT ConsultantCommented:
OP stated I don't really what to create a string that holds all the numbers and characters to use as a compare, and unless I'm misunderstanding something strpbrk, strcspn, strtok, etc all require a string to hold all the numbers and characters against which to compare, which is why I suggested isalnum - maybe I'm being too literal. ;)

string test("one two three---");

string::iterator it = find_if(test.rbegin(), test.rend(), isalnum).base();
	
int indexOfLastAlphaNumeric = it - test.begin() - 1;

Open in new window

0
 
phoffricCommented:
Using isalnum is likely to be a performance improvement over the other mentioned functions since it doesn't necessarily have to compare each char in your string against the 26*2+10 valid chars. Instead depending upon the locale, it will do just a few tests. If ASCII chars, it would be
( 'a' <= ch && ch <= 'z')  || ( 'A' <= ch && ch <= 'Z') for the alphas, and similar for the digits.
0
 
phoffricCommented:
>> which is what I did NOT want to do?
I misunderstood the OP.
0
 
Todd GerbertIT ConsultantCommented:
I guess you don't necessarily need to know the index of the last non-alpha-numeric, if, for example, you just want the last word in a given string:

http://www.cplusplus.com/reference/algorithm/find_if/
http://www.cplusplus.com/reference/std/functional/not1/
http://www.cplusplus.com/reference/string/string/

Enter a string: one---two---three---
The last word in the line is: three

Open in new window


#include <iostream>
#include <string>
#include <algorithm>
#include <functional>

using namespace std;

void GetLastWord(string &source, string &dest)
{
	string::reverse_iterator end = find_if(source.rbegin(), source.rend(), ::isalnum);
	string::iterator start = find_if(end, source.rend(), not1(ptr_fun(isalnum))).base();

	dest = string(start, end.base());
}

int main(int argc, char *argv[])
{
	string input, lastWord;

	cout << "Enter a string: ";
	getline(cin, input);
	
	GetLastWord(input, lastWord);

	cout << "The last word in the line is: " << lastWord << endl;

	cin.get();
}

Open in new window

0
 
HooKooDooKuCommented:
While perhaps not the most elegant solution, I would think the most strait forward solution would be to use strlen to find the end of the string, position a char* to point to that last char of the string, then use the logic like what phoffric shows two posts up to determine if what char* points to is a valid charactor or not.  If the character is invalid (i.e. not a-z, A-Z, or 0-9) then back the char* up one time until a valid character is reached (or the start of the string is reached).

char Read[100];
char* pLast;
fgets( Read );
pLast = Read + strlen( Read );
while( pLast > Read )
{
    char ch = *pLast;
    if( 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || '0' <= ch && ch <= '9')
        break;
    pLast--;
}
if( pLast == Read )
    pLast = NULL;  //Flags that there were no valid characters in the string
0
 
phoffricCommented:
why not just use isalnum(ch) instead of the if statement (which assumes ASCII chars)? You could just use:
    if( isalnum(ch) )
          break;
0
 
phoffricCommented:
>> Doesn't all these examples mean I have to create a comparison string of "0-9, a-z, A-Z", which is what I did NOT want to do?
To which I replied, "I misunderstood the OP."
So, I think you may have accepted my answer which is not what you wanted.
0
 
atomicgs12Author Commented:
Actually I should have divided it up, I ended up using your hint of find_last_of and tgerbert's std::string .begin, .end
0
 
Todd GerbertIT ConsultantCommented:
I'm not concerned about the points, so long as the correct answer is selected so someone  else reading this thread in the future might find it useful, and that appears to be the case so I say leave it as-is.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

  • 6
  • 4
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now