Find all substring in a given string c++ - c++

I've got a problem with a program which finds all substring in a given string.
I've tried to make variable "found", which would contain a position of a previously found substring and then start searching from the position.
Here's my code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
string str1;
cin >> str >> str1;
int i = 0;
int found = -1;
while(found < str1.size()){
found = str1.find(str, found + 1);
cout<<str1.find(str, found)<<endl;
i++;
}
}
for the following input: "ab
aabb"
it doesn't print anything.
Could you help?

So a little bit of theory first:
substr(a,b) -> returns cut out of the string from position a to position b
find(a) -> returns the position of found character or set of characters 'a'. returns -1 if NOT found.
Let's examine your code:
#include <iostream>
#include <string> //not really needed here. string should already be usable
using namespace std; //in small programs is ok but with big programs this could lead to problems with using specific things that could have the same names in std and other library. So its best to avoid this and or any other using namespace you use.
int main()
{
string str; // you should really name your variables better
string str1;
cin >> str >> str1; // your variable names are unreadable at first glance
int i = 0; // iterator cool but why is it needed if you're just using find()
int found = -1; // good variable although the name "pos" would probably be better as to further explain to the programmer what the variable does
while(found < str1.size()){ //not really sure what you were going for here
found = str1.find(str, found + 1); // this could have been your while logic above instead
cout<<str1.find(str, found)<<endl; // this finds the exact same position again using more resources. your variable found stores the position so doing cout << found << here would be better
i++;
}
}
Now let's see why your code doesn't show anything on console:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
string str1;
cin >> str >> str1; //you input ab as str and abbb as str1
int i = 0;
int found = -1;
while(found < str1.size()){ //first iteration is while(-1 < 4)
found = str1.find(str, found + 1); //<-- find needs just 1 parameter. heres your problem
cout<<str1.find(str, found)<<endl;
i++;
}
}
str1.find("ab); -> function find searches for "ab" in string str1. You don't need to add where it's meant to search for. Also the fact that your while loop is dependant on found < str1.size() and not anything to do with your iterator means your loop will go on forever. whenever this happens most IDE's crash your program giving you nothing cout'ed.
Fix:
#include <iostream>
using namespace std;
int main()
{
string str;
string str1;
int pos;
cin >> str >> str1;
for(int i = 0; i < str1.size(); i++) // this or could be while(true)
{
pos = str1.substr(i).find(str); //finds your string in the rest of the line
if (pos == -1)
{
//NOT FOUND
break; //stops
}
else
{
//FOUND
cout << pos + i << endl; //pos is position in the cut out after adding i we get global position
i += pos; // skip characters after we found them to NOT be found again
}
}
}

Another possible solution would be:
Walk the input string until the point you know the substring cannot fit anymore.
For each input string position, check if each substring starts with the substring (starts_with only since C++20).
[Demo]
#include <iostream>
#include <string>
int main() {
std::string str{ "ab aab" };
std::string sub{ "ab" };
int count{};
size_t last_index{ str.size() > sub.size() ? str.size() - sub.size() : 0 };
for (size_t i{0}; i <= last_index; ++i) {
if (str.substr(i).starts_with(sub)) {
count++;
}
}
std::cout << count;
}
// Outputs: 2

int find_substr(string substr, string str) {
int postion = 0;
auto beginning = str.c_str();
int i = 0;
char* p = (char *)beginning;
while (p && '\0'!=p)
{
p = strstr(p, substr.c_str());
if (!p)
break;
cout << "A substring is at index:" << p - beginning << "\n";
p++;
};
return 0;
}
void test()
{
string substr, str;
{
substr = "ab"; str = "aabb";
cout << "Finding " << substr << " in " << str << "\n";
find_substr(substr, str);
cout << "\n";
}
{
substr = "ab"; str = "abab";
find_substr(substr, str);
cout << "\n";
}
{
substr = "a"; str = "11111111111111111111111a";
find_substr(substr, str);
cout << "\n";
}
}

Related

Detecting if input string has a space

I wrote this code to detect if an input string has a space or not. Please tell what is wrong in this approach.
#include <iostream>
#include <string>
using namespace std;
int main(){
string inp;
getline(cin, inp);
for (int i = 0; i < inp.length(); i++) {
string z = to_string(inp[i]);
if (z == " ") {
cout << "space";
}
else {
i++;
}
}
}
If i enter a string with spaces, it doesn't print "space".
Since inp is an std::string, inp[i] will be a char. Since std::to_string only has overloads for arithmetic, non-char values, calling it on a char is akin to calling it on the integer representation of said char. (If you log z, you'll likely find a number printed.)
Instead, directly compare inp[i] to a space. else { i++; } is also unnecessary – you may be jumping over spaces.
for (int i = 0; i < inp.length(); i++) {
if (inp[i] == ' ') { // note single quotes for char
cout << "space";
}
}
#TrebledJ's answer explains why your code is broken and how to fix it.
Another way to handle this situation is to use std::string::find() instead:
#include <iostream>
#include <string>
int main(){
std::string inp;
std::getline(std::cin, inp);
if (inp.find(' ') != std::string::npos) {
std::cout << "space";
}
}
Alternatively, your original code tries to output "space" for each space character found. You could use find() in a loop:
#include <iostream>
#include <string>
int main(){
std::string inp;
std::getline(std::cin, inp);
std::string::size_type idx = inp.find(' ');
while (idx != std::string::npos) {
std::cout << "space at " << idx << std::endl;
idx = inp.find(' ', idx+1);
}
}

Insert a character into a string

I need to insert a character into a string at every instance of that character. For example if my string was, "This is a test" and my character was 's' then my output would need to look like this: "Thiss iss a tesst"
any idea why this isn't working? Here's what I have so far. I am not supposed to add any extra preprocessor instructions or anything, just using what's here I need to figure this out.
#include <iostream>
#include <string>
using namespace std;
int main(){
string userString;
char userChar;
cin >> userString;
cin >> userChar;
for (int i = 0; i < userString.size(); i++){
if(userString.at(i) == userChar){
userString.insert(userString.begin() + i, userChar);
}
}
cout << userString;
return 0;
Update:
Here's the solution I worked out.
#include <iostream>
#include <string>
using namespace std;
int main(){
string userString;
char userChar;
cout << "enter a string" << endl;
getline(cin, userString);
cout << "enter a character" << endl;
cin >> userChar;
for (int i = userString.size()-1; i >= 0; i--){
if(userString.at(i) == userChar){
userString.insert(userString.begin() + i, userChar);
}
}
cout << userString;
return 0;
}
I don't know why you want to go through the string backwards. Anyway. Your problem is that once you insert a character at some position, your loop will encounter the inserted character again in the next iteration and insert another. Ad infinitum.
#include <cstddef> // std::size_t, the correct type for indexes and sizes of objects in mem
#include <string>
#include <iostream>
int main()
{
std::cout << "Enter a string: ";
std::string userString; // define variables as close
std::getline(std::cin, userString);
std::cout << "Enter a character: ";
char userChar; // to where they're used as possible
std::cin >> userChar;
for (std::size_t i{}; i < userString.size(); ++i) {
if (userString[i] == userChar) { // no need to use std::string::at() 1)
userString.insert(userString.begin() + i, userChar);
++i; // advance the index to not read the same character again.
}
}
std::cout << userString << '\n';
}
1) since it is allready sure that the index will be in a valid range.
Your first solution probably ends up looping infinitely if you ever find one of the chosen character because you always insert one more copy ahead and keeps finding the same char ever after.
std::basic_string has a find function. It's always better to use code offered by a library than self made code. Here's my proposed solution:
std::string& duplicate_char(std::string& str, char val)
{
using std::string;
auto pos = str.find(val); // finds first index of character val or npos if unsuccessful
while (pos != string::npos)
{
str.insert(pos, 1, val); // insert at pos one character val
pos = str.find(val, pos + 2); // find the next occurence of val starting after the newly inserted character
}
return str;
}
You may use this function like this:
int main()
{
std::string testStr{"Thiss iss a tesst"};
duplicate_char(testStr, 's');
std::cout << testStr << std::endl;
}

C++ print string one word at a time, count characters, and average of characters

how can I print a single word from a string in each line with the number of characters right next to it and the average of the characters together? I'm suppose to use a string member function to convert the object into a c string. The function countWords accepts the c string and returns an int. The function is suppose to read in each word and their lengths including the average of characters. I have done how much words are in the string except I don't know how continue the rest.
For example: super great cannon boys
super 5
great 5
cannon 6
boys 4
average of characters: 5
This is my program so far:
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int countWords(char *sentence);
int main()
{
const int size=80;
char word[size];
double average=0;
cout<<"Enter words less than " <<size-1<<" characters."<<endl;
cin.getline(word, size);
cout <<"There are "<<countWords(word)<<" words in the sentence."<<endl;
return 0;
}
int countWords(char *sentence)
{
int words= 1;
while(*sentence != '\0')
{
if(*sentence == ' ')
words++;
sentence++;
}
return words;
}
Unless this is something like homework that prohibits doing so, you almost certainly want to use std::string along with the version of std::getline that works with a std::string instead of a raw buffer of char:
std::string s;
std::getline(std::cin, s);
Then you can count the words by stuffing the line into a std::istringstream, and reading words out of there:
std::istringstream buffer(s);
auto word_count = std::count(std::istream_iterator<std::string>(s),
std::istream_iterator<std::string());
To print out the words and their lengths as you go, you could (for example) use std::for_each instead:
int count = 0;
std::for_each(std::istream_iterator<std::string>(s),
std::istream_iterator<std::string>(),
[&](std::string const &s) {
std::cout << s << " " << s.size();
++count;});
This should not be far from you requirements - I only did minimal modification to your present code.
Limits :
you'd better use
string line;
getline(cin, line);
to read the line to be able to accept lines of any size
my present code assumes
no spaces at beginning or end of line
one single space between 2 words
it should be improved to cope with extra spaces, but I leave that to you as an exercise :-)
The code :
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int countWords(char *sentence, double& average);
int main()
{
const int size=80;
char word[size];
double average=0;
cout<<"Enter words less than " <<size-1<<" characters."<<endl;
cin.getline(word, size);
cout <<"There are "<<countWords(word, average)<<" words in the sentence."<<endl;
cout << "Average of the sentence " << average << endl;
return 0;
}
int countWords(char *sentence, double& average)
{
int words= 1;
int wordlen;
char *word = NULL;
while(*sentence != '\0')
{
if(*sentence == ' ') {
words++;
wordlen = sentence - word;
average += wordlen;
*sentence = '\0';
cout << word << " " << wordlen<< endl;
word = NULL;
}
else if (word == NULL) word = sentence;
sentence++;
}
wordlen = sentence - word;
average += wordlen;
cout << word << " " << wordlen<< endl;
average /= words;
return words;
}
For input : super great cannon boys
Output is :
Enter words less than 79 characters.
super great cannon boys
super 5
great 5
cannon 6
boys 4
There are 4 words in the sentence.
Average of the sentence 5
You can inspire here. Basically use std::getline to read from std::cin to std::string.
#include <iostream>
#include <string>
#include <cctype>
inline void printWordInfo(std::string& word) {
std::cout << "WORD: " << word << ", CHARS: " << word.length() << std::endl;
}
void printInfo(std::string& line) {
bool space = false;
int words = 0;
int chars = 0;
std::string current_word;
for(std::string::iterator it = line.begin(); it != line.end(); ++it) {
char c = *it;
if (isspace(c)) {
if (!space) {
printWordInfo(current_word);
current_word.clear();
space = true;
words++;
}
}
else {
space = false;
chars++;
current_word.push_back(c);
}
}
if (current_word.length()) {
words++;
printWordInfo(current_word);
}
if (words) {
std::cout << "AVERAGE:" << (double)chars/words << std::endl;
}
}
int main(int argc, char * argv[]) {
std::string line;
std::getline(std::cin, line);
printInfo(line);
return 0;
}
Going along the lines of what you already have:
You could define a countCharacters function, like your countWords:
int countCharacters(char *sentence)
{
int i;
char word[size];
for(i = 0; sentence[i] != ' '; i++) //iterate via index
{
word[i] = sentence[i]; //save the current word
i++;
}
cout <<word<< <<i<<endl; //print word & number of chars
return i;
}
which you can call inside your countWords function
int countWords(char *sentence)
{
int words = 1;
for(int i; sentence[i] != '\0';) //again this for loop, but without
//increasing i automatically
{
if(sentence[i] == ' ') {
i += countCharacters(sentence[++i]); //move i one forward to skip
// the space, and then move
// i with the amount of
// characters we just counted
words++;
}
else i++;
}
return words;
}

How to Convert a C++ String to Uppercase

I need to convert a string in C++ to full upper case. I've been searching for a while and found one way to do it:
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main()
{
string input;
cin >> input;
transform(input.begin(), input.end(), input.begin(), toupper);
cout << input;
return 0;
}
Unfortunately this did not work and I received this error message:
no matching function for call to 'transform(std::basic_string::iterator, std::basic_string::iterator, std::basic_string::iterator,
I've tried other methods that also did not work. This was the closest to working.
So what I'm asking is what I am doing wrong. Maybe my syntax is bad or I need to include something. I am not sure.
I got most of my info here:
http://www.cplusplus.com/forum/beginner/75634/
(last two posts)
You need to put a double colon before toupper:
transform(input.begin(), input.end(), input.begin(), ::toupper);
Explanation:
There are two different toupper functions:
toupper in the global namespace (accessed with ::toupper), which comes from C.
toupper in the std namespace (accessed with std::toupper) which has multiple overloads and thus cannot be simply referenced with a name only. You have to explicitly cast it to a specific function signature in order to be referenced, but the code for getting a function pointer looks ugly: static_cast<int (*)(int)>(&std::toupper)
Since you're using namespace std, when writing toupper, 2. hides 1. and is thus chosen, according to name resolution rules.
Boost string algorithms:
#include <boost/algorithm/string.hpp>
#include <string>
std::string str = "Hello World";
boost::to_upper(str);
std::string newstr = boost::to_upper_copy("Hello World");
Convert a String In C++ To Upper Case
Try this small program, straight from C++ reference
#include <iostream>
#include <algorithm>
#include <string>
#include <functional>
#include <cctype>
using namespace std;
int main()
{
string s;
cin >> s;
std::transform(s.begin(), s.end(), s.begin(), std::ptr_fun<int, int>(std::toupper));
cout << s;
return 0;
}
Live demo
You could do:
string name = "john doe"; //or just get string from user...
for(int i = 0; i < name.size(); i++) {
name.at(i) = toupper(name.at(i));
}
Uppercase to Lowercase and viceversa using BitWise operators
1.
string s = "cAPsLock";
for(char &c: s)
c = c | ' '; // similar to: c = tolower(c);
cout << s << endl; // output: capslock
string s = "cAPsLock";
for(char &c: s)
c = c & ~' '; // similar to: c = toupper(c);
cout << s << endl; // output: CAPSLOCK
PS: for more info check this link
#include <iostream>
using namespace std;
//function for converting string to upper
string stringToUpper(string oString){
for(int i = 0; i < oString.length(); i++){
oString[i] = toupper(oString[i]);
}
return oString;
}
int main()
{
//use the function to convert string. No additional variables needed.
cout << stringToUpper("Hello world!") << endl;
return 0;
}
Like leemes said, you can use toupper(int). Like this:
void ToUpper(string &str) {
for (auto beg = str.begin(); beg != str.end(); ++beg) {
*beg = toupper(*beg);
}
}
It'll through in each character from str and convert it to upper. Example:
int main()
{
string name;
cout << "Insert a name: ";
cin >> name;
ToUpper(name);
cout << "Name in upper case: " << name << endl;
}
You can also use the function from code below to convert it to Upper-case.
#include<iostream>
#include<cstring>
using namespace std;
//Function for Converting Lower-Case to Upper-Case
void fnConvertUpper(char str[], char* des)
{
int i;
char c[1 + 1];
memset(des, 0, sizeof(des)); //memset the variable before using it.
for (i = 0; i <= strlen(str); i++) {
memset(c, 0, sizeof(c));
if (str[i] >= 97 && str[i] <= 122) {
c[0] = str[i] - 32; // here we are storing the converted value into 'c' variable, hence we are memseting it inside the for loop, so before storing a new value we are clearing the old value in 'c'.
} else {
c[0] = str[i];
}
strncat(des, &c[0], 1);
}
}
int main()
{
char str[20]; //Source Variable
char des[20]; //Destination Variable
//memset the variables before using it so as to clear any values which it contains,it can also be a junk value.
memset(str, 0, sizeof(str));
memset(des, 0, sizeof(des));
cout << "Enter the String (Enter First Name) : ";
cin >> str; //getting the value from the user and storing it into Source variable.
fnConvertUpper(str, des); //Now passing the source variable(which has Lower-Case value) along with destination variable, once the function is successfully executed the destination variable will contain the value in Upper-Case
cout << "\nThe String in Uppercase = " << des << "\n"; //now print the destination variable to check the Converted Value.
}

How do I get a part of the a string in C++?

How do I get a part of a string in C++? I want to know what are the elements from 0 to i.
You want to use std::string::substr. Here's an example, shamelessly copied from http://www.cplusplus.com/reference/string/string/substr/
// string::substr
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str="We think in generalities, but we live in details.";
// quoting Alfred N. Whitehead
string str2, str3;
size_t pos;
str2 = str.substr (12,12); // "generalities"
pos = str.find("live"); // position of "live" in str
str3 = str.substr (pos); // get from "live" to the end
cout << str2 << ' ' << str3 << endl;
return 0;
}
You use substr, documented here:
#include <iostream>
#include <string>
using namespace std;
int main(void) {
string a;
cout << "Enter string (5 characters or more): ";
cin >> a;
if (a.size() < 5)
cout << "Too short" << endl;
else
cout << "First 5 chars are [" << a.substr(0,5) << "]" << endl;
return 0;
}
You can also then treat it as a C-style string (non-modifiable) by using c_str, documented here.
If the string is declared as an array of characters, you can use the following approach:
char str[20];
int i;
strcpy(str, "Your String");
// Now let's get the sub-string
cin >> i;
// Do some out-of-bounds validation here if you want..
str[i + 1] = 0;
cout << str;
If you mean std::string, use substr function as Will suggested.
Assuming you're using the C++ std::string class
you can do:
std::string::size_type start = 0;
std::string::size_type length = 1; //don't use int. Use size type for portability!
std::string myStr = "hello";
std::string sub = myStr.substr(start,length);
std::cout << sub; //should print h
use:
std::string sub_of_s(s.begin(), s.begin()+i);
which create a string sub_of_s which is the first i-th the element in s.