check if WCHAR contains string - c++

I have variable WCHAR sDisplayName[1024];
How can I check if sDisplayName contains the string "example"?

if(wcscmp(sDisplayName, L"example") == 0)
; //then it contains "example"
else
; //it does not
This does not cover the case where the string in sDisplayName starts with "example" or has "example" in the middle. For those cases, you can use wcsncmp and wcsstr.
Also this check is case sensitive.
Also this will break if sDisplayName contains garbage - i. e. is not null terminated.
Consider using std::wstring instead. That's the C++ way.
EDIT: if you want to match the beginning of the string:
if(wcsncmp(sDisplayName, L"Adobe", 5) == 0)
//Starts with "Adobe"
If you want to find the string in the middle
if(wcsstr(sDisplayName, L"Adobe") != 0)
//Contains "Adobe"
Note that wcsstr returns nonzero if the string is found, unlike the rest.

You can use the wchar_t variants of standard C functions (i.e., wcsstr).

wscstr will find your string anywhere in sDisplayName, wsccmp will see if sDisplayName is exactly your string.

Related

MFC newbie: how to determine if a character is hexadecimal using "FindOneOf()"

I'm new at MFC and I need to do something which sounds extremely simple: determining if a string only contains hexadecimal characters.
For that, I browse through the string (it's a CString) and I verify all characters using the FindOneOf() method, as follows:
int iTest = CString(pszText[i]).FindOneOf((LPCWSTR)"0123456789ABCDEFabcdef");
For some bizarre reason, I always get -1 as a result.
What am I doing wrong?
P.s.1 I prefer not to use the SpanIncluding() method, I find the FindOneOf() quite readable but I don't know how to use it.
P.s.2 Also simple STL seems not to be working: I tried to work with std::isxdigit(pszText[i]) but in order to get this to work, I need to include <locale> and then this function is asking for a second parameter, next to the character I want to check, and a null-pointer is not allowed there (std::isxdigit(pszText[i], nullptr) does not work).
There are several problems in your code:
This is wrong:
int iTest = CString(pszText[i]).FindOneOf(LPCWSTR)"0123456789ABCDEFabcdef");
It should be:
int iTest = CString(pszText[i]).FindOneOf(L"0123456789ABCDEFabcdef");
The cast will simply make the compiler believe that "0123..." is a wide string but it isn't. You need to use the L prefix to indicate that the string is a wide string.
But even then your algorithm won't work because FindOneOf will simply find the first occurrence of any of the characters in the parameter.
Example:
int iTest = CString(L"Z223Zbc").FindOneOf(L"0123456789ABCDEFabcdef");
"Z223Zbc" is obviously not a hexadecimal string, but iTest will contain 1 because the first character of "Z223Zbc" being part of "0123456789ABCDEFabcdef" is '2' and that's at position 1.
iTest will only contain -1 if the string to be tested doesn't contain any hexadecimal characters as for example "xyz".
Therefore this solution is appropriate:
#include <cwctype>
...
WCHAR string[] = L"123abcX";
bool ishexstring = true; // assume the string is a hex string
for (int i = 0; ; i++)
{
WCHAR c = string[i];
if (c == 0)
break; // end of string => we exit the looop
if (!std::iswxdigit(c))
{
ishexstring = false; // c is no hex digit
break; // exit loop
}
}
This algorithm should be put into a function, but I'm leaving this as an exercise for the reader.
Solution using SpanIncluding (less efficient because we need tot construct a temporary CString):
bool ishexstring = CString(string).SpanIncluding(L"0123456789ABCDEFabcdef") == str;

C++ check if string is beginning of an english word

