Check a string in another string in C++ - c++

#include <iostream>
#include <string>
using namespace std;
int main() {
string str_1 = "Gandalf";
string str_2 = "dal";
for (int i = 0; i <= str_1.length() - 2; i++)
for (int j = 0; j <= str_2.length(); j++) {
if (str_2[j] == str_1[i]) {
if (str_2[j + 1] == str_1[i + 1]) {
if (str_2[j + 2] == str_1[i + 2])
cout << "true";
}
}
}
return 0;
}
I can do it but if length of str_2 is 4 characters, program doesn't work.
I want that program can work for every length of string
but how?

The function find below basically reproduces the behaviour of std::string::find (without the starting position parameter). You need to:
loop through the outer string, and at each step:
loop through the second string checking each character.
If any of these fail, drop back to the outer loop.
If we make it all the way through the inner loop, then the second string is there, and return the current position in the outer loop.
If we run out of space in the first string, just skip the rest.
Hopefully the comments make this clear. I also include a little utility function to turn the found position into true/false, and some tests.
#include <iomanip>
#include <iostream>
#include <string>
std::string::size_type find(const std::string& s1,
const std::string& s2)
// return the position of s2 within s1,
// else npos if it is not present.
{
using size_type = std::string::size_type;
size_type curPos = 0;
size_type lim = s1.size();
size_type innerLim = s2.size();
for (; curPos<lim; ++curPos) { // loop through s1
if (lim < curPos+innerLim) {
break; // not enough space left
}
size_type innerPos = 0;
for(; innerPos < innerLim // loop through s2, while matching
&& curPos + innerPos < lim
&& s1[innerPos+curPos] == s2[innerPos];
++innerPos) ; // do nothing in the loop
if (innerPos == innerLim) { // matched the whole loop
return curPos;
}
}
return std::string::npos; // never matched
}
bool contains(const std::string& s1,
const std::string& s2)
{
return find(s1, s2)!=std::string::npos;
}
int main()
{
std::cout
<< std::boolalpha
<< contains("abc", "") << '\n' // true
<< contains("abc", "abc") << '\n' // true
<< contains("abc", "bc") << '\n' // true
<< contains("abc", "abcd") << '\n' // false
<< contains("abc", "abd") << '\n' // false
<< contains("abc", "xyz") << '\n';// false
}
This does more than what you really need, but it most closely models the "real" answer (use the facilities the language provides). Plus it makes it not a great homework answer, but contains all the clues to write your homework answer.

You could try something like this:
for (int i = 0; i < str_1.length() - str_2.length(); i++) {
bool is_same = true;
for (int j = 0; j < str_2.length(); j++) {
if (str[i + j] != str_2[j]) {
is_same = false;
break;
}
}
if (is_same) {
std::cout << "true" << std:endl;
}
}
It iterates over every character in str_1 and checks whether the character sequence starting at that point is the same as str_2.

Related

Getting "Exited with return code -11(SIGSEGV)" when attempting to run my code

