Infinite loop using string.substr(post,len) - c++

Could you figure out why it keeps looping infinitely in the console? The programmer's supposed to list out each character of a user-inserted string and next to each unique character, in brackets, it's supposed to display the number of times that character occurs in the string... no idea why.
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main () {
string input;
cout << "input string: " , cin >> input;
sort (input.begin() , input.end());
while (!input.empty()) {
int j{1}, i{0};
while (input.at(i) == input.at(i+1)) {
j++;
i++;
}
cout << input.at(i) << " (" << j << "), ";
input.substr(i);
}
return 0;
}

This statement
input.substr(i);
does not change the object input itself.
So, either you will have an infinite loop if for some index i input.at(i) is not equal to input.at(i+1), or you can have an exception out of range because i + 1 can be equal to input.size().
From the description of the member function at
Throws: out_of_range if pos >= size().
The program can be implemented in different ways. For example the following way
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::cout << "input string: ";
std::string input;
std::cin >> input;
std::sort( input.begin() , input.end() );
for ( size_t i = 0; i < input.size(); )
{
size_t j = input.find_first_not_of( input[i], i );
if ( j == std::string::npos ) j = i + 1;
if ( i != 0 ) std::cout << ", ";
std::cout << input[i] << " (" << j - i << ")";
i = j;
}
std::cout << '\n';
return 0;
}
The program output is
input string: Hello
H (1), e (1), l (2), o (1)
Or you can use the standard container std::map or std::unordered_map as for example
#include <iostream>
#include <string>
#include <map>
int main()
{
std::cout << "input string: ";
std::string input;
std::cin >> input;
std::map<char, size_t> m;
for ( const auto &c : input )
{
++m[c];
}
bool first = true;
for ( const auto &p : m )
{
if ( !first ) std::cout << ", ";
std::cout << p.first << " (" << p.second << ")";
first = false;
}
std::cout << '\n';
return 0;
}
If you want that characters of the inputted string were output in the order in which they are present in the string then the program can look like
#include <iostream>
#include <string>
#include <map>
int main()
{
std::cout << "input string: ";
std::string input;
std::cin >> input;
auto less = [&input]( const auto &c1, const auto &c2 )
{
return input.find( c1 ) < input.find( c2 );
};
std::map<char, size_t, decltype( less )> m( less );
for ( const auto &c : input )
{
++m[c];
}
bool first = true;
for ( const auto &p : m )
{
if ( !first ) std::cout << ", ";
std::cout << p.first << " (" << p.second << ")";
first = false;
}
std::cout << '\n';
return 0;
}
Or without changing the original string and without using an additional container the program can look the following way.
#include <iostream>
#include <string>
int main()
{
std::cout << "input string: ";
std::string input;
std::cin >> input;
for ( size_t i = 0; i < input.size(); i++ )
{
size_t j = 0;
while ( j != i && input[j] != input[i] ) j++;
if ( j == i )
{
size_t count = 1;
while ( ++j < input.size() )
{
if ( input[j] == input[i] ) ++count;
}
if ( i != 0 ) std::cout << ", ";
std::cout << input[i] << " (" << count << ")";
}
}
std::cout << '\n';
return 0;
}
The program output might look like
input string: elephant
e (2), l (1), p (1), h (1), a (1), n (1), t (1)

Related

The string in the struct cannot be output after being put into the vector --- a problem