I've found a couple answers for how to check if a string is a full word, but nothing for how to check if a string is the first part of a word.
For example, I need a function that will return true for "c", "b", "cong" (congratulations, congruent, etc.), or "exa" (example, examine, etc.), but false for "congx", "qt", or other gibberish.
I'd imagine there are a number of ways to go about this. If you could provide a rough outline for a strategy, I would really appreciate it.
I'm trying to make a Boggle solver.
Thanks!
Is std::string part contained in std::string word?
if(word.find(part) != std::string::npos)
{
// part is in word somethere
}
Is std::string part at the beginning of std::string word?
if(word.find(part) == 0)
{
// word starts with part
}
By way of explanation, std::string::find() returns the position of what was found. So 0 means it was found at the beginning. The value std::string::npos is a special value that indicates nothing was found at all.

How do I remove only the first character of a string that is not a digit? (MFC, C++)

I want to remove only the first character in a string that is NOT a digit. The first character can be anything from ‘A’ to ‘Z’ or it may be a special character like ‘&’ or ‘#’. This legacy code is written in MFC. I've looked at the CString class but cannot figure out how to make this work.
I have strings that may look like any of the following:
J22008943452GF or 22008943452GF or K33423333333IF or 23000526987IF or #12000895236GF. You get the idea by now.
My dilemma is I need to remove the character in the first position of all the strings, but not the strings that starts with a digit. For the strings that begin with a digit, I need to leave them alone. Also, none of the other characters in the string should not be altered. For example the ‘G’, ‘I’ or ‘F’ in the later part of the string should not be changed. The length of the string will always be 13 or 14 digits.
Here is what I have so far.
CString GAbsMeterCalibration::TrimMeterSNString (CString meterSN)
{
meterSN.MakeUpper();
CString TrimmedMeterSNString = meterSN;
int strlength = strlen(TrimmedMeterSNString);
if (strlength == 13)
{
// Check the first character anyway, even though it’s
// probably okay. If it is a digit, life’s good.
// Return unaltered TrimmedMeterSNString;
}
if (strlength == 14))
{
//Check the first character, it’s probably going
// to be wrong and is a character, not a digit.
// if I find a char in the first postion of the
// string, delete it and shift everything to the
// left. Make this my new TrimmedMeterSNString
// return altered TrimmedMeterSNString;
}
}
The string lengths are checked and validated before the calls.
From my investigations, I’ve found that MFC does not have a regular expression
class. Nor does it have the substring methods.
How about:
CString GAbsMeterCalibration::TrimMeterSNString (CString meterSN)
{
meterSN.MakeUpper();
CString TrimmedMeterSNString = meterSN;
int strlength = strlen(TrimmedMeterSNString);
if (std::isdigit(TrimmedMeterSNString.GetAt(0)) )
{
// Check the first character anyway, even though it’s
// probably okay. If it is a digit, life’s good.
// Return unaltered TrimmedMeterSNString;
}
}
From what I understand, you want to remove the first letter if it is not a digit. So you may make this function simpler:
CString GAbsMeterCalibration::TrimMeterSNString(CString meterSN)
{
meterSN.MakeUpper();
int length = meterSN.GetLength();
// just check the first character is always a digit else remove it
if (length > 0 && unsigned(meterSN[0] - TCHAR('0')) > unsigned('9'))
{
return meterSN.Right(length - 1);
}
return meterSN;
}
I am not using function isdigit instead of the conditional trick with unsigned because CString uses TCHAR which can be either char or wchar_t.
The solution is fairly straight forward:
CString GAbsMeterCalibration::TrimMeterSNString(CString meterSN) {
meterSN.MakeUpper();
return _istdigit(meterSN.GetAt(0)) ? meterSN :
meterSN.Mid(1);
}
The implementation can be compiled for both ANSI and Unicode project settings by using _istdigit. This is required since you are using CString, which stores either MBCS or Unicode character strings. The desired substring is extracted using CStringT::Mid.
(Note that CString is a typedef for a specific CStringT template instantiation, depending on your project settings.)
CString test="12355adaddfca";
if((test.GetAt(0)>=48)&&(test.GetAt(0)<=57))
{
//48 and 57 are ascii values of 0&9, hence this is a digit
//do your stuff
//CString::GetBuffer may help here??
}
else
{
//it is not a digit, do your stuff
}
Compare the ascii value of the first position in the string and you know if it's a digit or not..
I don't know if you've tried this, but, it should work.
CString str = _T("#12000895236GF");
// check string to see if it starts with digit.
CString result = str.SpanIncluding(_T("0123456789"));
// if result is empty, string does not start with a number
// and we can remove the first character. Otherwise, string
// remains intact.
if (result.IsEmpty())
str = str.Mid(1);
Seems a little easier than what's been proposed.

