use a string or stream? - c++

I need to progressively build a string and am trying to find the best way to do it. The maximum it can grow to is about 10k and hence was planning to do something like this:
const unsigned long long configSize = 10240; //Approximation
void makeMyConfig() {
std::string resp;
std::string input;
resp.reserve(configSize);
while ( getInput(input) ) {
resp += input;
}
if ( resp.length > configSize )
log << "May need to adjust configSize. Validate" << endl;
if (!sendConfig(resp)){
log << "Error sending config" << endl;
}
}
getInput may read from file/tcp conn or ftp and is decided at runtime. It receives const char* and puts it into a string (which I may be able to avoid but left it for convenience)
However, I heard there is a much efficient way of doing with string streams but not sure how to do. Appreciate any insights.

Looks pretty great to me.
You're pre-allocating the buffer, avoiding ongoing allocations and copies.
You already have it implemented
Don't optimize until you actually have a performance problem and can measure any performance changes. You might end up making it worse without realizing!

For anyone interested in the difference between reserving and not reserving a string, consider this code:
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
const int BIG = 10000000;
const int EXTRA = 100;
int main() {
string s1;
s1.reserve( BIG );
clock_t t = clock();
for ( int i = 0; i < BIG + EXTRA; i++ ) {
s1 += 'x';
}
cout << clock() - t << endl;
string s2;
t = clock();
for ( int i = 0; i < BIG + EXTRA; i++ ) {
s2 += 'x';
}
cout << clock() - t << endl;
}
In the first case, the string is reserved, in the second not. This produces the timings:
60
78
for g++ compiled with -O2.

Related

C++ duration_cast<>(time_point_end - tine_point_start). count() overflows

What I want to do, my project:
I want to make a program that waits 0.5 seconds, for example, does something, let's say cout << "Hello World", once and then again the same for about 10 times(this is a test for another program), but without sleep, sleep_for, sleep or anything similar BCS I don't want the processor to actually sleep, BCS at that time the processor does not just wait, it does nothing for that time, for these 0.5 seconds it does nothing and I don't want that, and the main reason is BCS it also doesn't take input.
What I tried:
What I tried was to keep two points in time(time_point start,end), duration_cast their difference (end - start) in a for loop ((int i = 0;i < 10;i++)), and if their difference was 500 milliseconds, then, cout << "Hello World\n";.
My code looked something like this:
#include <iostream>
#include <chrono>
#include <ctime>
using namespace std;
using namespace chrono;
int main()
{
time_point<steady_clock> t = steady_clock::now():
for (int i = 0; i < 10;)
{
duration<double> d = steady_clock::now() - t;
uint32_t a = duration_cast<milliseconds>(d).count();
if (a >= 500)
{
cout << a << " Hello World!" << endl;
t = steady_clock::now();
i++;
}
}
return 0;
}
My problem:
It overflows, most of the time, I don't know what exactly overflows, but a appears to be sometimes 6??? others 47??? (? = some digit)
I tried many things, I ended up to something like this:
#include <iostream>
#include <chrono>
#include <ctime>
using namespace std;
using namespace chrono;
int main()
{
time_point<high_resolution_clock> t = high_resolution_clock::now();
for (int i = 0; i< 10;)
{
duration<double,ratio<1,1000000>> d = high_resolution_clock::now() - t;
uint32_t a = duration_cast<microseconds>(d).count();
if (d >= microseconds(500000) )
{
cout << a << " Hello World!" << endl;
i++;
t = high_resolution_clock::now();
}
}
return 0;
}
It didn't really solve the problem, but the max value appears is `~1500(1500000 in microseconds) and when it happens it takes longer to print the message, I don't know if its still overflow, to be honest, but...
Question
Anyway, do you have any suggestions about how to stop the overflow or a completely different way to achieve what I want, even if you don't, thanks for spending time to read my question, I hope to express someone else's question if there someone who has the same question as me.
Not sure if this is what you're looking for or not. But if not, maybe we can build on this to figure out what you want:
#include <chrono>
#include <iostream>
int
main()
{
using namespace std;
using namespace std::chrono;
auto t = steady_clock::now();
for (int i = 0; i < 10; ++i)
{
auto t1 = t + 500ms;
while (steady_clock::now() < t1)
;
cout << duration<double>(t1-t).count() << " Hello World!" << endl;
t = t1;
}
}
The code sets a time_point for 500ms in the future, and then enters a busy loop until that future time_point is now.

