Finding a substring within a string - c++

In C++ I have a phonebook with many names, such as Sinatra, Frank, and I want the user to be able to input any length of string to scan the file for it. Once I have the user input a string of any desired length, how do I scan an entire string of "Sinatra, Frank" for just "Frank" or "Sinatra" or "atra" and see which name(s) it belongs to?

You can use the std::string::find method:
string s = "Sinatra, Frank";
string::sizetype index = s.find("Frank");
This gets you the index of the match (which in this case is 9).

A question: is your phonebook a flat file with each name on a new line (as in your example with "Sinatra, Frank" in a format like "Lastname, Firstname", etc.), or do you have some structure of this phonebook where each name-string is a node of an array, a linked list, etc?
Note that for strstr():
strstr(const char *s1, const char *s2)
locates the first occurrence of string s2 in s1, which may be sufficient for you.
For your input string, always be sure to check size limits in one way or another; if the user enters a string through some interface it should be explicitly handled to ensure it doesn't exceed your storage for it or contain malevolent characters or code.
Ken's solution produces the position of the substring in the original string (and so long as it's not null that mean's there's a 'hit') but doesn't tell you which entry of the phonebook is the hit; your code will need to track which entry/entries are hits so you can return a meaningful set of results.

You can use strstr() to locate one substring within a string.

If it's a std::string, you can use the .find() method of the "Sinatra,Frank" string

Related

It is possible to pass a reference in a regex quantifier in Java?