How do I return the end of a directory

I have a function that is supposed to find the last bit of a directory in a string. eg:
"C:\Lolcats\pie\ambulance\" should return "ambulance". However it returns some strange characters ive never seen, like the male arrow-point symbol and some other weird stuff.
string App::getlastName(string cakes){
//finds the name of the last folder in a directory
string name;
string temp;//popback all of temp into name to invert it
cakes.pop_back();
char i = cakes[cakes.length()-1];
while (i != '\\'){
temp.push_back(cakes[i]);
cakes.pop_back();
i = cakes[cakes.length()-1];
} //-1?
for (int j = 0; j<temp.length(); ++j){
name.push_back(temp.back());
temp.pop_back();
}
return name;
}
This is probably one of the worst functions i've ever written, but I can't think of how else to wrangle the end off :( Can someone help me please? :D
Note that the function doesnt need to find the name of a file, it'll just be folders.
Two steps:
if it ends with a backslash character remove it:
if (!cakes.empty() && '\\' == *(cakes.end() - 1))
{
cakes.erase(cakes.end() - 1);
}
use std::string::find_last_of() to locate last backslash and std::string::substr() to extract the last part:
std::string last_part;
const size_t slash_idx = cakes.find_last_of("\\");
if (std::string::npos != slash_idx)
{
last_part = cakes.substr(slash_idx + 1);
}
If it is possible that the directory name could contain forward slashes add the additional check for the last character and just add it to the argument to find_last_of("\\/"), as it can search for more than one character.
If you remove the trailing \ off the string you can use a simple combination of rfind and substr to get the data you want.
string substring = cakes.substr(cakes.rfind("\\") + 1);
#Joel Rondeau's comment where he says that the line temp.push_back(cakes[i]) is a problem is correct, but I thought I would elaborate.
The reason is that the variable i is defined as a char not an int, but it is possible for the two to be cast implicitly. So the reason why you are getting strange characters returned is because casting a char to an int has resulted in an index value that probably does not exist in your string.
Reading your code sample it looks like you should be doing temp.push_back(cakes[cakes.length()-1]) instead (or better, store this index in a temp variable so you don't have to keep writing it every time).
Your method depends on the string already being in the correct format with no assertions or error checking--not a good idea.
I would just do something like:
char* directoryName = strrchr(fullPath, '\\') + 1;
after you have trimmed off the trailing '\'.

C++: how to judge if the path of the file start with a given path

I have a path, for example, named
/my/path/test/mytestpath
, and I want to judge if it start with a given path, for example
/my/path
The C++17 filesystem library is probably the most robust solution. If C++17 is not available to you, Boost.Filesystem provides an implementation for earlier C++ versions. Try something like:
bool isSubDir(path p, path root)
{
while(p != path()) {
if(p == root) {
return true;
}
p = p.parent_path();
}
return false;
}
Substring the length of the string ( /my/path ) of the original (/my/path/test/mytestpath ) from the beginning.
Check whether two strings are equal.
You can do a string compare of the number of characters in the shorter string.
The fact that the characters match of itself won't mean it is a sub-path because you need to check that the next character in the longer string is a '/'
In C you can use strncmp() which takes a length of characters.
In C++ you can use the same or string compare functions. The find() function will work for this but remember to also check that the next character in the main path is a directory separator.
You could "tokenize" your path but that is likely to not be worth it.
std::string::find() returns the index at which a string was found, with an index of 0 being the start of the string:
std::string path("/my/path/test/mytestpath");
// This will check if 'path' begins with "/my/path/".
//
if (0 == path.find("/my/path/"))
{
// 'path' starts with "/my/path".
}