Find count of character occurrences in array using recursion - c++

I'm pretty new with recursion. I need to write two functions. So far I wrote one, which entitles finding the length of a string. However, the second one, which is: finding the repeating character in an array is proving to be very difficult. I have scoured the web trying to find examples, I have been doing a lot of reading but nothing so far. So if you could point me in the right direction, I would really appreciate it.
Thank you
//length( ) -- this function is sent a null terminated array of characters.
//The function returns the length of the "string".
long slength (const char ntca[])
{
int length = 0;
if (ntca[length] == '\0'){
return 0;
}
else{
return slength(ntca+1)+1;
}
}
//countall( ) -- This function is sent a null terminated array of characters
//and a single character. The function returns the number of times the character
//appears in the array.
long countall (const char ntca[],char letter){
int position = 0;
int counter = 0;
long length = slength(ntca);
if (length == 0)
return 0;
else if (ntca[position]==letter)
return 1 + countall(ntca-1,letter);
else
return countall(ntca,letter);
}

You can try the below code:
long countall(const char *ptr, char letter)
{
if(!*ptr) return 0; //base case
return (*ptr == letter) + countall(ptr + 1, letter);
}
The base case of recursion is when function meets the end of the string. For an empty string and any letter the answer is 0.
If string is not empty, we add 1 to the result of recursive call on shorter string if and only if the current char matches letter.

Related

Length of longest consecutive characters in a string

I am trying to find the length of the longest consecutive character('!') in a string.
For example, input:
!!!!Hello!!
Output:
4
I am trying to solve this problem with recursion and this is my approach:
unsigned int length_of_longest_consecutive_dquotes(const char line[], int start)
{
if (line[start] != '\0') {
if (line[start] == '!') {
return length_of_longest_consecutive_mark(line,start+1) + 1;
}
else
return length_of_shortest_consecutive_mark(line,start+1);
}
return 0;
}
Where Start = 0; I am not able to figure out what shall I implement in the length_of_shortest_consecutive_dquotes(line,start) function.
Please suggest me some better algorithm for implementing it. Thanks!
At each iteration you have to remember the preceding parsed character, and then compare with the first of the remaining part of the array. If they are the same then add one to the length of the current possible longest sequence, if not length is 1 (the length of a new possible longest sequence). Of course you also have to remember the highest length.
Something like that?
#include <iostream>
unsigned int length_of_longest_consecutive(char previous,const char *line,int ll,int current_length)
{
if (*line==0) return ll>current_length?ll:current_length;
if (*line==previous) {
return length_of_longest_consecutive(*line,line+1,ll,current_length+1);
}
return length_of_longest_consecutive(*line,line+1,ll>current_length?ll:current_length,1);
}
int main() {
const char *a = "a!!!b!!!!ccccc!!d";
std::cout << length_of_longest_consecutive('\0',a,0,0) << std::endl;
}

Expression must have class type while using pointers

