length of sub-sequence in the string - c++

I need to implement lastSeq function,which gets as argument string str and char chr
and returns the length of last sequence of repeated chr (the sequence can be of any length)
for example:
lastSeq("abbaabbbbacd",'a') should return 1
lastSeq("abbaabbbbacd",'b') should return 4
lastSeq("abbaabbbbacd",'t') should return 0
Is there C++ function which can solve it?

This appear to be homework, so I'm just going to give you direction so that you can find the answer by yourself.
First, how would you do it yourself, without a computer to give the correct result for your samples. From those manual run, how would you generalize then in simple steps so that you can solve the problem for all different inputs.
By this point you should have a rough algorithm to solve the problem. What do you know about storage of string in C++, and the method that are available from that class? Can some one them be used to solve some of the steps of your algorithm?
Try to write a program using those function, to compile it and to run it. Do you get the expected result? If not, can you try to print intermediate state (using std::cout << "Some value: " << variable << "\n";) to try to debug it.
Once you have done all of that, and if you are still having issues, update your question with your code, and we'll be able to give you more directed help.

int lastSeq(char *str, char chr)
{
int i = strlen(str);
int l = 0;
while(--i>=0)
if(*(str + i) == chr && ++l)
break;
while(--i>=0 && chr == *(str + i) && ++l);
return l;
}

Related

Searching a function with the cctype library to find the number of characters that are digits in a range

Trying to solve one of the questions I was given by an instructor and I'm having trouble understanding how to call this properly.
I'm given a function that is linked to a test driver and my goal is to use the cstring library to find any numbers in the range of 0-9 in a randomly generated string object with this function.
int countDigits(char * const line) {return 0;}
So far this is what I have:
int countDigits(char * const line)
{
int i, index;
index = -1;
found = false;
i = 0;
while (i < *line && !found)
{
if (*line > 0 && *line < 9)
index++;
}
return 0;
}
My code not great and at the moment only results in an infinite loop and failure, any help would be very much appreciated.
Well, there are several problems with your function.
you want it to return the number of digits, but it returns 0 in any case
found is never set to anything than false and thus prohibits the while loop from stopping
also the comparison i<*line does not make much sense to me, I guess you want to check for the end of the line. Maybe you would want to look for a null termination "\0" (here again i is never set to anything else than 0)
and, if you want to compare single characters, you should look up the ASCII code of the characters you are comparing to (the digits 0-9 are not equal to codes 0-9)
Hope that is a start to improve your function.
There's a readymade for this called count_if:-
count_if(begin, end, [](char c){ return isdigit(c);});

Split a even-numbered string in c++