I defined a string class called "atom" in struct. Like this
#include <iostream>
#include <fstream>
#include <string>
#include <string.h>
#include <cstring>
#include <iomanip>
#include <vector>
#include "Sab.h"
using namespace std;
struct STO
{
string atom;
int atomNo;
int BNoba;
int SNoba;
int coatomNo;
int baatomNo;
int px;
int py;
int pz;
double x=0.0;
double y=0.0;
double z=0.0;
};
then I defined a vector and single struct to get input data.
int main()
{
......
ifstream inco("nh3.gjf");
if(!inco)
{
cout << "can't open this file!" << endl;
exit( 1 );
}
........
vector<STO> sto;
STO stotemp;
......
while ( sscanf( StrLine.c_str(), " %[a-zA-Z] %lf%lf%lf", stotemp.atom.c_str(), &(stotemp.x), &(stotemp.y), &(stotemp.z)) == 4 )
......
cout << stotemp.atom.c_str() << " " <<stotemp.coatomNo<<" "<< stotemp.atom << " " << stotemp.x << " " << stotemp.y << " " << stotemp.z << endl;
Everyting is ok so far. The output of stotemp.atom.c_str() is normal. But when I put stotemp into the vector sto, something happened.
sto.push_back(stotemp);
......
cout << tempc.c_str()<< " "<< sto[i].atom.c_str() << endl;
I can't get any out put from sto[i].atom.c_str(), but the other members in sto[i] is normal.
Anyone tell me how to fix it? thanks a lot!
Complete code (didn't finished)
#include <iostream>
#include <fstream>
#include <string>
#include <string.h>
#include <cstring>
#include <iomanip>
#include <vector>
#include "Sab.h"
using namespace std;
struct STO
{
string atom;
int atomNo;
int BNoba;
int SNoba;
int coatomNo;
int baatomNo;
int px;
int py;
int pz;
double x=0.0;
double y=0.0;
double z=0.0;
};
int main()
{
inti, j, k, l, m , sums,sump, p, q, s1, s2, s3, s4,nse, stons,ns,np, npe,stonp, nd, nc, na, charge, spin, **zetas, **zetap, *elec, *eleb ,tempi,*han;
double**co, **basa, **basc, **bapa, **bapc, tempd ,hh ,kk ,V_nn ,Escf ,**C_ij ,**S_ij ,**T_ij ,**H_ij ,**F_ij , **P_ij;
stringStrLine, tempc;
charZele[119][3] = { "0", "H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne" };
ifstream inco("nh3.gjf");
if(!inco)
{
cout << "can't open this file!" << endl;
exit( 1 );
}
ifstream inba("3-21g.TXT");
if(!inba)
{
cout << "can't open this file!" << endl;
exit( 1 );
}
nc=0;
while(!inco.eof())
{
getline(inco,StrLine);
if ( sscanf( StrLine.c_str(), "%d%d", &charge, &spin ) == 2 )
{
//cout << StrLine << endl;
nc = 0;
while (!inco.eof())
{
getline(inco,StrLine);
nc++;
}
break;
}
}
na = 0;
tempi = 0;
while ( !inba.eof() )
{
getline(inba,StrLine);
if ( sscanf( StrLine.c_str(), "%[a-zA-Z] %d ",tempc.c_str() , &tempi ) == 2 && tempi == 0 )
{
na++;
}
}
inba.clear();
inba.seekg(0,inba.beg);
inco.seekg(0,inco.beg);
vector<STO> sto;
STO stotemp;
i = 1;
while ( !inco.eof() )
{
getline(inco,StrLine);
if ( sscanf( StrLine.c_str(), "%d%d", &charge, &spin ) == 2 )
{
i = 1;
getline(inco,StrLine);
while ( sscanf( StrLine.c_str(), " %[a-zA-Z] %lf%lf%lf", stotemp.atom.c_str(), &(stotemp.x), &(stotemp.y), &(stotemp.z)) == 4 )
{
stotemp.x=stotemp.x/0.5291772083;
stotemp.y=stotemp.y/0.5291772083;
stotemp.z=stotemp.z/0.5291772083;
for ( j = 1; j <= 118; j++ )
{
if ( strcmp( stotemp.atom.c_str(), Zele[j] ) == 0 )
{
stotemp.atomNo = j;
stotemp.coatomNo= i;
cout << stotemp.atom.c_str() << " " <<stotemp.coatomNo<<" "<< stotemp.atom << " " << stotemp.x << " " << stotemp.y << " " << stotemp.z << endl;
sto.push_back(stotemp);
i++;
break;
}
}
if(inco.eof())
break;
else
getline(inco,StrLine);
}
}
}
while ( !inba.eof() )
{
getline(inba,StrLine);
if ( sscanf( StrLine.c_str(), "%[a-zA-Z] 0 ", tempc.c_str() ) == 1 )
{
for ( i =0; i <= nc-1; i++ )
{
for(j=0;j<=na-1;j++)
{
stotemp=sto[i];
cout << tempc.c_str()<< " "<< sto[i].atom << endl;
system("pause");
if ( strcmp( tempc.c_str(), stotemp.atom.c_str() ) == 0 )
{
sto[i].baatomNo = j+1;
cout << sto[i].atomNo <<sto[i].baatomNo << endl;
system("pause");
break;
}
}
}
}
}
inba.seekg(0,inba.beg);
V_nn=0.0;
for ( i = 0; i <= nc-1; i++ )
{
for ( j = i+1; j <= nc-1; j++ )
{
V_nn+=(sto[i].atomNo*sto[j].atomNo)/norm2(sto[i].x,sto[i].y, sto[i].z ,sto[j].x,sto[j].y, sto[j].z );
}
}
cout << "coordinate and distance are expressed by Bhor" << endl;
cout << fixed<<setprecision(6) <<V_nn << endl;
inco.seekg(0,inco.beg);
system("pause");
/* ns= 0;
np= 0;
nse= 0;
npe= 0;
tempi=0;
stons = 0;
stonp = 0;
for(i=0 ; i<= nc-1 ; i++)
{
for ( j = 0; j <= na-1; j++ )
{
while ( !inba.eof())
{
getline( inba,StrLine );
if ( strstr( StrLine.c_str(), "****" ) != NULL )
{
break;
}
if ( sscanf( StrLine.c_str(), "S %d %*lf", &j ) == 1 )
{
ns+= j;
nse+= j;
stons += 1;
}
if ( sscanf( StrLine.c_str(), "SP %d %*lf", &j ) == 1 )
{
ns= ns + j;
np= np + j;
nse+= j;
npe+= j;
stons+= 1;
stonp+= 3;
}
}
}
}*/
}
nh3.gjf:
%chk=D:\LSZ\tf\NH3\nh3.chk
# hf/3-21g geom=connectivity
Title Card Required
0 1
N 0.00000000 0.00000000 0.00000000
H 0.00000000 0.00000000 1.00000000
H 0.94280915 0.00000000 -0.33333304
H -0.47140478 -0.81649655 -0.33333304
3-21g.TXT:
H 0
S 2 1.00
5.4471780 0.1562850
0.8245470 0.9046910
S 1 1.00
0.1831920 1.0000000
****
N 0
S 3 1.00
242.7660000 0.0598657
36.4851000 0.3529550
7.8144900 0.7065130
SP 2 1.00
5.4252200 -0.4133010 0.2379720
1.1491500 1.2244200 0.8589530
SP 1 1.00
0.2832050 1.0000000 1.0000000
****
++++++++++++++++++++++++++++++++++
Oh! I forgot the Sab! sorry!
Sab.cpp
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define pai 3.1415927
double norm2(double xx1,double yy1,double zz1,double xx2,double yy2,double zz2)
{
double norm;
norm=sqrt(pow(xx2-xx1,2)+pow(yy2-yy1,2)+pow(zz2-zz1,2));
return norm;
}
and Sab.h
#ifndef SAB_H_INCLUDED
#define SAB_H_INCLUDED
double norm2(double xx1,double yy1,double zz1,double xx2,double yy2,double zz2);
#endif // SAB_H_INCLUDED
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
First of all, you should not read into stotemp.c_str() because that is of type const char *, thus you should not modify its content. My compiler (g++) gives a warning about that.
Your code seems to work because a std::string object contains an internal buffer that holds the actual string data and also a field that specifies the size of the string. A call to c_str() returns a pointer to this buffer. If you use the std::string default constructor then this internal buffer is created with a certain size. In my case the default initial buffer size is 15. c_str() returns this buffer. So you can safely read up to 15 characters into that buffer. If you then print that buffer immediately, it will show the correct string. However, with your scanf operation you do not update the length field of the string object. So the object still thinks that the string has length 0, so it will only copy a string of length 0 when copying the structure into the vector.
As you can see, you are just misusing the internal buffer of a std::string instance and it is pure luck that this does create problems. As soon as the string you read will be longer than the initial buffer size of a std::string you will write into bad memory locations and your program will probably crash.
In order to scan those 4 fields from StrLine you could do something like this:
std::stringstream s(StrLine);
while (s >> stotemp.atom >> stotemp.x >> stotemp.y >> stotemp.z) {
std::cout << stotemp.atom << ", " << stotemp.x << ", "
<< stotemp.y << ", " << stotemp.z << std::endl;
}
or explicitly handle the beginning of the string and the use sscanf for the rest:
char const *line = StrLine.c_str();
while (isspace(*line)) ++line; // Skip leading whitespace
char const *end = line;
while (isalpha(*end)) ++end; // Find first non-alpha charachter
stotemp.atom = std::string(line, end); // capcture string
sscanf(end, "%lf %lf %lf", &stotemp.x, &stotemp.y, &stotemp.z);
std::cout << stotemp.atom << ", " << stotemp.x << ", "
<< stotemp.y << ", " << stotemp.z << std::endl;
return 0;
That would give you more control about what characters you want to accept for atom.

Create the largest possible number from input - implementation issue with cout

I am trying to implement an algorithm that will take a set of numbers and output the largest possible number (without breaking up the individual numbers). So in an example like this where I give 4 numbers:
4
43 12 3 91
The output would be
91-43-3-12 or 9143312.
My attempt is below.
#include <algorithm>
#include <sstream>
#include <iostream>
#include <vector>
#include <string>
using std::vector;
using std::string;
bool compare (int x, int y) {
std::cout << "in func \n";
string a = std::to_string(x);
string b = std::to_string(y);
std::cout << a << " " << b << "\n";
std::cout << std::stoi(a.substr(0, 1)) << " " << std::stoi(b.substr(0, 1)) << "\n" ;
if (std::stoi(a.substr(0, 1)) < std::stoi(b.substr(0, 1))) {
std::cout.flush();
std::cout << "if \n";
return true;
}
else {
std::cout.flush();
std::cout <<"else \n";
return false;
}
}
string largest_number(vector<string> a) {
std::stringstream ret;
while (a.size() > 0) {
int maxNumber =-1;
int index = -1;
std::cout << "going into for " << a.size() << "\n";
for (size_t i = 0; i < a.size(); i++) {
if (! compare (stoi(a[i]), maxNumber ) ) { //stoi(a[i]) >= maxNumber) {
maxNumber = stoi(a[i]);
std::cout << maxNumber << " " << i << "\n";
index = i;
}
std::cout << "here \n";
}
ret << maxNumber;
a.erase(a.begin() + index);
}
string result;
ret >> result;
return result;
}
int main() {
int n;
std::cin >> n;
vector<string> a(n);
for (size_t i = 0; i < a.size(); i++) {
std::cin >> a[i];
}
std::cout << largest_number(a);
}
I do not understand what is wrong with my compare function. When I run it, say with this input:
$ g++ -pipe -O2 -std=c++14 largest_number.cpp -lm -o largest1
$ ./largest1.exe
4
4 23 1 45
going into for 4
in func
4 -1
It doesnt print the cout statements in the conditional if or else. How could this be possible? I even tried flushing. However, if I take the entire conditional out, put a cout statement and the return true or something, then it runs the program in entirety (although this is not the expected output).
I do not mind harsh criticism. What am I doing wrong here? Any advice will be appreciated.
Thanks in advance.
In this statement
std::cout << std::stoi(a.substr(0, 1)) << " " << std::stoi(b.substr(0, 1)) << "\n" ;
when b is equal to -1 the expression b.substr(0, 1) is equal to an object of type std::string that contains one character '-' that is the minus sign.
If to apply the standard function std::stoi to such a string then an exception will be thrown.
Consider the following code snippet
std::string s("-");
try
{
std::stoi(s);
}
catch (const std::exception &e)
{
std::cout << e.what() << std::endl;
}
Its output will be
invalid stoi argument
It seems what you need is just to sort the strings. For example
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
int main()
{
std::vector<std::string> v { "4", "23", "1", "45" };
auto cmp = [](const std::string &a, const std::string &b)
{
std::string::size_type i = 0, m = a.size();
std::string::size_type j = 0, n = b.size();
int result;
do
{
if (m < n)
{
result = a.compare(i, m, b, j, m);
j += m;
n -= m;
}
else
{
result = a.compare(i, n, b, j, n);
i += n;
m -= n;
}
} while (result == 0 && m && n);
return 0 < result;
};
std::sort(v.begin(), v.end(), cmp);
for (const auto &s : v) std::cout << s;
std::cout << std::endl;
return 0;
}
The output of the program will be
454231
Or for this set of numbers
std::vector<std::string> v{ "43", "12", "3", "91" };
the output will be
9143312
or for one more set of numbers
std::vector<std::string> v{ "93", "938" };
the output will be
93938

how can I find the sequence number (index) of word in such a paragraph c++?

I'm working on a project which needs to find the number of words and the indices of each word in the paragraph ...I have written the code which is counting the number of word in a string but I stuck with finding the indices of words,
such as : Hi John How are you I miss you ..
I need to print the indices like : 0 1 2 3 4 5 6 7
here is the code:
int _tmain(int argc, _TCHAR* argv[])
{
int count_words(std::string);
std::string input_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
int number_of_words=1;
int counter []={0};
for(int i = 0; i < input_text.length();i++)
if(input_text[i] == ' ')
number_of_words++;
std::cout << "Number of words: " << number_of_words << std::endl;
//std:: cout << number_of_words << std::endl;
system ("PAUSE");
}
Hopefully this helps. Edited to include use of count_words function.
#include <iostream>
#include <sstream>
void count_words(std::string);
int main(){
std::string input_text, output_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
count_words(input_text);
system ("PAUSE");
return 0; //MUST RETURN AN INTEGER VALUE FROM 'INT MAIN'
}
void count_words(std::string inputString){
std::string output_text;
std::stringstream indexes;
int number_of_words=0; //If there are no words, it would be false, make it 0.
//int counter []={0}; //This serves no purpose.
if(!inputString.empty()){// test to make sure it isn't empty.
number_of_words++;
for(int i = 0; i < inputString.length();i++){ // For loops should have curly braces {} containing their statement.
if(inputString[i] == ' '){
number_of_words++;
}
if((isalpha(inputString[i]))&&inputString[i-1]==' '){ //test for following space separated word
indexes << i << " ";
}
}
}
output_text = indexes.str(); //convert stringstream to string
std::cout << "Number of words: " << number_of_words << std::endl;
//std:: cout << number_of_words << std::endl; //duplicate info
std::cout << "Indexes: " << output_text << std::endl;
}
I'm not sure if i understand the question. You only need print the "indices"?? like this? (Using your own code)
#include <iostream>
#include <vector>
#include <string>
void stringTokenizer(const std::string& str, const std::string& delimiter, std::vector<std::string>& tokens) {
size_t prev = 0, next = 0, len;
while ((next = str.find(delimiter, prev)) != std::string::npos) {
len = next - prev;
if (len > 0) {
tokens.push_back(str.substr(prev, len));
}
prev = next + delimiter.size();
}
if (prev < str.size()) {
tokens.push_back(str.substr(prev));
}
}
int main()
{
std::vector <std::string> split;
std::string input_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
stringTokenizer(input_text, " ", split);
int number_of_words = 0;
for (std::vector<std::string>::iterator it = split.begin(); it != split.end(); it++, number_of_words++) {
std::cout << *it << " " << number_of_words << std::endl;
}
}

C++ Search for a unique word and assign it a number

I am looking at various examples of reading an input file and counting the occurrences of a word. Then give it a variable to count.
Lets say we have an input file and you want to look for how many times the word "account" or word "like" shows up and give it the variable "1.2". So when you find the word, count how many times it occurs and then times it by 1.2 .
How would you go about doing this?
EDIT: This is the only way I know how. However, this pre-searches the word versus letting the user search it
#include <iostream>
#include <fstream>
using namespace std;
int main(void)
{
int option=0; //option number
ifstream inputFile;
string filename;
cout << "Welcome\n" << endl;
//Getting the input file
cout << "Enter input data file name:";
cin >> filename;
cout << endl;
fin.open(filename.c_str()); // change to C-string
if (!inputFile) {// makes sure file exist
cout << "Unable to open " << filename << endl;
cin.get();
return 1;
}
do {
cout << "5- Count frequency of the following three words individually: I, like, is" << endl;
cout << "6 - To quit";
cout << endl;
cin >> option;
int iWord = 0;
int likeWord = 0;
int isWord = 0;
if (option == 5) {
string word;
do {
inputFile >> word;
if (word == "I") iWord++;
else if (word== "like") likeWord++;
else if (word == "is") isWord++;
}while (inputFile.good());
cout << "The word I is repeated " << iWord << " times" << endl;
cout << "The word is has been repeated " << isWord << " times" << endl;
cout << "The word like is repeated " << likeWord << " times" << endl << endl;
}
inputFile.clear(); // clear fail bit or seekg won't work!
inputFile.seekg (0, ios::beg);
}while (option != 6);
return 0;
}
Not the most efficient way (especially for one word), but maybe this could give you direction:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <algorithm>
#include <unordered_map>
void tokenize( const std::string & line, std::unordered_map< std::string, size_t > & map_count )
{
for( std::string::size_type pos_start = 0, pos_end = 0; ( pos_end != std::string::npos ) && ( pos_start = line.find_first_of( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", pos_end ) ) != std::string::npos; )
{
pos_end = line.find_first_not_of( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", pos_start );
std::string current_word = ( pos_end == std::string::npos ) ? line.substr( pos_start ) : line.substr( pos_start, pos_end - pos_start );
std::unordered_map< std::string, size_t >::iterator iter( map_count.find( current_word ) );
if( iter == map_count.end() )
map_count.insert( std::pair< std::string, size_t >( current_word, 1 ) );
else
++( iter->second );
}
}
void countWordsInFile( const std::string & filename, std::unordered_map< std::string, size_t > & map_count )
{
std::ifstream in( filename );
std::string line;
size_t count = 0;
if( in.is_open() )
while( std::getline( in, line ).good() )
tokenize( line, map_count );
}
double countAndWeigh( const std::string & filename, const std::string & word, double weight )
{
std::unordered_map< std::string, size_t > map_count;
countWordsInFile( filename, map_count );
std::unordered_map< std::string, size_t >::const_iterator iter( map_count.find( word ) );
return ( iter != map_count.end() ) ? iter->second * weight : 0;
}
int main( int argc, char ** argv )
{
if( argc == 4 )
std::cout << countAndWeigh( argv[1], argv[2], strtod( argv[3], nullptr ) ) << std::endl;
return 0;
}

Recursion of an index

Hello fellow programmers, I have a question about recursion that I do not understand, being new to C++ and all. So for this exercise I am completing, I need to: 1. Ask user for a string 2. Ask user for a string to search in the first string entered. 3. report and index of the string if it finds it. For instance the user enters the string "Search me", string to search for is "me", and the index would return "7". I am throwing my hands up at this point for some help on how to complete it, any help would be appreciated. Here is my code thus far. The stuff that is in the for loop isn't a complete thought, just FYI.
int index_of(string stringToSearchIn, string stringToSearchFor, int index)
{
if (stringToSearchIn.length() < stringToSearchFor.length())
{
cout << "Your string cannot be found." << endl;
system("PAUSE");
return OUTLIER;
}
else
{
bool found = true;
for (int i = ZERO; i < stringToSearchFor.length; i++)
{
found = found && stringToSearchIn(i) == stringToSearchFor(i);
}
return index;
}
return index_of(stringToSearchIn.substr(INCREASE), stringToSearchFor, index++);
}
int main()
{
//Initializing values
string userString;
string userSearch;
int userIndex = 0;
//Asking for user input for string
cout << "This program will find the occurence of one string inside of another." << endl;
cout << "Enter the string to be searched: " << userString;
//Getting the string
getline(cin, userString);
//Asking for user input for search input
cout << "Now enter the string you want to search for: " << userSearch;
//Getting the string
getline(cin, userSearch);
//Displaying results
cout << "The index of the substring is = " << index_of(userString, userSearch, userIndex);
//Keeping console window open until key press
system("PAUSE");
return ZERO;
}
Catch.:)
#include <iostream>
size_t index_of( const char *s, const char *t )
{
const char *p = s;
const char *q = t;
while ( *q && *p == *q ) ++p, ++q;
if ( *q == '\0' )
{
return 0;
}
else if ( *p == '\0' )
{
return -1;
}
else
{
size_t n = 1 + index_of( s + 1, t );
return n == 0 ? -1 : n;
}
}
int main()
{
const char *s = "Search me";
const char *t = "me";
size_t n = index_of( s, t );
if ( n != -1 )
{
std::cout << "string " << t << " is found at position " << n << std::endl;
}
else
{
std::cout << "string " << t << " is not found" << std::endl;
}
return 0;
}
The output is
string me is found at position 7
For other strings I did not test the function.:)
For objects of type std::string you can call it like
size_t n = index_of( s.c_str(), t.c_str() );
Otherwise if you want to write a similar recursive function for objects of type std::string then you need either to add a static local variable that to keep the current position inside the source string or add one more parameter for index or use member function substr.
Also my advice is do not use manifest constant ZERO for zero. In my opinion it is a bad style of programming. It only confuses readers because ZERO can be anything including some user-defined class.
For example (without testing)
#include <iostream>
#include <string>
std::string::size_type index_of( const std::string &s, const std::string &t )
{
static std::string::size_type pos;
if ( s.size() < t.size() ) return std::string::npos;
if ( s.compare( pos, t.size(), t ) == 0 ) return 0;
++pos;
std::string::size_type n = index_of( s, t );
--pos;
return n == std::string::npos ? std::string::npos : n + 1;
}
int main()
{
std::string s = "Search me";
std::string t = "me";
std::string::size_type n = index_of( s, t );
if ( n != std::string::npos )
{
std::cout << "string " << t << " is found at position " << n << std::endl;
}
else
{
std::cout << "string " << t << " is not found" << std::endl;
}
return 0;
}
As for your function realization then it can look for example the following way
#include <iostream>
#include <string>
std::string::size_type index_of( const std::string &stringToSearchIn,
const std::string &stringToSearchFor,
std::string::size_type index )
{
if ( stringToSearchIn.length() < stringToSearchFor.length() + index )
{
return std::string::npos;
}
else if ( stringToSearchIn.compare( index,
stringToSearchFor.length(),
stringToSearchFor ) == 0 )
{
return index;
}
else
{
std::string::size_type n =
index_of( stringToSearchIn, stringToSearchFor, ++index );
return n == std::string::npos ? std::string::npos : n;
}
}
int main()
{
std::string s = "Search me";
std::string t = "me";
std::string::size_type n = index_of( s, t, 0 );
if ( n != std::string::npos )
{
std::cout << "string " << t << " is found at position " << n << std::endl;
}
else
{
std::cout << "string " << t << " is not found" << std::endl;
}
return 0;
}