I had a programming exercise where we had to write a format method that would take as parameters a String, as the text input we want to format, and an integer, as the length of the lines we want.
We also had specific rules, and one of them was: if a word is longer than the desired length, it should go on a line by itself.
So an easy way to do this was to search with a Regex expression a series of non-white space characters being at least length and possibly more, and to replace this matched by itself with two \n at each side...
perhaps the code is clearer: let's imagine our desired line length is 10
String s = line.replaceAll("([ \t])(\\S{10,})([ \t])", "\n$2\n");
System.out.println(s);
This actually works fine.
My problem is that the line length should be passed as a parameter to the format method; so the only way I can refer to this parameter is by using its reference. For example:
public static String format(String s, int length) { ...
//missing stuff
String s = line.replaceAll("([ \t])(\S{length,})([ \t])", "\n$2\n");
System.out.println(s);
However in that case it will return an error: PatternSyntaxException
My question is: is there any way to use a reference into a quantifier (instead of a number), as argument for the number of occurrences we want to match? As it seems it would be really useful, I was surprised that it didn't seem to work. Also it doesn't look like a lot of people encountered this issue.
try this
String s = line.replaceAll("([ \t])(\S{"+length+",})([ \t])", "\n$2\n");
System.out.println(s);

Input filtering using scanf

I want to filter input. I don't know what is the best way. I want words starting with alpha-bates to be read. For example, if the input is:
This is 1 EXAMPLE1 input.
The string should be like this:
This is EXAMPLE1 input
What is the easiest way to filter input like this?
I tried using "%[a-zA-Z]s", but it not working.
Your scan string "%[a-zA-Z]s" probably isn't want you think it is. Drop that trailing s.
"%[a-zA-Z]" will scan a string consisting entirely of lower and uppercase letters. So numbers will be discounted. However, you want to scan alpha-numeric strings that begin with a lower or uppercase letter. scanf doesn't provide a facility to look for a string in that way. You can, instead, scan for an alpha-numeric string with "%[a-zA-Z0-9]", and then drop the scanned input if it the first character of the string is numeric.
Using scanf is tricky for various reasons. The string may be longer than you expect, and cause buffer overflow. If the input isn't in the format you expect, then scanf may fail to advance past the unexpected input. It is usually more reliable to read the input into a buffer unconditionally, and parse the buffer. For example:
const char *wants
= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
std::string word;
while (std::cin >> word) {
if (!isalpha(word[0])) continue;
std::string::size_type p = word.find_first_not_of(wants);
word = word.substr(0, p);
//... do something with word
}

Need help on getting characters from a string?

I'm currently in an Intro C++ class, and I'm learning about Strings and Member Functions of them.
I have questions that are like this:
Assume that name is a variable of type string that has been assigned a value. Write an expression whose value is a string containing the first character of the value of name . So if the value of name were "Smith" the expression's value would be "S".
or
Assume that name is a variable of type string that has been assigned a value. Write an expression whose value is a string containing the last character of the value of name . So if the value of name were "Smith" the expression's value would be "h".
or
Assume that word is a variable of type string that has been assigned a value. Write an expression whose value is a string consisting of the last three characters of the value of word . So if the value of word were "biggest" the expression's value would be "est".
I know things like name[0] and name[name.length() - 1], but I don't know how to turn those into a string in one expression. I've been looking for a table or list of member functions that can help me do this, but I'm stuck. Any directions or aid would be great. :D
Take a look at the substr method.
http://www.cplusplus.com/reference/string/string/substr/
I would use substring:
//assume that the string in question is held in a variable with the name str
string s1 = str.substr(0,1);
string s2 = str.substr(str.length() - 2, 1);
string s3 = str.substr(str.length() = 4, 3);
Hopefully that helps!
There are quite a few number of ways to do it. For instance, an std::string is also a standard container of char. So you could begin with an empty string, and append one char to it.

How to order a string[] in c++

The input is string[] like below.
"CSE111: CSE110 MATH101"
"CSE110:"
I need to order the strings based on some logic. For example my output should be a string[] like
"CSE110","MATH122","CSE111"
My question is
While scanning through the input array, if one string is picked to be the first string of the output array, then how do I skip all occurrences of that particular string, while I continue to process the string[] for the second output string etc..
Eg:
Input:
"CSE111: CSE110 MATH101"
"CSE110:"
If CSE110 is picked to be the first string in the output, then when I scan through the input string[] for the second string to be a part of output, I should not consider CSE110.
How can I achieve this? The answer I am looking forward to is something like:
Store the input in a string[]
loop through the strings one by one using strtok or stringstream >> operator.
Once the first string is found ...blah blah blah ....
Hope my question is clear enough. I will be glad to provide more details.
Edit1:More Explanation
The strings represent the order in which the classes need to taken . If a class has pre-requisite , the pre-requisite has to be taken first. ie. if Input is
"CSE111: CSE110 MATH101"
"CSE110:"
The class CSE111 has a pre-requisite of CSE110 MATH101 . So I need to consider first CSE1110(No Pre-requisite) - MATH101((No Pre-requisite) and then CSE111 . (Further Ties can broken in alphabetical order. )
I hope this helps..
I hopefully got it now: For a string of the form A: B C D, the course A has B, C, and D as prerequisites.
In that case you want a mapping from a course to its prerequisites, e.g.:
typedef std::set<std::string> CourseSet;
typedef std::map<std::string, CourseSet> Prerequisites;
Now you can fill a Prerequisites by tokenizing, using the first part as the key and a CourseSet as the value.
As it seems that you just want one of the possible orders for all courses in the input, you could then do the following:
complete the prerequisites for the courses (i.e. include the courses they indirectly depend on)
now a>b if a has b as a prerequisite
if b doesn't have a as a prerequisite use e.g. the lexicographical order

How to replace a string between two substrings in a string in VC++/MFC?

Say I have a CString object strMain="AAAABBCCCCCCDDBBCCCCCCDDDAA";
I also have two smaller strings, say strSmall1="BB";
strSmall2="DD";
Now, I want to replace all occurence of strings which occur between strSmall1("BB") and strSmall2("DD") in strMain, with say "KKKKKKK"
Is there a way to do it without Regex. I cannot use regex as adding another file to the project is prohibited.
Is there a way in VC++/MFC to do it? Or any easy algorithm you can point me to?
int length = strMain.GetLength();
int begin = strMain.Find(strSmall1, 0) + strSmall1.GetLength();
int end = strMain.Find(strSmall2, 0);
CStringT left = strMain.Left(begin);
CStringT right = strMain.Right(length - end);
strMain = left + "KKKKKKK" + right
The easiest way is probably to handle the replacement recursively. Search for the starting delimiter and the ending delimiter. If you find them, put together a new string consisting of the string up to the starting delimiter, followed by the replacement string, followed by the return from recursively doing the replacement in the remainder of the string following the ending delimiter.
That, of course, assumes you want to replace all the occurrences in the main string -- if you only want to replace the first one, John Weldon's solution (for one example) will work quite nicely.
psudocode:
loop over string
if curlocation matches string strsmall1 save index break
loop over remaining string
replace till curlocation matches string strsmall2
Extra credit:
What will the next assignment be?
My answer:
Speed it up by jumping the length of strsmall1 and strsmall2 in loop iterations