Optimizing .txt files creation speed

I've written the following simple testing code, that creates 10 000 empty .txt files in a subdirectory.
#include <iostream>
#include <time.h>
#include <string>
#include <fstream>
void CreateFiles()
{
int i = 1;
while (i <= 10000) {
int filename = i;
std::string string_i = std::to_string(i);
std::string file_dir = ".\\results\\"+string_i+".txt";
std::ofstream outfile(file_dir);
i++;
}
}
int main()
{
clock_t tStart1 = clock();
CreateFiles();
printf("\nHow long it took to make files: %.2fs\n", (double)(clock() - tStart1)/CLOCKS_PER_SEC);
std::cin.get();
return 0;
}
Everything works fine. All 10 000 .txt files are created within ~3.55 seconds. (using my PC)
Question 1: Ignoring the conversion from int to std::string etc., is there anything that I could optimize here for the program to create the files faster? I specifically mean the std::ofstream outfile usage - perhaps using something else would be relevantly faster?
Regardless, ~3,55 seconds is satisfying compared to the following:
I have modified the function so right now it would also fill the .txt files with some random i integer data and some constant text:
void CreateFiles()
{
int i = 1;
while (i <= 10000) {
int filename = i;
std::string string_i = std::to_string(i);
std::string file_dir = ".\\results\\"+string_i+".txt";
std::ofstream outfile(file_dir);
// Here is the part where I am filling the .txt with some data
outfile << i << " some " << i << " constant " << i << " text " << i << " . . . "
<< i << " --more text-- " << i << " --even more-- " << i;
i++;
}
}
And now everything (creating the .txt files and filling it with short data) executes within... ~37 seconds. That's a huge difference. And that's only 10 000 files.
Question 2: Is there anything I can optimize here? Perhaps there exist some alternative that would fill the .txt files quicker. Or perhaps I have forgotten about something very obvious that slows down the entire process?
Or, perhaps I am exaggerating a little bit and ~37 seconds seems normal and optimized?
Thanks for sharing your insights!
The speed of creation of file is hardware dependent, faster the drive faster you can create the files.
This is evident from the fact that I ran your code on an ARM processor (Snapdragon 636, on a Mobile phone using termux), now mobile phones have flash memory that are very fast when it comes to I/O. So it ran under 3 seconds most of the time and some time 5 second. This variation is expected as drive has to handle multi process read writes. You reported that it took 47 seconds for your hardware. Hence you can safely conclude that I/O speed is significantly dependent on Hardware.
None the less I thought to do some optimization to your code and I used 2 different approaches.
Using a C counterpart for I/O
Using C++ but writing in a chunk in one go.
I ran the simulation on my phone. I ran it 50 times and here are the results.
C was fastest taking 2.73928 second on average to write your word on 10000 text files, using fprintf
C++ writing with the complete line at one go took 2.7899 seconds. I used sprintf to get the complete line into a char[] then wrote using << operator on ofstream.
C++ Normal (Your Code) took 2.8752 seconds
This behaviour is expected, writing in chunks is fasters. Read this answer as to why. C was fastest no doubt.
You may note here that The difference is not that significant but if you are on a hardware with slow I/O, this becomes significant.
Here is the code I used for simulation. You can test it yourself but make sure to replace std::system argument with your own commands (different for windows).
#include <iostream>
#include <time.h>
#include <string>
#include <fstream>
#include <stdio.h>
void CreateFiles()
{
int i = 1;
while (i <= 10000) {
// int filename = i;
std::string string_i = std::to_string(i);
std::string file_dir = "./results/"+string_i+".txt";
std::ofstream outfile(file_dir);
// Here is the part where I am filling the .txt with some data
outfile << i << " some " << i << " constant " << i << " text " << i << " . . . "
<< i << " --more text-- " << i << " --even more-- " << i;
i++;
}
}
void CreateFilesOneGo(){
int i = 1;
while(i<=10000){
std::string string_i = std::to_string(i);
std::string file_dir = "./results3/" + string_i + ".txt";
char buffer[256];
sprintf(buffer,"%d some %d constant %d text %d . . . %d --more text-- %d --even more-- %d",i,i,i,i,i,i,i);
std::ofstream outfile(file_dir);
outfile << buffer;
i++;
}
}
void CreateFilesFast(){
int i = 1;
while(i<=10000){
// int filename = i;
std::string string_i = std::to_string(i);
std::string file_dir = "./results2/"+string_i+".txt";
FILE *f = fopen(file_dir.c_str(), "w");
fprintf(f,"%d some %d constant %d text %d . . . %d --more text-- %d --even more-- %d",i,i,i,i,i,i,i);
fclose(f);
i++;
}
}
int main()
{
double normal = 0, one_go = 0, c = 0;
for (int u=0;u<50;u++){
std::system("mkdir results results2 results3");
clock_t tStart1 = clock();
CreateFiles();
//printf("\nNormal : How long it took to make files: %.2fs\n", (double)(clock() - tStart1)/CLOCKS_PER_SEC);
normal+=(double)(clock() - tStart1)/CLOCKS_PER_SEC;
tStart1 = clock();
CreateFilesFast();
//printf("\nIn C : How long it took to make files: %.2fs\n", (double)(clock() - tStart1)/CLOCKS_PER_SEC);
c+=(double)(clock() - tStart1)/CLOCKS_PER_SEC;
tStart1 = clock();
CreateFilesOneGo();
//printf("\nOne Go : How long it took to make files: %.2fs\n", (double)(clock() - tStart1)/CLOCKS_PER_SEC);
one_go+=(double)(clock() - tStart1)/CLOCKS_PER_SEC;
std::system("rm -rf results results2 results3");
std::cout<<"Completed "<<u+1<<"\n";
}
std::cout<<"C on average took : "<<c/50<<"\n";
std::cout<<"Normal on average took : "<<normal/50<<"\n";
std::cout<<"One Go C++ took : "<<one_go/50<<"\n";
return 0;
}
Also I used clang-7.0 as the compiler.
If you have any other approach let me know, I will test that too. If you find a mistake do let me know, I will correct it as soon as possible.