I am trying to count in a string1 how many times string2 exists. For example:
string1 = abababd.
string2 = ab.
Result: 3.
(I must use pointers for this question)
What I have so far:
int mystr(char* s, char* t) {
int counter = 0;
int length = strlen(t);
while (*s != '\0')
{
char d[] = *s.substr(0, 2);
if (*s == *t)
counter++;
*s += length;
}
return counter;
}
I keep receiving the issue:
Expression must have class type for this line: char d[] = *s.substr(0, 2);
Can someone assist please?
substr is a method of class std::string.
You are using C pointers here (char* s), so there is no substr() to call, thus the error.
Of course, I'll leave the implementation to you, but you can get inspired by create my own substr.
Since OP is showing good faith in trying to do their own HW, let's comment on the approach so far:
int mystr(char* s, char* t) {
int counter = 0;
int length = strlen(t);
// while we haven't reach the end of string
while (*s != '\0')
{
// this is not used anywhere, and it's wrong. Why 2? You want the length of `t` there, if you would use it anyway
char d[] = *s.substr(0, 2);
// this is wrong. It will increase the counter,
// every time a character of the substring is matched with the
// current character in the string
if (*s == *t)
counter++;
// you want to read the next chunk of the string, seems good for a start
*s += length;
}
return counter;
}
So now, you should focus on how to check if the current substring is matched in the string. So, you need to change this:
if (*s == *t)
counter++;
into something that will check all the characters of t, versus the same number of characters of the string, from current position. So, you need to iterate through *s. How many times? For as much as the length of t.
In that iteration, you would need to check that the current character of string s is the compared equal to the current character of string t. When the iteration ends, and if all characters visited during that iteration where the same, then that means that you found a match! So, if that is true, then we should increment the counter.
Bonus: If you have time, and have completed the logic discussed above, think about *s += length; and this input: `s = "dabababd", t = "ab".

C++, String to Array of Characters with my professor's limitations

I'm learning C++, and I have no idea how I'm supposed to do the following.
In an assignment, we need to write a function that checks if the first two characters of a string are the same as the last two.
These are the limitations:
You cannot use std::string class or string function such as strlen. You must use either array or pointer for this function.
I tried this:
bool haveTheSameTwoChars(string str) {
char arr[] = str;
if (sizeof(arr) < 3) {
return false;
}
else if (arr[0] == arr[sizeof(arr) - 3] && arr[1] == arr[sizeof(arr) - 2]) {
return true;
}
else {
return false;
}
}
But it won't accept str into the array.
However, if I were to put something in quotes in the place of str, it accepts it just fine, despite them both being strings.
What am I doing wrong?
Well, here's the breakdown of your problem:
You need to take input as an array or a pointer. For example:
bool isMatched( const char* str )
{
// ...
}
Now, you need to calculate the length of your string yourself. Revise the loops and devise something that gives you the length of a null terminated string. C-strings are null-terminated i.e. '\0' so you can end your loop when you encounter null character. For example:
int len = 0;
while ( str[len] != '\0' ) len++;
That's just an idea. Do your own research and calculate the string length correctly.
The rest is just a comparison of first and last two characters using if. :)
I'm sure you can put things together and revise your study material a bit to solve this.
Best of luck!
Happy coding!
When you're not allowed strlen, it is a strong hint that the problem can be solved without caring about the length of the string.
Let's do that:
First, you should have the prototype (no strings allowed, right?)
bool haveTheSameTwoChars(const char* str)
Then, verify that the string has at least two characters
if (!str || !str[0] || !str[1])
return false;
Then you find the end of the string:
const char* end = str;
while (*end)
end++;
Then move back two characters, so end points to the first of the last two characters:
end -= 2;
(This is safe since we first checked that there are at least two characters.)
Then compare
return str[0] == end[0] && str[1] == end[1];
Your professor wants you to use a const char* as the function parameter, that is, model a string as a pointer to the first character in the string, where the string finishes with a 0. (We call this NUL-termination).
So your function is
bool haveTheSameTwoChars(const char* s)
You then need to roll your own version of strlen1 to calculate the number of characters in the string up to and not including the NUL:
#include <cstddef> // for std::size_t
std::size_t strlen(const char *s) {
const char *p = s;
while (*s) ++s;
return s - p;
}
After which, it's a simple case, given the length l say, of dealing with a couple of edge cases and the general case:
If l is 0 or 1, return false.
If l is 2, return true.
If l is greater than 2 then something similar to how you have it in the question will suffice, remembering that my l is one less than yours.
Note that C++ does not support variable length arrays, so char arr[] = str; is not valid C++, and sizeof is a compile-time operator so would only give you the size of an actual array type, not an array that's decayed to a pointer type.
1 No professional programmer would dream of doing that. A compiler might optimise strlen down to a machine word-based algorithm, i.e. consider multiple bytes simultaneously.
Here is some sample code for your purpose
bool haveTheSameTwoChars(const char* p) {
if(!p || !*p)
return false;
int len = -1;
while(p[++len]);
if(p[0] == p[len-2] &&
p[1] == p[len-1])
return true;
return false;
}
This will return true if the string is "ABxxxAB" and false if "ABxxxBA". Rest you can tweak according to your desire.Thanks
Another approach uses a loop and a single pointer to iterate over each line saving the first and second characters to compare against the next to last (penultimate) and last (ultimate) characters in the string.
By using simple iteration over the character array, as long as it is nul-terminated, you don't have to worry about a separate loop to find the length, you simply grab/save the first two characters, and then iterate to the end of your string saving the prev/last characters as you go. When you hit the end of your string, all you need to do is compare the first against the last and the second against the next to last, e.g.
/* function iterates pointer through chars in 'line' saving
* the 1st & 2nd chara in 'beg` and 'next' and the penultimate and
* ultimate characters in 'prev' & 'last' and compares. returns 1 if
* 1st matches ultimate AND 2nd matches penultimate, 0 otherwise.
*/
int begmatchend (const char *line)
{
const char *p = line; /* pointer to line */
char beg = *p++, /* save for 1st char */
next = *p++, /* save for 2nd char */
prev = *p++, /* save for next to last char */
last = *p++; /* save for last char */
while (*p) { /* iterate over line setting prev/last as you go */
prev = last;
last = *p++;
}
if (beg == last && next == prev) /* test whether equal */
return 1;
return 0;
}
Then for a simple test, you can just feed your programs lines from a file calling begmatchend on each line and then output indication of which lines matched. Something simple like the following is one way:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstddef>
#define MAXC 1024
/* function iterates pointer through chars in 'line' saving
* the 1st & 2nd chara in 'beg` and 'next' and the penultimate and
* ultimate characters in 'prev' & 'last' and compares. returns 1 if
* 1st matches ultimate AND 2nd matches penultimate, 0 otherwise.
*/
int begmatchend (const char *line)
{
const char *p = line; /* pointer to line */
char beg = *p++, /* save for 1st char */
next = *p++, /* save for 2nd char */
prev = *p++, /* save for next to last char */
last = *p++; /* save for last char */
while (*p) { /* iterate over line setting prev/last as you go */
prev = last;
last = *p++;
}
if (beg == last && next == prev) /* test whether equal */
return 1;
return 0;
}
int main (int argc, char **argv) {
char line[MAXC] = "";
size_t n = 0;
std::ifstream f (argc > 1 ? argv[1] : "/dev/stdin");
if (!f.is_open()) {
std::cerr << "error: file open failed.\n";
return 1;
}
while (f.getline (line, MAXC, '\n')) {
if (begmatchend ((const char *)line))
std::cout << "line[" << std::setw(3) << n <<
"] 1st/ultimate matched, 2nd/penultimate matched.\n";
n++;
}
return 0;
}
Example Input
$ cat dat/linesbegend.txt
all good vikings go to valhalla
be a tide that will flow and eb
a quick brown fox jumps over the lazy dog
we can find the begin and end - eew
Example Use/Output
$ ./bin/beg_end_match dat/linesbegend.txt
line[ 0] 1st/ultimate matched, 2nd/penultimate matched.
line[ 1] 1st/ultimate matched, 2nd/penultimate matched.
line[ 3] 1st/ultimate matched, 2nd/penultimate matched.
Look things over and let me know if you have any questions.

