/* Write a program that would mix-and-merge two given strings (s1 and s2) into string s3 as follows:
first character of s1, first character of s2, second character of s1, second character of s2, etc. */
But the problem with my code is: that if i type for s1 "John" and then for s2 "Stevens"
Result will be = JSothenv e n s.
How do i fix the spaces that are left after one of the strings ends?
The way i thought i would fix it is i would check with the ifs i have below in the for loop To see if the index is null or '\0' but that doesn't work as the string holds random values after the string ends.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1, s2;
string s3;
int i; // For index
int j = 0; // For second index and loop checking
cout << "Type first string: ";
getline(cin, s1);
cout << "Type second string: ";
getline(cin, s2);
s3.resize(s1.size() + s2.size() + 100); // The + 100 is used so we have space for all the characters. The + 100 is not needed if i fix my problem.
for(i = 0; j <= s1.size(); i += 2)
{
if(s1[j] == null) // With what do i check it?
{
break;
}
else
{
s3[i] = s1[j];
++j;
}
}
j = 0;
for(i = 1; j <= s2.size(); i += 2)
{
if(s2[j] == null)
{
break;
}
else
{
s3[i] = s2[j];
}
++j;
}
for( i = 0; i <= s3.size(); ++i)
{
cout << s3[i];
}
return 0;
Try this:
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char const *argv[])
{
string s1, s2, s3;
int i,j,k;
cout << "Type first string: ";
getline(cin, s1);
cout << "Type second string: ";
getline(cin, s2);
s3.resize(s1.size()+s2.size());
for(i = 0, j = 0, k = 0; j < s1.size() && k < s2.size(); i++) {
if(i & 1) {
s3[i] = s2[k++];
} else {
s3[i] = s1[j++];
}
}
if(j == s1.size()) {
while(k < s2.size()) {
s3[i++] = s2[k++];
}
} else {
while(j < s1.size()) {
s3[i++] = s1[j++];
}
}
cout << s3 << endl;
return 0;
}
You can replace the code after getline with this:
string::const_iterator i1 = s1.begin(), i2 = s2.begin();
bool useFirst = true;
while (i1 != s1.end() || i2 != s2.end())
{
if (useFirst && i1 != s1.end())
{
s3.push_back(*i1++);
}
else if (i2 != s2.end())
{
s3.push_back(*i2++);
}
useFirst = !useFirst; // switch over for next iteration
}
cout << s3 << endl;
It's a bit simpler, and basically iterates alternately over the two strings until they're both exhausted.
It's quite simple to write a generic interleave algorithm that iterates over both ranges once:
template<typename InputIterator1, typename InputIterator2, typename OutputIterator>
OutputIterator interleave(InputIterator1 first1, InputIterator1 end1,
InputIterator2 first2, InputIterator2 end2,
OutputIterator out)
{
while(first1 != end1 && first2 != end2)
{
out = *first1;
out = *first2;
++first1;
++first2;
}
// copy remaining elements from both ranges
while(first1 != end1)
{
out = *first1;
++first1;
}
while(first2 != end2)
{
out = *first2;
++first2;
}
return out;
}
Live demo here. Usage is like std::set_merge:
interleave(begin(s1), end(s1),
begin(s2), end(s2),
std::back_inserter(result));
It iterates over both ranges until one runs out, then copies the remaining elements in both ranges. Iterates once over both containers and has one double end check I couldn't get rid of without assuming one range to be larger than the other. Can handle two different containers now
Related
I have this function that checks if a string is a substring, is it possible for me to add a variable to it that will count to me how many times that subsequence appears in that sequence? or i need to create another function for that.
bool SearchString(string sir1, string sir2) {
if (sir2.size() > sir1.size())
return false;
for (int i = 0; i < sir1.size(); i++) {
int j = 0;
if (sir1[i] == sir2[j]) {
int k = i;
while (sir1[i] == sir2[j] && j < sir2.size()) {
j++;
i++;
}
if (j == sir2.size())
return true;
else
i = k;
}
}
return false;
}
As "500 - Internal Server Error" said, you simply need to increment a counter where you return. With a little bit of refactoring it would look like this:
unsigned SearchString(const string& haystack, const string& needle) {
if (needle.size() > haystack.size())
return 0;
unsigned count = 0;
for (int i = 0; i < haystack.size(); ++i) {
int j = 0;
if (haystack[i] == needle[j]) {
int k = i;
while (k < haystack.size() && j < needle.size() && haystack[k] == needle[j]) {
++j;
++k;
}
if (j == needle.size())
++count;
}
}
return count;
}
Note: it's important to check that you haven't reached the end of the haystack while searching for the needle. Consider haystack="ababa", needle="bac": trying to locate 'c' would read after the end of the haystack
It's also important to check reaching end before trying to dereference the next character:
while (sir1[i] == sir2[j] && j < sir2.size()) ...
would read sir2[j] before making sure j is not over the boundary.
For starters your function SearchString is too complicated and moreover can invoke undefined behavior in this loop
while (sir1[i] == sir2[j] && j < sir2.size()) {
j++;
i++;
}
if for example when the string s2 contains an imbedded zero character '\0'.
Also the function parameters should have constant referenced types.
The function can be written much simpler.
As for your question then it will be better to write a separate function to count occurrences of a sub-string.
That is there is no great sense to count all occurrences of a sub-string in a string if you need only to know whether the sub-string is present in the string.
Here is a demonstration program
#include <iostream>
#include <iomanip>
#include <string>
bool SearchString( const std::string &s1, const std::string &s2 )
{
return s1.find( s2 ) != std::string::npos;
}
size_t CountStringOccurrences( const std::string &s1, const std::string &s2 )
{
size_t n = 0;
for ( std::string::size_type pos = 0;
s1.find( s2, pos ) != std::string::npos;
pos += s2.size() )
{
++n;
}
return n;
}
int main()
{
std::string s1( "123123123" );
std::string s2( "123" );
std::cout << std::boolalpha << SearchString( s1, s2 ) << '\n';
std::cout << CountStringOccurrences( s1, s2 ) << '\n';
return 0;
}
The program output is
true
3
This sounds like std::search as in
bool SearchString(const std::string& s0, const std::string& s1) {
return std::search(s0.begin(), s0.end(), s1.begin(), s1.end()) != s0.end();
}
Counting would be a loop:
std::size_t count = 0;
for (auto it = std::search(s0.begin(), s0.end(), s1.begin(), s1.end());
it != s0.end();
it = std::search(it, s0.end(), s1.begin(), s1.end())) {
++count;
}
or perhaps clearer: pull out the duplication:
std::size_t count = 0;
auto search = [&](auto start) { return std::search(start, s0.end(), s1.begin(), s1.end()); };
for (auto it = search(s0.begin()); it != s0.end();
it = search(it)) {
++count;
}
I bet there’s a way to do it with std::ranges::count_if but I don’t see it.
In this question, we take 2 strings as input say s1 and s2.
Now, first we need to check if s2 is a subsequence of s1. If not, print no.
But if it is, we need to print the minimum number of characters to be deleted from s1 to get s2.
Eg- thistext text
Here, text can be directly found without deleting any characters so the answer is 0.
Eg- cutefriendship crisp
In this case, the answer is 9.
What I've done so far,
#include <bits/stdc++.h>
using namespace std;
int checkIfSub(string s1, string s2, int m, int n)
{
int j = 0;
for(int i = 0; i < m && j < n; i++)
if(s1[i] == s2[j])
j++;
if(j == n)
return 0;
else
return 1;
}
int check(string s1, string s2)
{
int count = 0; string s3;
if(checkIfSub(s1, s2, s1.length(), s2.length()) == 1 || s2.length() > s1.length())
{
cout << "NO\n"; return 0;
}
int j = 0;
for(int i = 0; i < s1.length(); i++)
{
if(s1[i] == s2[j])
{
s3[j] = s1[j];
j++; continue;
}
count++;
}
cout << "YES " << count << "\n";
return 0;
}
int main() {
string s1, s2;
cin >> s1 >> s2;
check(s1, s2);
return 0;
}
My code works well for the second example, but fails the first case.
(This was a question asked in some interview I read online.)
Try something like this:
#include <iostream>
#include <string>
using namespace std;
bool check(const string &s1, const string &s2, int &minToDelete)
{
minToDelete = 0;
bool anySubSeqFound = false;
if (s2.empty())
return false;
string::size_type first = 0;
while ((first = s1.find(s2[0], first)) != string::npos)
{
int numDeleted = 0;
bool isSubSeq = true;
string::size_type next = first + 1;
for(string::size_type j = 1; j < s2.size(); ++j)
{
string::size_type found = s1.find(s2[j], next);
if (found == string::npos)
{
isSubSeq = false;
break;
}
numDeleted += (found - next);
next = found + 1;
}
if (isSubSeq)
{
if (anySubSeqFound)
{
if (numDeleted < minToDelete)
minToDelete = numDeleted;
}
else
{
anySubSeqFound = true;
minToDelete = numDeleted;
}
}
++first;
}
return anySubSeqFound;
}
int main()
{
int minToDelete;
if (check("thistext", "text", minToDelete))
cout << "yes, delete " << minToDelete << endl;
else
cout << "no" << endl;
if (check("cutefriendship", "crisp", minToDelete))
cout << "yes, delete " << minToDelete << endl;
else
cout << "no" << endl;
}
Live Demo
I need to create a program that allows a user to input a string and my program will check to see if that string they entered is a palindrome (word that can be read the same backwards as it can forwards).
Note that reversing the whole string (either with the rbegin()/rend() range constructor or with std::reverse) and comparing it with the input would perform unnecessary work.
It's sufficient to compare the first half of the string with the latter half, in reverse:
#include <string>
#include <algorithm>
#include <iostream>
int main()
{
std::string s;
std::cin >> s;
if( equal(s.begin(), s.begin() + s.size()/2, s.rbegin()) )
std::cout << "is a palindrome.\n";
else
std::cout << "is NOT a palindrome.\n";
}
demo: http://ideone.com/mq8qK
Just compare the string with itself reversed:
string input;
cout << "Please enter a string: ";
cin >> input;
if (input == string(input.rbegin(), input.rend())) {
cout << input << " is a palindrome";
}
This constructor of string takes a beginning and ending iterator and creates the string from the characters between those two iterators. Since rbegin() is the end of the string and incrementing it goes backwards through the string, the string we create will have the characters of input added to it in reverse, reversing the string.
Then you just compare it to input and if they are equal, it is a palindrome.
This does not take into account capitalisation or spaces, so you'll have to improve on it yourself.
bool IsPalindrome(const char* psz)
{
int i = 0;
int j;
if ((psz == NULL) || (psz[0] == '\0'))
{
return false;
}
j = strlen(psz) - 1;
while (i < j)
{
if (psz[i] != psz[j])
{
return false;
}
i++;
j--;
}
return true;
}
// STL string version:
bool IsPalindrome(const string& str)
{
if (str.empty())
return false;
int i = 0; // first characters
int j = str.length() - 1; // last character
while (i < j)
{
if (str[i] != str[j])
{
return false;
}
i++;
j--;
}
return true;
}
// The below C++ function checks for a palindrome and
// returns true if it is a palindrome and returns false otherwise
bool checkPalindrome ( string s )
{
// This calculates the length of the string
int n = s.length();
// the for loop iterates until the first half of the string
// and checks first element with the last element,
// second element with second last element and so on.
// if those two characters are not same, hence we return false because
// this string is not a palindrome
for ( int i = 0; i <= n/2; i++ )
{
if ( s[i] != s[n-1-i] )
return false;
}
// if the above for loop executes completely ,
// this implies that the string is palindrome,
// hence we return true and exit
return true;
}
#include <iostream>
#include <string>
bool isPalindrome(const std::string& str){
if(str.empty()) return true;
std::string::const_iterator itFirst = str.begin();
std::string::const_iterator itLast = str.end() - 1;
while(itFirst < itLast) {
if (*itFirst != *itLast)
return false;
++itFirst;
--itLast;
}
return true;
}
int main(){
while(1){
std::string input;
std::cout << "Eneter a string ...\n";
std::cin >> input;
if(isPalindrome(input)){
std::cout << input << " is palindrome.\n";
} else {
std::cout << input << " is not palindrome.\n";
}
}
return 0;
}
Check the string starting at each end and meet in the middle. Return false if there is a discrepancy.
#include <iostream>
bool palidromeCheck(std::string str) {
for (int i = 0, j = str.length()-1; i <= j; i++, j--)
if (str[i] != str[j])
return false;
return true;
}
int main(){
std::cout << palidromeCheck("mike");
std::cout << palidromeCheck("racecar");
}
Reverse the string and check if original string and reverse are same or not
I'm no c++ guy, but you should be able to get the gist from this.
public static string Reverse(string s) {
if (s == null || s.Length < 2) {
return s;
}
int length = s.Length;
int loop = (length >> 1) + 1;
int j;
char[] chars = new char[length];
for (int i = 0; i < loop; i++) {
j = length - i - 1;
chars[i] = s[j];
chars[j] = s[i];
}
return new string(chars);
}
I need to create a program that allows a user to input a string and my program will check to see if that string they entered is a palindrome (word that can be read the same backwards as it can forwards).
Note that reversing the whole string (either with the rbegin()/rend() range constructor or with std::reverse) and comparing it with the input would perform unnecessary work.
It's sufficient to compare the first half of the string with the latter half, in reverse:
#include <string>
#include <algorithm>
#include <iostream>
int main()
{
std::string s;
std::cin >> s;
if( equal(s.begin(), s.begin() + s.size()/2, s.rbegin()) )
std::cout << "is a palindrome.\n";
else
std::cout << "is NOT a palindrome.\n";
}
demo: http://ideone.com/mq8qK
Just compare the string with itself reversed:
string input;
cout << "Please enter a string: ";
cin >> input;
if (input == string(input.rbegin(), input.rend())) {
cout << input << " is a palindrome";
}
This constructor of string takes a beginning and ending iterator and creates the string from the characters between those two iterators. Since rbegin() is the end of the string and incrementing it goes backwards through the string, the string we create will have the characters of input added to it in reverse, reversing the string.
Then you just compare it to input and if they are equal, it is a palindrome.
This does not take into account capitalisation or spaces, so you'll have to improve on it yourself.
bool IsPalindrome(const char* psz)
{
int i = 0;
int j;
if ((psz == NULL) || (psz[0] == '\0'))
{
return false;
}
j = strlen(psz) - 1;
while (i < j)
{
if (psz[i] != psz[j])
{
return false;
}
i++;
j--;
}
return true;
}
// STL string version:
bool IsPalindrome(const string& str)
{
if (str.empty())
return false;
int i = 0; // first characters
int j = str.length() - 1; // last character
while (i < j)
{
if (str[i] != str[j])
{
return false;
}
i++;
j--;
}
return true;
}
// The below C++ function checks for a palindrome and
// returns true if it is a palindrome and returns false otherwise
bool checkPalindrome ( string s )
{
// This calculates the length of the string
int n = s.length();
// the for loop iterates until the first half of the string
// and checks first element with the last element,
// second element with second last element and so on.
// if those two characters are not same, hence we return false because
// this string is not a palindrome
for ( int i = 0; i <= n/2; i++ )
{
if ( s[i] != s[n-1-i] )
return false;
}
// if the above for loop executes completely ,
// this implies that the string is palindrome,
// hence we return true and exit
return true;
}
#include <iostream>
#include <string>
bool isPalindrome(const std::string& str){
if(str.empty()) return true;
std::string::const_iterator itFirst = str.begin();
std::string::const_iterator itLast = str.end() - 1;
while(itFirst < itLast) {
if (*itFirst != *itLast)
return false;
++itFirst;
--itLast;
}
return true;
}
int main(){
while(1){
std::string input;
std::cout << "Eneter a string ...\n";
std::cin >> input;
if(isPalindrome(input)){
std::cout << input << " is palindrome.\n";
} else {
std::cout << input << " is not palindrome.\n";
}
}
return 0;
}
Check the string starting at each end and meet in the middle. Return false if there is a discrepancy.
#include <iostream>
bool palidromeCheck(std::string str) {
for (int i = 0, j = str.length()-1; i <= j; i++, j--)
if (str[i] != str[j])
return false;
return true;
}
int main(){
std::cout << palidromeCheck("mike");
std::cout << palidromeCheck("racecar");
}
Reverse the string and check if original string and reverse are same or not
I'm no c++ guy, but you should be able to get the gist from this.
public static string Reverse(string s) {
if (s == null || s.Length < 2) {
return s;
}
int length = s.Length;
int loop = (length >> 1) + 1;
int j;
char[] chars = new char[length];
for (int i = 0; i < loop; i++) {
j = length - i - 1;
chars[i] = s[j];
chars[j] = s[i];
}
return new string(chars);
}
Given 2 strings, design a function that can check whether they are rotations to each other without making any changes on them ? The return value is boolean.
e.g ABCD, ABDC, they are not rotations. return false
ABCD, CDAB or DABC are rotations. return true.
My solution:
shift one of them to right or left one position and then compare them at each iteration.
If they are not equal at all iterations, return false. Otherwise, return true.
It is O(n). Are there other more efficient solutions ?
What if the contents of them cannot be changed ?
thanks
Concatenate the given string with the given string.
Search for the target string in the concatenated string.
Example:
Given = CDAB
After step 1, Concatenated = CDABCDAB
After step 2, Success CDABCDAB
^^^^
Rather than shifting one of them, it might be more efficient to use two index variables. Start one at 0 each time and the other at each of the possible positions (0 to N-1) and increment it mod N.
If you can't modify the strings, just take the first character of string1 and compare it to each character of string2. When you get a match, compare the second char of string1 to the next char of string2, and so on.
Pseudocode:
len = strlen(string1);
len2 = strlen(string2);
if( len != len2 )
printf("Nope.");
for( int i2=0; i2 < len; i2++ ) {
for( int i1=0; i1<len; i1++ ) {
if( string1[i1] != string2[(i2+i1)%len] )
break;
}
if( i1 == len ) {
print("Yup.");
break;
}
}
A simple one would be:
(s1+s1).find(s2) != string::npos && s1.size() == s2.size();
#include <iostream>
#include <cstring>
#include<string>
using namespace std;
void CompareString(string, string, int);
int ComputeStringLength(string str);
int main()
{
string str = ""; string str1 = ""; int len = 0, len1 = 0;
cout << "\nenter string ";
cin >> str;
cout << "\nenter string 2 to compare:- ";
cin >> str1;
len = ComputeStringLength(str);
len1 = ComputeStringLength(str1);
if (len == len1)
CompareString(str, str1, len);
else
cout << "rotation not possible";
getchar();
return 0;
}
int ComputeStringLength(string str)
{
int len = 0;
for (int i = 0; str[i] != '\0'; i++)
{
len++;
}
return len;
}
void CompareString(string str, string str1, int n)
{
int index = 0, flag = 0, curr_index = 0, count1 = 0, flagj = 0;
for (int i = 0; i<n; i++)
{
for (int j = flagj; j<n; j++)
{
if (str[i] == str1[j])
{
index = j;
flagj =j;
count1++;
flag++;
if (flag == 1)
{
curr_index = index;
}
break;
}
}
}
int temp = count1;
if (count1 != n)
{
if (curr_index>=0)
{
int k = 0;
for (int i = n - 1; i>n - curr_index - 1; i--)
{
if (str[i] == str1[k])
{
temp++;
k++;
}
}
}
if (temp == n)
{
cout << "\n\nstring is same after rotation";
}
else
{
cout << "\n\nstring is not same after rotation";
}
}
else
{
cout << "\n\nstring is same after rotation";
}
}
https://dsconceptuals.blogspot.in/2016/10/a-program-to-check-if-strings-are.html