I am very new to c++. I am trying to split a string that contains even numbered sub strings till there is no even numbered sub string left. For example, if I input AB ABCD ABC, the output should be A B A B C D ABC. I am trying to do it without tokens, because I don't know how to..
What I have so far only split the first even sub string and it doesn't work if I only have 1 sub string. Can someone please help me out?
Any advise will be much appreciated. Thank you!
string temp = "";
void check(string &str, int &i, int &flag)
{
int count = 0;
int reminder;
do
{
count++;
temp += str[i];
i++;
} while (str[i] != ' ');
i = i - temp.size();
reminder = count % 2;
if (reminder == 0)
flag = 1;
else
flag = 0;
}
void SplitEvenWord(string &str)
{
int i = 0;
int flag = 0;
for (i = 0; i < str.size(); i++)
{
check(str, i, flag);
if (flag == 1)
{
temp.insert(temp.size() / 2, " ");
str.replace(i, temp.size() - 1, temp);
}
}
}
There are two skills that are absolutely vital in software engineering (Well, more than two, but two for now): developing new functions in isolation, and testing things in the simplest possible way.
You say that the code fails if there is only one substring. You don't say how it fails (I should have mentioned clear error reports in the list) so I don't know whether to test your code with an even-length string which it ought to split ("ABCD" => "A B C D") or an odd-length string which it ought to leave alone ("ABC" => "ABC"). Before I try to code these up, I look at your first function:
void check(string &str, int &i, int &flag)
{
...
do
{
count++;
temp += str[i];
i++;
} while (str[i] != ' ');
...
}
Trouble already. The strings I have in mind do not contain any spaces, so the loop cannot terminate. This code will run past the end of the string into whatever happens to be in that memory space, which will cause undefined behavior. (If you don't know that term, it means that there's no telling what will happen, but if you're lucky the program will just crash.)
Fix that, try running that code on "ABC" and "ABCD" and "A" and "" and "ABC DEF", and get it working perfectly. Once it does, take a look at your other function. Don't test it with random typing, test it with short, clearly defined strings. Once it works perfectly, try longer, more complicated ones. If you find a string which causes it to fail, hold onto it! That string will lead you to a bug.
That should be enough to get you started.
I'm writing this as an answer because it was too long to fit as a comment.
I have a couple of suggestions that may help you to figure out what the problem is.
Separate "check" into at least two functions, one to split the string into individual words and check them and one to check the length of the string.
Test the "check" and "tokenize" functions by separately and see if they give you the expected answers. Work on them individually until they are correct.
Separate the formatting of the answers out of "SplitEvenWord" into a separate function.
"SplitEvenWord" should then be nothing more than calling the functions you created as a result of the steps above.
When I'm stuck, I always try to break the problem down into small bite sized pieces that I know I can get working. Eventually, the problem becomes assembling the already working pieces of the solution into a larger function that solves the original problem.

extracting data between having { } any other method with good run time

I have this piece of code where am extracting the data between the { }, and this takes me around O(n) is there any other method which is more effcient
#include <iostream>
#include <string>
#include <stdio.h>
int main()
{
const char *blah = "[{post:banb {bbbbbbbb}: ananmsdb},{dsgdf{9090909090}fdgsdfg}";
std::string op;
unsigned int i = 0;
int im = 0;
int found = 0;
while(strlen(blah) != i){
if(blah[i] == '{'){
found = 1;
// copy what ever u got
op+=blah[i];
im++;
}
else if(blah[i] == '}'){
//copy wat ever u got
op+=blah[i];
im--;
}
if(found ==1){
//copy wat ever u got.
op+=blah[i];
}
if(found ==1 && im == 0) {
found = 0;
cout << op <<endl;
op.clear() ;
// u have found the full one post so send it for processing.
}
i++;
}
}
output :post:banb {bbbbbbbb}: ananmsdb
dsgdf{9090909090}fdgsdfg
No. You can use library functions to make this code shorter, but it will never be more efficient than O(n) where n is the length of the input string, since you need to examine each character at least once because each one could potentially be a token that you need to extract.
I don't think you can improve on O(n) for the underlying algorithm, but you can probably improve your implementation.
Currently your implementation may well be O(n^2) rather than O(n), as strlen() could be called on every iteration (unless your compiler is particularly smart). You should probably cache the call to strlen() explicitly, e.g. change:
while(strlen(blah) != i){
...
to:
const int len = strlen(blah);
while(len != i){
...
As everybody else has said there is no way to make this faster as you have to check every character incase you miss one.
But, this being said if perhaps you already knew some information about the data aka how many pairs of '{' and'}' then I can onlythink of one way(besides sorting but that brings it back to O(n) + etc).
This would be to choose indexes between 0 - x and randomly check at spots if you can find the '{' or '}'. Just to be clear this will only work if you know how many '{' and '}'s are already in the set of data.
Edit: Addtionally the copy you provided (just from using notepad) when it hits the first cout<< it should output "{{post:banb {{bbbbbbbb}}: ananmsdb}}", as its creating additional {'s and }'s.

creating a function to match a string in the main

This is a group assignment and it's become rather difficult to the point our professor has extended the project by 1 week. there are 50 stages/tests, we've only been able to reach up to stage 11 and then the function fails.
this function is in our .cpp file (we're positive it's this function causing the problem's because when we change parts of it, it affects stage 11 which we've passed).
int segment::match(const char word[]) {
int i;
cout << data[0];
data[0] == "OOP";
cout << data[0];
for(i=0;i<NUM_MAX;i++) {
cout << "word = " << &word[i] << " data[i] = " << data[i];
if(strstr(&word[i],data[i])!= NULL)
break;
}
return i==NUM_MAX ? 1 : i-1;
and from the main.cpp (provided to us as the assignment) this is the what we are trying to accomplish
Passed test 11...
Your match( ) return value ----> -1
Actual match( ) return value --> -1
Press the ENTER key to continue...
word = OOP data[i] =
Failed while testing the match( )
function... Failed on test 12...
Your match( ) return value ----> -1
Actual match( ) return value --> 1
Press the ENTER key to continue...
You passed 11/50 tests...
Your program is 22.00% complete!
Your program still needs some work!
Keep at it!
what the function is suppose to do is check for "oop" and if it isn't there it exits with -1, and if it is there it should return true with 1.
I guess what I'm asking is how do I make that function that it returns both -1 and 1 in the proper order?
If you would like access to the main.cpp and segement.cpp i can upload that as files somewhere because they're very long and I did not want to cram the post.
Any help is appreciated, thank you.
EDIT*
Here is the full code that we have
http://jsfiddle.net/h5aKN/
The "html" section has the segement.cpp which is what we built.
and the jscript section has the a2main.cpp which is what our professor built.
data[0] == "OOP"; is probably not what you want to do. The double = (==) tests for equality, so here you're testing if the item at the first index of data (data[0]) and the character string "OOP" are equal.
In the running of the test, you are cout'ing: word = OOP data[i] =, which means that word[i] is probably defined correctly, but data[i] is not. This goes back to the usage of the equivalence test above.
If you set initialize data correctly, (correctly meaning allocating the memory correctly, I don't know where data is instantiated), then the test would likely return -1, as it would get a non NULL pointer from the strstr() call (assuming that data is the correct type), i would be 0 on breaking, and the ternary operator would yield i-1, = -1.
So fix the initialization / assignment of the data variable
And if you're not limited to c style strings (char arrays), I'd use the std::string type and its associated methods (see the c++ string reference if you haven't already). Usually much nicer to work with
If you are passing a list of words to the function:
As the use of (strstr(&word[i],data[i])) suggests you are looking for a string inside another string. Thus you are looping over a list of strings (words).
Then this looks wrong:
int segment::match(const char word[]) {
Here you are passing one word.
Its impossable to tell what it should be, but a guess would be:
int segment::match(const char* word[]) {
// ^^^^^
But to be honest the whole thing is rather ugly C++. If you were writting C I would say fine, but if you had been writing C++ correctly the type system would have saved you from all these problems. Use std::string to represent words.

Fastest way to determine whether a string contains a real or integer value

I'm trying to write a function that is able to determine whether a string contains a real or an integer value.
This is the simplest solution I could think of:
int containsStringAnInt(char* strg){
for (int i =0; i < strlen(strg); i++) {if (strg[i]=='.') return 0;}
return 1;
}
But this solution is really slow when the string is long... Any optimization suggestions?
Any help would really be appreciated!
What's the syntax of your real numbers?
1e-6 is valid C++ for a literal, but will be passed as integer by your test.
Is your string hundreds of characters long? Otherwise, don't care about any possible performance issues.
The only inefficiency is that you are using strlen() in a bad way, which means a lot of iterations over the string (inside strlen). For a simpler solution, with the same time complexity (O(n)), but probably slightly faster, use strchr().
You are using strlen, which means you are not worried about unicode. In that case why to use strlen or strchr, just check for '\0' (Null char)
int containsStringAnInt(char* strg){
for (int i =0;strg[i]!='\0'; i++) {
if (strg[i]=='.') return 0;}
return 1; }
Only one parsing through the string, than parsing through the string in each iteration of the loop.
Your function does not take into account exponential notation of reals (1E7, 1E-7 are both doubles)
Use strtol() to try to convert the string to integer first; it will also return the first position in the string where the parsing failed (this will be '.' if the number is real). If the parsing stopped at '.', use strtod() to try to convert to double. Again, the function will return the position in the string where the parsing stopped.
Don't worry about performance, until you have profiled the program. Otherwise, for fastest possible code, construct a regular expression that describes acceptable syntax of numbers, and hand-convert it first into a FSM, then into highly optimized code.
So the standard note first, please don't worry about performance too much if not profiled yet :)
I'm not sure about the manual loop and checking for a dot. Two issues
Depending on the locale, the dot can actually be a "," too (here in Germany that's the case :)
As others noted, there is the issue with numbers like 1e7
Previously I had a version using sscanf here. But measuring performance showed that sscanf is is significantly slower for bigger data-sets. So I'll show the faster solution first (Well, it's also a whole more simple. I had several bugs in the sscanf version until I got it working, while the strto[ld] version worked the first try):
enum {
REAL,
INTEGER,
NEITHER_NOR
};
int what(char const* strg){
char *endp;
strtol(strg, &endp, 10);
if(*strg && !*endp)
return INTEGER;
strtod(strg, &endp);
if(*strg && !*endp)
return REAL;
return NEITHER_NOR;
}
Just for fun, here is the version using sscanf:
int what(char const* strg) {
// test for int
{
int d; // converted value
int n = 0; // number of chars read
int rd = std::sscanf(strg, "%d %n", &d, &n);
if(!strg[n] && rd == 1) {
return INTEGER;
}
}
// test for double
{
double v; // converted value
int n = 0; // number of chars read
int rd = std::sscanf(strg, "%lf %n", &v, &n);
if(!strg[n] && rd == 1) {
return REAL;
}
}
return NEITHER_NOR;
}
I think that should work. Have fun.
Test was done by converting test strings (small ones) randomly 10000000 times in a loop:
6.6s for sscanf
1.7s for strto[dl]
0.5s for manual looping until "."
Clear win for strto[ld], considering it will parse numbers correctly I will praise it as the winner over manual looping. Anyway, 1.2s/10000000 = 0.00000012 difference roughly for one conversion isn't all that much in the end.
Strlen walks the string to find the length of the string.
You are calling strlen with every pass of the loop. Hence, you are walking the string way many more times than necessary. This tiny change should give you a huge performance improvement:
int containsStringAnInt(char* strg){
int len = strlen(strg);
for (int i =0; i < len; i++) {if (strg[i]=='.') return 0;}
return 1;
}
Note that all I did was find the length of the string once, at the start of the function, and refer to that value repeatedly in the loop.
Please let us know what kind of performance improvement this gets you.
#Aaron, with your way also you are traversing the string twice. Once within strlen, and once again in for loop.
Best way for ASCII string traversing in for loop is to check for Null char in the loop it self. Have a look at my answer, that parses the string only once within for loop, and may be partial parsing if it finds a '.' prior to end. that way if a string is like 0.01xxx (anotther 100 chars), you need not to go till end to find the length.
#include <stdlib.h>
int containsStringAnInt(char* strg){
if (atof(strg) == atoi(strg))
return 1;
return 0;
}