How return position of pointer in function of searching substrings in strings?

Help please how to finish function.
I got exersize for develop function for searching substring in string and return first position of enter.
That is code what i made:
int strstr(const char *str, const char *pattern) {
const char *st = str; // assign adress of string to pointer
const char *pa = pattern; //assign adress of pattern what we must find in string to pointer
while (*st){ // starting sort out string
++st;
if( *st == *pa){ //when first symbol of pattern equal to symbol of string starting the loop
int i = 0; //counter of iteration for possibility to return first enter of substring
for(i;*st == *pa;i++){ //that loop sort out every next symbol of string and pattern for equality
++st;
++pa;
} //loop finish when pattern or string was ended, or any next symbol was not equal
if(*pa == 0){ //if patter was ended return position of first enter
return st-i; //there not compiling((
}
pa-i; //reset pattern
st-i; //reset string
}
}
return -1; //return -1, if substring was not find
}
For hard luck that code not compiling... Error is invalid conversion from ‘const char*’ to ‘int’
What type must be variable i for that? And check my logic please)
return st-i; //there not compiling((
You are returning a pointer to a constant char, where your function requires to return an integer. My best guess is you need to change it into:
return *(st-i)
Use the * to dereference the pointer into the const char object, which is interchangeable with int
The problem is that your function is currentlu defined to return an int.
If you desire to return an int, such as the relative position from the beginning of your string, then you have to return a difference between pointers
return (st-i)-str; // st-i = begin of the pattern found, - str for the relative position
If you desire to return a pointer, then your function signature shall be changed and you should return nullptr instead of -1 when you didn't fin the patter.
Several other minor issues:
incrementing st before starting comparison risk to miss the pattern if the string starts with it.
pa-i and st-i are without effect: it's just expressions, no change is stored. Maybe you wanted to write pa-=i ?
Try the following. At least it looks simpler.:)
#include <iostream>
int strstr( const char *str, const char *pattern )
{
bool found = false;
const char *p = str;
for ( ; *p && !found; ++p )
{
size_t i = 0;
while ( p[i] == pattern[i] && pattern[i] != '\0' ) ++i;
found = pattern[i] == '\0';
}
return found ? --p - str : -1;
}
int main()
{
std::cout << ::strstr( "Hello evsign", "evsign" ) << std::endl;
return 0;
}
The output is
6
As for your code then even the first statement in the loop is wrong
while (*st){ // starting sort out string
++st;
Why is st increased?
Also this loop
for(i;*st == *pa;i++){
shall be written as
for( ;*st == *pa && *pa; i++){

What is wrong with this recursive code?

I am doing online work using CodeLab for C++ and am not sure what's wrong with my code. Here is the question:
Write a recursive, int-valued function, len, that accepts a string and returns the number of characters in the string.
The length of a string is:
0 if the string is the empty string ("").
1 more than the length of the rest of the string beyond the first character.
And here's my code:
int len(string s)
{
if (s.length()==0)
return 0;
else
{
return 1+(len(s)-1);
}
}
It says I have a run-time error.
Any help?
Thanks.
Well here:
return 1+(len(s)-1);
The length of the string never decreases. So you will eventually have a stackoverflow because you never hit your base case (s.length() == 0). You need to get a substring where the length of s decreases by 1:
return 1+(len(s.erase(0,1))); // erases 1 char from beginning then recurses
Hopefully this is purely academic, because std::string has a length method that will run in constant time. (Not to mention erasing from the front of a string is probably horribly inefficient-- see the other answers that work with char *)
You are never modifying s in your code, so if s is not empty you keep calling the same function and again, with the same parameter; your never stop. Your computer runs out of stack space and the program crashes.
Others have given you some ideas/options. Here's mine suggestion:
int len(const std::string &s, int start)
{
/* If we are starting at the end, there's no more length */
if(start == s.length())
return 0;
/* one plus whatever else... */
return 1 + len(s, start + 1);
}
Assuming str is the string you want to get the length of, you can call it as: len(str, 0)
If you need to use a const char * version try this:
int len(const char *s)
{
if((s == NULL) || (*s == 0))
return 0; /* we ran out of string! */
return 1 + len(s + 1);
}
len(s) will never decrease and cause a stackoverflow. I would do something like:
int len(const char * s) {
if(*s == '\0')
return 0;
else
return 1 + len(s+1);
}
Another solution:
int len(string s)
{
if (s.length()==0)
return 0;
else
{
s = s.substr(0, s.size()-1);
return 1+(len(s));
}
}