0

I tried making a little program that checks if a string is a substring of another. I think got the logic down correctly, but i encountered a problem concerning data types. I declared 2 strings and gave them a value instantly and they worked fine, but the other one, the checker variable, works in a weird way. It can not be printed out like a regular string using cout but it only prints the first letter. And functions like .length() do not work on it, the error says

|error: request for member 'length' in 'checker', which is of non-class type 'std::__cxx11::string

Code:

#include <iostream> #include <string.h> #include <string> using namespace std; int main() { string text = "abcde"; string subtext = "bcde"; //string specialChars = "\\*"; string checker[subtext.length()]; int counter = 0; for(int i = 0; i < 5; i++){ if (subtext[counter] == text[i]){ checker[counter] = text[i]; counter++; } } cout << text << " " << checker.length() << endl; for (int i = 0; i < 4; i++){ cout << checker[i]; } return 0; } 

Bonus question ^_^: Is the logic behind the program good enough, or is there a more efficient way of solving it.

thanks a lot.

2
  • Tip: using namespace std; is a bad habit to get into and if you can stop now you might avoid a whole lot of headaches in the future. The std:: prefix is there for a reason: It avoids conflict with your own classes, structures and variables especially when you’re importing a lot of header files which may define a lot more things than they superficially appear to. Commented Oct 27, 2020 at 18:51
  • 1
    Note that variable-length arrays are not part of standard C++. Please try to avoid it in favor of std::vector (which will as noted in an answer also solve your problem). Commented Oct 27, 2020 at 19:17

2 Answers 2

1
string checker[subtext.length()]; 

is an array of subtext.length() empty std::strings. Not what you want to have if you indeed want a string of the shared character. Which you don't. More on that after the post-mortem.

string checker(subtext.length(), ' '); 

Will give you a single std::string of the requested length using spaces as place-holder characters. This is also the wrong thing to do because now you have to deal with left-over unused spaces still containing spaces.

What you need in order to correct the code you currently have is a single empty std::string and a change to the loop that builds it.

#include <iostream> #include <string> int main() { std::string text = "abcde"; std::string subtext = "bcde"; std::string checker; int counter = 0; for(std::string::size_type i = 0; // unlikely to happen, but int may not be // big enough. size_type is guaranteed i < text.length(); // avoid magic numbers. Use the length of the string i++){ if (subtext[counter] == text[i]){ checker.push_back(text[i]); //add to checker counter++; } } std::cout << text << " " << checker.length() << std::endl << checker << std::endl; return 0; } 

That's it for the post-mortem. The code works as I believe the asker intends. Unfortunately it doesn't detect substrings. For a string to be a substring not only do all of the letters have to match and be in the same order, they also need to be contiguous. The way it is built, checker can't guarantee this.

The easiest way to find a substring is

#include <iostream> #include <string> int main() { std::string text = "abcde"; std::string subtext = "bcde"; if (text.find(subtext) != std::string::npos) { std::cout << "We Got One!"; } return 0; } 

find looks for the exact subtext inside text and returns the location of subtext inside text. If subtext is not found, find returns an impossible index, npos.

If you have to search the hard way, as in the assignment won't all of you to call a library function to do the dirty work, there are many approaches with Knuth-Morris-Pratt being relatively easy to implement, pretty darn efficient, and extremely well documented.

Sign up to request clarification or add additional context in comments.

Comments

1

checker is not a std::string, it's an array of std::string, and as a primitive type, does not have a .length() function.1

If you want that, you'll need to use this instead:

std::vector<std::string> checker; 

Where then you can add as many as you see fit:

checker.push_back(text[i]); 

And later:

cout << text << " " << checker.size() << endl; 

1 Not everything in the C++ Standard Library has a length() function anyway, it's conventionally called size(). std::string just has an alias, but it's an exception.

13 Comments

My suspicion is the asker really wants string checker(' ', subtext.length()); and this is just a typo (and errors descending from the typo while trying to make the code compile).
@user4581301 A very good point. Worth adding as a separate answer?
I was commenting and about to close as typo when I saw your answer pop up and decided to stop and wait for more input.
If you're learning C++ and don't know that yet, time to get a reference which covers templates. They're extremely important to know, and if you don't, then 90% of the Standard Library will be off-limits and useless, which is a huge impediment. A template is a C++ "generic" of sorts. C++ is not something you can intuit your way through, so a good reference book is absolutely critical to understanding it.
In C++ X y[n] creates a C array of type X with n entries. That [n] part doesn't even hit the constructor, it means create n of. You want X y(...) where the ... part is passed to the constructor.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.