#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<string> separate(string str){
string build = "";
vector<string> temp;
for(int i = 0;i < str.size(); i++){
if(str[i] != ' '){
build += str[i];
} else if(str[i] == ' '){
temp.push_back(build);
build = "";
}
}
return temp;
}
int main() {
int count;
string sentence;
vector<int> numTimes;
getline(cin, sentence);
vector<string> words = separate(sentence);
for(int i = 0; i < words.size(); i++){
for(int j = 0; j < words.size(); i++){
if(words[i] == words[j]){
count++;
}
}
numTimes.push_back(count);
}
for(int k = 0; k < words.size(); k++){
cout << words[k] << " - " << numTimes[k] << endl;
}
return 0;
}
The code is supposed to receive a string, separate it into the individual words, place those words into a vector and finally output the number of times the word occurs in the sentence. However when running my code, I get a message saying that the program was exited with code -11. I have looked a bit online but do not fully understand what this means or where it is occurring in my code.
Changed signed counter variables (i, j) to unsigned (size_t) as you compare the two. In separate(..) changed if-else-if to just if-else, and fixed the loop per #user4581301 to use the right loop variable. Also fixed last word not being added. Minor reformat to use tab/8 space for indent.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<string> separate(string str) {
string build = "";
vector<string> temp;
for(size_t i = 0; i < str.size(); i++) {
if(str[i] == ' ') {
temp.push_back(build);
build = "";
} else {
build += str[i];
}
}
if(build.size()) {
temp.push_back(build);
}
return temp;
}
int main() {
int count = 0;
string sentence;
vector<int> numTimes;
getline(cin, sentence);
vector<string> words = separate(sentence);
for(size_t i = 0; i < words.size(); i++) {
for(size_t j = 0; j < words.size(); j++) {
if(words[i] == words[j]) {
count++;
}
}
numTimes.push_back(count);
}
for(size_t k = 0; k < words.size(); k++) {
cout << words[k] << " - " << numTimes[k] << endl;
}
return 0;
}
This seems to fix the segfault which answers question posed.
You haven't provided sample input and output but the counts clearly seems wrong. What do you mean with sentence? There is no notion of English sentences ending with '.' or whatever:
./a.out
a bc d
a - 1
bc - 2
d - 3
./a.out
a a b
a - 2
a - 4
b - 5
Suggest you work on that and open new question if you need further help.
#Allan Wind is right, but to offer an alternate solution using the C++17 standard.
Iterating
Rather than use indexes, let's use a more modern for loop.
for (const char &ch : s)
Rather than:
for (size_t i = 0; i < str.size(); i++)
After all, the index is not important in this situation.
Dealing with multiple spaces
Right now, both the OP's code and Allan's will push an empty string onto the output vector whenever they encounter more than one contiguous space. We can correct that by resetting the string to empty when a space is encountered, but when a space is encountered and the string is empty, don't take any action.
We also need to check if the string is non-empty when the loop is finished. If so, we need to push that onto the output vector. We may not get a trailing space to trigger pushing that last word.
vector<string> separate(string s) {
vector<string> output;
string current = "";
for (const char &ch : s) {
if (current != "" && ch == ' ') {
output.push_back(current);
current = "";
}
else if (ch == ' ') {
// Do nothing!
}
else {
current += ch;
}
}
if (current != "") {
output.push_back(current);
}
return output;
}
Putting it together so far
#include <string>
#include <vector>
#include <iostream>
using namespace std;
vector<string> separate(string s);
int main() {
auto v = separate("hello world foo");
for (auto i : v) {
cout << i << endl;
}
}
vector<string> separate(string s) {
vector<string> output;
string current = "";
for (const char &ch : s) {
if (current != "" && ch == ' ') {
output.push_back(current);
current = "";
}
else if (ch == ' ') {
// Do nothing!
}
else {
current += ch;
}
}
if (current != "") {
output.push_back(current);
}
return output;
}
Counting words
We can use a map to count the occurrences of words. We use a map<string, int> where each word is the key, and the val is the occurrences. As we iterate over the words, if the word already exists as a key in the map, we increment it by `. If not, we set it to 1.
int main() {
auto v = separate("hello world hello world foo");
map<string, int> m;
for (auto i : v) {
if (m[i]) {
m[i] += 1;
}
else {
m[i] = 1;
}
}
for (auto const& [key, val] : m) {
cout << "The word \"" << key << "\" occurs "
<< val << " times." << endl;
}
}

Why does the first and second case keep returning false when both the original and reversed strings are the same? Palindrome code

Why does the function return false for the first and second words when they are both palindromes? The reversed text should be the same as the original.
#include <iostream>
#include <string>
// Define is_palindrome() here:
bool is_palindrome(std::string text) {
std::string reversed = "";
for (int i = text.size(); i >= 0; i--) {
reversed.push_back(text[i]);
}
if (reversed == text) {
return true;
}
else {
return false;
}
}
int main() {
std::cout << is_palindrome("madam") << "\n";
std::cout << is_palindrome("ada") << "\n";
std::cout << is_palindrome("lovelace") << "\n";
}
Your array bounding is incorrect. In C++ indices begin at 0 so the highest index of your array will be text.size() - 1 Try this instead:
for (int i = text.size() - 1; i >= 0; i--) {
reversed.push_back(text[i]);
}
For starters the function parameter should be constant referenced type
bool is_palindrome( const std::string &text ) {
In this loop
for (int i = text.size(); i >= 0; i--) {
reversed.push_back(text[i]);
}
when i is initially equal to text.size() when you are accessing a non-actual element of the string. According to the C++ 11 Standard it is equal to '\0'.
Also it is a bad idea to use the signed type int as the type of the index instead of the unsigned type std::string::size_type.
Moreover there is no need to create a copy of the whole string to determine whether the given string is a palindrome. This is just a bad approach because it is inefficient.
The function can be defined the following way
bool is_palindrome( const std::string &s )
{
std::string::size_type i = 0, n = s.size();
while ( i < n / 2 && s[i] == s[n - i - 1] ) ++i;
return i == n / 2;
}
Here is a demonstrative program.
#include <iostream>
#include <iomanip>
#include <string>
bool is_palindrome( const std::string &s )
{
std::string::size_type i = 0, n = s.size();
while ( i < n / 2 && s[i] == s[n - i - 1] ) ++i;
return i == n / 2;
}
int main()
{
std::cout << std::boolalpha << is_palindrome("madam") << "\n";
std::cout << std::boolalpha << is_palindrome("ada") << "\n";
std::cout << std::boolalpha << is_palindrome("lovelace") << "\n";
return 0;
}
Its output is
true
true
false
Another approach is to use the standard algorithm std::equal.
Here is a demonstrative program.
#include <iostream>
#include <iomanip>
#include <string>
#include <iterator>
#include <algorithm>
bool is_palindrome( const std::string &s )
{
return std::equal( std::begin( s ), std::next( std::begin( s ), s.size() / 2 ),
std::rbegin( s ) );
}
int main()
{
std::cout << std::boolalpha << is_palindrome("madam") << "\n";
std::cout << std::boolalpha << is_palindrome("ada") << "\n";
std::cout << std::boolalpha << is_palindrome("lovelace") << "\n";
return 0;
}
The program output is the same as shown above
true
true
false
If your compiler supports the C++ 17 Standard then it is even better to declare the function parameter as having the type std::string_view.
For example (or you can use the implementation with the standard algorithm std::equal)
#include <string_view>
bool is_palindrome( std::string_view s )
{
std::string_view::size_type i = 0, n = s.size();
while ( i < n / 2 && s[i] == s[n - i - 1] ) ++i;
return i == n / 2;
}
In this case you will be able to call the function selecting a sub-string of a string without creating an object of the type std::string as for example
std::cout << std::boolalpha << is_palindrome( { "adam", 3 } ) << "\n";
This line is wrong
for (int i = text.size(); i >= 0; i--) {
reversed.push_back(text[i]);
}
Notice that you are indexing from .size(), but that is not correct. The character at position text[text.size()] is guaranteed to be \0. This is probably not part of the string whose 'palindrome-ness' you want to check.
You need to do
for (int i = text.size() - 1; i >= 0; i--) {
reversed.push_back(text[i]);
}
If you actually want to reverse a string, you could just use std::reverse like this
auto rev = text;
std::reverse(rev.begin(), rev.end());
and then compare with rev == text.
Note that if you just want to check if a string is a palindrome, there are much more efficient ways to do it. To start off, your example is making 2 unnecessary copies; one in the function parameter, and one to store the reversed string.
Change the signature to take by const reference, and use an algorithm
bool is_palindrome(std::string const &text)
{
return std::equal(text.begin(),
text.begin() + text.size() / 2,
text.rbegin());
}

How to print all the distinct possible palindromic strings formed using characters of a given string [duplicate]

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);
}

Determine if all characters in a string are unique in C++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Trying to implement a fairly simple program in C++. I'm kinda new to this language. But it doesn't seem to be working.
#include <iostream>
#include <string>
using namespace std;
bool isUnique(string);
int main(){
bool uniq;
string a;
cout << "Please input a string, not a very long one...."<< endl;
getline(cin, a);
uniq = isUnique(a);
if (uniq == true)
{
cout << "The string has no repeatations." <<endl;
}else{
cout << "The characters in the string are not unique." <<endl;
}
return EXIT_SUCCESS;
}
bool isUnique(string str){
int len = strlen(str);
bool uniq = true;
for (int i = 0; i <= len; ++i)
{
for (int j = i+1; j <= len; ++j)
{
if (str[j] == str[i])
{
uniq = false;
}
}
}
return uniq;
}
The program compiles but has some logical errors I suppose. Any help appreciated.
An simple criterion for uniqueness is that there are no repeated characters in the sorted range of characters. There are algorithms in the standard library for this:
#include <algorithm> // for std::sort, std::unique
#include <iostream> // for std::cin, std::cout
#include <string> // for std:getline, std::string
int main()
{
std::string input;
std::cout << "Please input a string, not a very long one: ";
std::getline(input, std::cin);
std::sort(input.begin(), input.end());
bool u = std::unique(input.begin(), input.end()) == input.end();
if (u) { std::cout << "Every character is unique.\n"; }
else { std::cout << "The string contains repeated characters.\n"; }
}
As an optimization, you can exit early if the string has more characters than there are unique characters, though you'd need some way to determine what that number is.
You can check uniqueness much easier without a nested loop: make an array of bool[256], cast char to unsigned char, and use as an index into the array. If a bool has been set, the characters are not unique; otherwise, they are unique.
bool seen[256];
for (int i = 0 ; i != str.length() ; i++) {
unsigned char index = (unsigned char)str[i];
if (seen[index]) return false;
seen[index] = true;
}
return true;
The idea is simple: you mark characters that you've seen as you go, returning false if you see a "marked" character. If you reach the end without returning, all characters are unique.
This algorithm is O(n); your algorithm is O(n2). This does not make much difference, though, because it is impossible to construct a string of unique characters that is longer than 256 characters.
You are using a string, so it is not necessary to convert it to a char array. Use the string to check. You can check it like this:
bool isUnique(string str){
for (std::string::size_type i = 0; i < str.size(); ++i)
{
if(i < str.size()-1){
for (std::string::size_type j = i+1; j < str.size(); ++j)
{
if (str[j] == str[i])
{
uniq = false;
}
}
}
}
return uniq;
}
you can try this:
int main () {
bool uniqe=false;
string a;
char arr[1024];
int count[256]={0};
cout << "Please input a string, not a very long one...."<< endl;
getline(cin, a);
strcpy(arr, a.c_str());
for(int i=0;i<strlen(arr);i++)
count[(int)(arr[i])]++; // counting the occurence of character
for(int i=0;i<256;i++){
if(count[i]>1){ // if count > 1 means character are repeated.
uniqe=false;
break;
}else{
uniqe=true;
}
}
if(uniqe)
cout << "The string has no repeatations." <<endl;
else
cout << "The characters in the string are not unique." <<endl;
return 0;
}
There are too many errors in your code. For example instead of
int len = sizeof(arr)/sizeof(*arr);
there shall be
size_t len = std::strlen( arr );
Or instead of
for (int i = 0; i <= len; ++i)
there shall be at least
for (int i = 0; i < len; ++i)
and so on.
And there is no any need to define a character array. Class std::string has all that is required to do the task.
Try the following function
bool isUnique( const std::string &s )
{
bool unique = true;
for ( std::string::size_type i = 0; i < s.size() && unique; i++ )
{
std::string::size_type j = 0;
while ( j < i && s[j] != s[i] ) ++j;
unique = j == i;
}
return unique;
}
Here is a demonstrative program
#include <iostream>
#include <iomanip>
#include <string>
bool isUnique( const std::string &s )
{
bool unique = true;
for ( std::string::size_type i = 0; i < s.size() && unique; i++ )
{
std::string::size_type j = 0;
while ( j < i && s[j] != s[i] ) ++j;
unique = j == i;
}
return unique;
}
int main()
{
std::string s( "abcdef" );
std::cout << std::boolalpha << isUnique( s ) << std::endl;
s = "abcdefa";
std::cout << std::boolalpha << isUnique( s ) << std::endl;
return 0;
}
The output is
true
false
Here is your code with the errors fixed:
#include <iostream>
using namespace std;
bool isUnique(string,int); //extra parameter
int main(){
bool uniq;
string a;
cout << "Please input a string, not a very long one...."<< endl;
getline(cin, a);
uniq = isUnique(a,a.length()); //pass length of a
if (uniq == true)
{
cout << "The string has no repeatations." <<endl;
}else{
cout << "The characters in the string are not unique." <<endl;
}
return EXIT_SUCCESS;
}
bool isUnique(string str,int len){
bool uniq = true;
for (int i = 0; i < len-1; ++i) //len-1 else j would access unitialized memory location in the last iteration
{
for (int j = i+1; j < len; ++j) //j<len because array index starts from 0
{
if (str[j] == str[i])
{
uniq = false;
}
}
}
return uniq;
}

Check if a string is palindrome

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);
}