What's the fastest way in C++ to concat a list of variables in different types to a comma separated string?

string A = "test";
double B = 123.45;
float C = 43.23;
char D = 'c';
Trying to join them to product a string string res = "test,123.45,43.23,c". What is the fastest way?
ostringstream is good, but seems not fast enough.
you can always use the C way:
char outbuf[256];
sprintf(outbuf, "%s,%3.2d,%2.2f,%c", A.c_str(), B, C, D);
note that the line I wrote is highly specific; because you didn't precise anything about the format for the doubles, floats, string length,...
Your problem consists of two tasks:
convert the variables to strings
concatenate the strings to a single string.
The second step can be sped up by reserving some memory using std::string::reserve(). Normally std::string will have to reallocate memory several times when repeatedly appending to the end. This can be avoided if the size of the resulting string is known ahead of time. std::string::reserve() then can be used to tell std::string about it so that it can reduce the calls to reallocate the memory which may significantly improve performance for long strings.
I do not know the fastest way. I simply know how it can be done in C++.:)
Here is a demonstrative program that shows two approaches
#include <iostream>
#include <string>
#include <sstream>
int main()
{
std::string A = "test";
double B = 123.45;
float C = 43.23;
char D = 'c';
std::string res1 = A + ',' + std::to_string( B ) + ',' +
std::to_string( C ) + ',' + D;
std::cout << res1 << std::endl;
std::ostringstream is;
is << A << ',' << B << ',' << C << ',' << D;
std::string res2 = is.str();
std::cout << res2 << std::endl;
return 0;
}
The program output is
test,123.450000,43.230000,c
test,123.45,43.23,c
So you can select what you like.:)
To make the methods faster you should reserve enough memory for strings using member function reserve.
I think ostringstream is a very good methods, "seems not fast enough" may be not so important unless you have a lot of numbers and strings to cat.
maybe [sprintf][1] http://www.cplusplus.com/reference/cstdio/sprintf/
is a alterative, I think this may be faster if you know the length of the result:
you make a new char[length] at the beginning.
For example:
char * buffer = new char[LENGTH];
int a = 1;
double b = 2.0;
string c = "3.0";
int n = sprintf(buffer, "%d plus %f is %s", a, b, c.c_str());
In Addition, snprintf is suggested because it is more safe
Under Visual Studio 2013, sprintf is two times faster than ostringstream (measured in release). The reason is probably because ostringstream does a lot of allocations, I have used _CrtSetAllocHook and it is triggered 74 times for below code sample, while it is not even once triggered for sprintf - this was measured in debug.
ps. stringstream can be customized, you can write your own custom buffer which will be optimal for your needs.
#include <Windows.h>
#include <iostream>
#include <sstream>
struct TimeMe {
ULONG64 start;
TimeMe() {
QueryThreadCycleTime(GetCurrentThread(), &start);
}
ULONG64 total() {
ULONG64 end;
QueryThreadCycleTime(GetCurrentThread(), &end);
return (end - start);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
std::string A = "test";
double B = 123.45;
float C = 43.23;
char D = 'c';
char outbuf[256];
std::ostringstream is;
ULONG64 sum=0;
for ( int k = 0; k < 100; ++k ) {
TimeMe me;
// ~8800 ticks
//is.str("");
//is.clear();
//is << A << ',' << B << ',' << C << ',' << D;
//std::string res2 = is.str();
// ~4500 ticks
sprintf(outbuf, "%s,%3.2lf,%2.2f,%c", A.c_str(), B, C, D);
sum += me.total();
}
std::cout << "CPU ticks: " << (sum)/100 << std::endl;
return 0;
}

How to truncate a string [formating] ? c++

I want to truncate a string in a cout,
string word = "Very long word";
int i = 1;
cout << word << " " << i;
I want to have as an output of the string a maximum of 8 letters
so in my case, I want to have
Very lon 1
instead of :
Very long word 1
I don't want to use the wget(8) function, since it will not truncate my word to the size I want unfortunately. I also don't want the 'word' string to change its value ( I just want to show to the user a part of the word, but keep it full in my variable)
I know you already have a solution, but I thought this was worth mentioning: Yes, you can simply use string::substr, but it's a common practice to use an ellipsis to indicate that a string has been truncated.
If that's something you wanted to incorporate, you could just make a simple truncate function.
#include <iostream>
#include <string>
std::string truncate(std::string str, size_t width, bool show_ellipsis=true)
{
if (str.length() > width)
if (show_ellipsis)
return str.substr(0, width) + "...";
else
return str.substr(0, width);
return str;
}
int main()
{
std::string str = "Very long string";
int i = 1;
std::cout << truncate(str, 8) << "\t" << i << std::endl;
std::cout << truncate(str, 8, false) << "\t" << i << std::endl;
return 0;
}
The output would be:
Very lon... 1
Very lon 1
As Chris Olden mentioned above, using string::substr is a way to truncate a string. However, if you need another way to do that you could simply use string::resize and then add the ellipsis if the string has been truncated.
You may wonder what does string::resize? In fact it just resizes the used memory (not the reserved one) by your string and deletes any character beyond the new size, only keeping the first nth character of your string, with n being the new size. Moreover, if the new size is greater, it will expand the used memory of your string, but this aspect of expansion is straightforward I think.
Of course, I don't want to suggest a 'new best way' to do it, it's just another way to truncate a std::string.
If you adapt the Chris Olden truncate function, you get something like this:
#include <iostream>
#include <string>
std::string& truncate(std::string& str, size_t width, bool show_ellipsis=true) {
if (str.length() > width) {
if (show_ellipsis) {
str.resize(width);
return str.append("...");
}
else {
str.resize(width);
return str;
}
}
return str;
}
int main() {
std::string str = "Very long string";
int i = 1;
std::cout << truncate(str, 8) << "\t" << i << std::endl;
std::cout << truncate(str, 8, false) << "\t" << i << std::endl;
return 0;
}
Even though this method does basically the same, note that this method takes and returns a reference to the modified string, so be careful with it since this string could be destroyed because of an external event in your code. Thus if you don't want to take that risk, just remove the references and the function becomes:
std::string truncate(std::string str, size_t width, bool show_ellipsis=true) {
if (str.length() > width) {
if (show_ellipsis) {
str.resize(width);
return str + "...";
}
else {
str.resize(width);
return str;
}
}
return str;
}
I know it's a little bit late to post this answer. However it might come in handy for future visitors.

Check if a string contains a string in C++

I have a variable of type std::string. I want to check if it contains a certain std::string. How would I do that?
Is there a function that returns true if the string is found, and false if it isn't?
Use std::string::find as follows:
if (s1.find(s2) != std::string::npos) {
std::cout << "found!" << '\n';
}
Note: "found!" will be printed if s2 is a substring of s1, both s1 and s2 are of type std::string.
You can try using the find function:
string str ("There are two needles in this haystack.");
string str2 ("needle");
if (str.find(str2) != string::npos) {
//.. found.
}
Starting from C++23 you can use std::string::contains
#include <string>
const auto haystack = std::string("haystack with needles");
const auto needle = std::string("needle");
if (haystack.contains(needle))
{
// found!
}
Actually, you can try to use boost library,I think std::string doesn't supply enough method to do all the common string operation.In boost,you can just use the boost::algorithm::contains:
#include <string>
#include <boost/algorithm/string.hpp>
int main() {
std::string s("gengjiawen");
std::string t("geng");
bool b = boost::algorithm::contains(s, t);
std::cout << b << std::endl;
return 0;
}
You can try this
string s1 = "Hello";
string s2 = "el";
if(strstr(s1.c_str(),s2.c_str()))
{
cout << " S1 Contains S2";
}
In the event if the functionality is critical to your system, it is actually beneficial to use an old strstr method. The std::search method within algorithm is the slowest possible. My guess would be that it takes a lot of time to create those iterators.
The code that i used to time the whole thing is
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <random>
#include <chrono>
std::string randomString( size_t len );
int main(int argc, char* argv[])
{
using namespace std::chrono;
const size_t haystacksCount = 200000;
std::string haystacks[haystacksCount];
std::string needle = "hello";
bool sink = true;
high_resolution_clock::time_point start, end;
duration<double> timespan;
int sizes[10] = { 10, 20, 40, 80, 160, 320, 640, 1280, 5120, 10240 };
for(int s=0; s<10; ++s)
{
std::cout << std::endl << "Generating " << haystacksCount << " random haystacks of size " << sizes[s] << std::endl;
for(size_t i=0; i<haystacksCount; ++i)
{
haystacks[i] = randomString(sizes[s]);
}
std::cout << "Starting std::string.find approach" << std::endl;
start = high_resolution_clock::now();
for(size_t i=0; i<haystacksCount; ++i)
{
if(haystacks[i].find(needle) != std::string::npos)
{
sink = !sink; // useless action
}
}
end = high_resolution_clock::now();
timespan = duration_cast<duration<double>>(end-start);
std::cout << "Processing of " << haystacksCount << " elements took " << timespan.count() << " seconds." << std::endl;
std::cout << "Starting strstr approach" << std::endl;
start = high_resolution_clock::now();
for(size_t i=0; i<haystacksCount; ++i)
{
if(strstr(haystacks[i].c_str(), needle.c_str()))
{
sink = !sink; // useless action
}
}
end = high_resolution_clock::now();
timespan = duration_cast<duration<double>>(end-start);
std::cout << "Processing of " << haystacksCount << " elements took " << timespan.count() << " seconds." << std::endl;
std::cout << "Starting std::search approach" << std::endl;
start = high_resolution_clock::now();
for(size_t i=0; i<haystacksCount; ++i)
{
if(std::search(haystacks[i].begin(), haystacks[i].end(), needle.begin(), needle.end()) != haystacks[i].end())
{
sink = !sink; // useless action
}
}
end = high_resolution_clock::now();
timespan = duration_cast<duration<double>>(end-start);
std::cout << "Processing of " << haystacksCount << " elements took " << timespan.count() << " seconds." << std::endl;
}
return 0;
}
std::string randomString( size_t len)
{
static const char charset[] = "abcdefghijklmnopqrstuvwxyz";
static const int charsetLen = sizeof(charset) - 1;
static std::default_random_engine rng(std::random_device{}());
static std::uniform_int_distribution<> dist(0, charsetLen);
auto randChar = [charset, &dist, &rng]() -> char
{
return charset[ dist(rng) ];
};
std::string result(len, 0);
std::generate_n(result.begin(), len, randChar);
return result;
}
Here i generate random haystacks and search in them the needle. The haystack count is set, but the length of strings within each haystack is increased from 10 in the beginning to 10240 in the end. Most of the time the program spends actually generating random strings, but that is to be expected.
The output is:
Generating 200000 random haystacks of size 10
Starting std::string.find approach
Processing of 200000 elements took 0.00358503 seconds.
Starting strstr approach
Processing of 200000 elements took 0.0022727 seconds.
Starting std::search approach
Processing of 200000 elements took 0.0346258 seconds.
Generating 200000 random haystacks of size 20
Starting std::string.find approach
Processing of 200000 elements took 0.00480959 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00236199 seconds.
Starting std::search approach
Processing of 200000 elements took 0.0586416 seconds.
Generating 200000 random haystacks of size 40
Starting std::string.find approach
Processing of 200000 elements took 0.0082571 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00341435 seconds.
Starting std::search approach
Processing of 200000 elements took 0.0952996 seconds.
Generating 200000 random haystacks of size 80
Starting std::string.find approach
Processing of 200000 elements took 0.0148288 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00399263 seconds.
Starting std::search approach
Processing of 200000 elements took 0.175945 seconds.
Generating 200000 random haystacks of size 160
Starting std::string.find approach
Processing of 200000 elements took 0.0293496 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00504251 seconds.
Starting std::search approach
Processing of 200000 elements took 0.343452 seconds.
Generating 200000 random haystacks of size 320
Starting std::string.find approach
Processing of 200000 elements took 0.0522893 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00850485 seconds.
Starting std::search approach
Processing of 200000 elements took 0.64133 seconds.
Generating 200000 random haystacks of size 640
Starting std::string.find approach
Processing of 200000 elements took 0.102082 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00925799 seconds.
Starting std::search approach
Processing of 200000 elements took 1.26321 seconds.
Generating 200000 random haystacks of size 1280
Starting std::string.find approach
Processing of 200000 elements took 0.208057 seconds.
Starting strstr approach
Processing of 200000 elements took 0.0105039 seconds.
Starting std::search approach
Processing of 200000 elements took 2.57404 seconds.
Generating 200000 random haystacks of size 5120
Starting std::string.find approach
Processing of 200000 elements took 0.798496 seconds.
Starting strstr approach
Processing of 200000 elements took 0.0137969 seconds.
Starting std::search approach
Processing of 200000 elements took 10.3573 seconds.
Generating 200000 random haystacks of size 10240
Starting std::string.find approach
Processing of 200000 elements took 1.58171 seconds.
Starting strstr approach
Processing of 200000 elements took 0.0143111 seconds.
Starting std::search approach
Processing of 200000 elements took 20.4163 seconds.
If the size of strings is relatively big (hundreds of bytes or more) and c++17 is available, you might want to use Boyer-Moore-Horspool searcher (example from cppreference.com):
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
int main()
{
std::string in = "Lorem ipsum dolor sit amet, consectetur adipiscing elit,"
" sed do eiusmod tempor incididunt ut labore et dolore magna aliqua";
std::string needle = "pisci";
auto it = std::search(in.begin(), in.end(),
std::boyer_moore_searcher(
needle.begin(), needle.end()));
if(it != in.end())
std::cout << "The string " << needle << " found at offset "
<< it - in.begin() << '\n';
else
std::cout << "The string " << needle << " not found\n";
}
If you don't want to use standard library functions, below is one solution.
#include <iostream>
#include <string>
bool CheckSubstring(std::string firstString, std::string secondString){
if(secondString.size() > firstString.size())
return false;
for (int i = 0; i < firstString.size(); i++){
int j = 0;
// If the first characters match
if(firstString[i] == secondString[j]){
int k = i;
while (firstString[i] == secondString[j] && j < secondString.size()){
j++;
i++;
}
if (j == secondString.size())
return true;
else // Re-initialize i to its original value
i = k;
}
}
return false;
}
int main(){
std::string firstString, secondString;
std::cout << "Enter first string:";
std::getline(std::cin, firstString);
std::cout << "Enter second string:";
std::getline(std::cin, secondString);
if(CheckSubstring(firstString, secondString))
std::cout << "Second string is a substring of the frist string.\n";
else
std::cout << "Second string is not a substring of the first string.\n";
return 0;
}
Good to use std::regex_search also. Stepping stone for making the search more generic. Below is an example with comments.
//THE STRING IN WHICH THE SUBSTRING TO BE FOUND.
std::string testString = "Find Something In This Test String";
//THE SUBSTRING TO BE FOUND.
auto pattern{ "In This Test" };
//std::regex_constants::icase - TO IGNORE CASE.
auto rx = std::regex{ pattern,std::regex_constants::icase };
//SEARCH THE STRING.
bool isStrExists = std::regex_search(testString, rx);
Need to include #include <regex>
For some reason, suppose the input string is observed something like "Find Something In This Example String", and interested to search either "In This Test" or "In This Example" then the search can be enhanced by simply adjusting the pattern as shown below.
//THE SUBSTRING TO BE FOUND.
auto pattern{ "In This (Test|Example)" };
what about
string response = "hello world";
string findMe = "world";
if(response.find(findMe) != string::npos)
{
//found
}
#include <algorithm> // std::search
#include <string>
using std::search; using std::count; using std::string;
int main() {
string mystring = "The needle in the haystack";
string str = "needle";
string::const_iterator it;
it = search(mystring.begin(), mystring.end(),
str.begin(), str.end()) != mystring.end();
// if string is found... returns iterator to str's first element in mystring
// if string is not found... returns iterator to mystring.end()
if (it != mystring.end())
// string is found
else
// not found
return 0;
}
From so many answers in this website I didn't find out a clear answer so in 5-10 minutes I figured it out the answer myself.
But this can be done in two cases:
Either you KNOW the position of the sub-string you search for in the string
Either you don't know the position and search for it, char by char...
So, let's assume we search for the substring "cd" in the string "abcde", and we use the simplest substr built-in function in C++
for 1:
#include <iostream>
#include <string>
using namespace std;
int i;
int main()
{
string a = "abcde";
string b = a.substr(2,2); // 2 will be c. Why? because we start counting from 0 in a string, not from 1.
cout << "substring of a is: " << b << endl;
return 0;
}
for 2:
#include <iostream>
#include <string>
using namespace std;
int i;
int main()
{
string a = "abcde";
for (i=0;i<a.length(); i++)
{
if (a.substr(i,2) == "cd")
{
cout << "substring of a is: " << a.substr(i,2) << endl; // i will iterate from 0 to 5 and will display the substring only when the condition is fullfilled
}
}
return 0;
}
This is a simple function
bool find(string line, string sWord)
{
bool flag = false;
int index = 0, i, helper = 0;
for (i = 0; i < line.size(); i++)
{
if (sWord.at(index) == line.at(i))
{
if (flag == false)
{
flag = true;
helper = i;
}
index++;
}
else
{
flag = false;
index = 0;
}
if (index == sWord.size())
{
break;
}
}
if ((i+1-helper) == index)
{
return true;
}
return false;
}
You can also use the System namespace.
Then you can use the contains method.
#include <iostream>
using namespace System;
int main(){
String ^ wholeString = "My name is Malindu";
if(wholeString->ToLower()->Contains("malindu")){
std::cout<<"Found";
}
else{
std::cout<<"Not Found";
}
}
Note: I know that the question requires a function, which means the user is trying to find something simpler. But still I post it in case anyone finds it useful.
Approach using a Suffix Automaton. It accepts a string (haystack), and after that you can input hundreds of thousands of queries (needles) and the response will be very fast, even if the haystack and/or needles are very long strings.
Read about the data structure being used here: https://en.wikipedia.org/wiki/Suffix_automaton
#include <bits/stdc++.h>
using namespace std;
struct State {
int len, link;
map<char, int> next;
};
struct SuffixAutomaton {
vector<State> st;
int sz = 1, last = 0;
SuffixAutomaton(string& s) {
st.assign(s.size() * 2, State());
st[0].len = 0;
st[0].link = -1;
for (char c : s) extend(c);
}
void extend(char c) {
int cur = sz++, p = last;
st[cur].len = st[last].len + 1;
while (p != -1 && !st[p].next.count(c)) st[p].next[c] = cur, p = st[p].link;
if (p == -1)
st[cur].link = 0;
else {
int q = st[p].next[c];
if (st[p].len + 1 == st[q].len)
st[cur].link = q;
else {
int clone = sz++;
st[clone].len = st[p].len + 1;
st[clone].next = st[q].next;
st[clone].link = st[q].link;
while (p != -1 && st[p].next[c] == q) st[p].next[c] = clone, p = st[p].link;
st[q].link = st[cur].link = clone;
}
}
last = cur;
}
};
bool is_substring(SuffixAutomaton& sa, string& query) {
int curr = 0;
for (char c : query)
if (sa.st[curr].next.count(c))
curr = sa.st[curr].next[c];
else
return false;
return true;
}
// How to use:
// Execute the code
// Type the first string so the program reads it. This will be the string
// to search substrings on.
// After that, type a substring. When pressing enter you'll get the message showing the
// result. Continue typing substrings.
int main() {
string S;
cin >> S;
SuffixAutomaton sa(S);
string query;
while (cin >> query) {
cout << "is substring? -> " << is_substring(sa, query) << endl;
}
}
We can use this method instead.
Just an example from my projects.
Refer the code.
Some extras are also included.
Look to the if statements!
/*
Every C++ program should have an entry point. Usually, this is the main function.
Every C++ Statement ends with a ';' (semi-colon)
But, pre-processor statements do not have ';'s at end.
Also, every console program can be ended using "cin.get();" statement, so that the console won't exit instantly.
*/
#include <string>
#include <bits/stdc++.h> //Can Use instead of iostream. Also should be included to use the transform function.
using namespace std;
int main(){ //The main function. This runs first in every program.
string input;
while(input!="exit"){
cin>>input;
transform(input.begin(),input.end(),input.begin(),::tolower); //Converts to lowercase.
if(input.find("name") != std::string::npos){ //Gets a boolean value regarding the availability of the said text.
cout<<"My Name is AI \n";
}
if(input.find("age") != std::string::npos){
cout<<"My Age is 2 minutes \n";
}
}
}