Answer difference between two compiler - c++

I compiled the following code, But I got a serious problem.
When I compiled this code in visual studio 2015, It works perfectly.
However When I compile this code in Dev C++, I think it doesn't print "Yes" as an answer.
For example, when I type words like,
lol
Was it a car or a cat i saw?
abcdefghiihgfedcba
these inputs must return yes, but in dev c++ returns no.
Why does this problem occur?
#include <iostream>
#include <string>
using namespace std;
bool is_palindrome(char input[], int numOfSlots);
int main(void) {
char text[256], fixed[256];
cin.getline(text, sizeof(text), '\n');
for (int i = 0; i < sizeof(text); i++) {
text[i] = toupper(text[i]);
}
int j = 0;
for (int i = 0; i < sizeof(text); i++) {
if ((text[i] >= '0' && text[i] <= '9') || (text[i] >= 'A' && text[i] <= 'Z')) {
fixed[j] = text[i];
j++;
}
}
fixed[j] = '\0';
string s_fixed = fixed;
if (is_palindrome(fixed, s_fixed.length()) == true) {
cout << "Yes";
}
else {
cout << "No";
}
return 0;
}
bool is_palindrome(char input[], int numOfSlots) {
int i = 0;
while (i < numOfSlots / 2)
{
if (input[i] != input[(numOfSlots - 1) - i])
return false;
i++;
}
return true;
}

Your program exhibits undefined behavior since you are using uninitialized data.
You have:
char text[256], fixed[256];
which are uninitialized arrays. And then you go to access them using:
for (int i = 0; i < sizeof(text); i++) {
text[i] = toupper(text[i]); // Accessing uninitialized array
}
You can fix it using couple of ways:
Initialize the arrays.
char text[256] = {0}, fixed[256] = {0};
Access only the elements that were filled in the call to getline.
size_t size = strlen(text);
for (int i = 0; i < size; i++) {
However, the better fix is to always use the second method. That way, you don't process unnecessary data.

using std::string as replacement of strlen() is rather strange, when you can use it much better way:
bool is_palindrome( const std::string &input );
int main(void) {
std::string text;
getline(cin,text);
for (size_t i = 0; i < text.length(); i++) {
text[i] = toupper(text[i]);
}
std::string fixed;
for (size_t i = 0; i < text.length(); i++) {
if ((text[i] >= '0' && text[i] <= '9') || (text[i] >= 'A' && text[i] <= 'Z')) {
fixed += text[i];
}
}
if (is_palindrome(fixed)) {
cout << "Yes";
}
else {
cout << "No";
}
return 0;
}
bool is_palindrome(const std::string &input) {
size_t numOfSlots = input.length();
int i = 0;
while (i < numOfSlots / 2)
{
if (input[i] != input[(numOfSlots - 1) - i])
return false;
i++;
}
return true;
}
of course your program can be simplified but I tried to keep it close to original to show why it is better to use std::string instead of old style char[] in C++
Here simnpliefied version using std::string and other algos from standard libraries:
#include <iostream>
#include <string>
#include <algorithm>
bool is_palindrome( std::string str )
{
if( str.empty() ) return false;
std::transform( str.begin(), str.end(), str.begin(), []( char c ) { return std::toupper( c ); } );
str.erase( std::remove_if( str.begin(), str.end(), []( char c ) { return !std::isalnum( c ); } ), str.end() );
auto len = str.length() / 2 + 1;
return std::string( str.begin(), std::next( str.begin(), len ) ) ==
std::string( str.rbegin(), std::next( str.rbegin(), len ) );
}
int main()
{
std::string text;
std::getline( std::cin, text );
std::cout << ( is_palindrome( text ) ? "yes" : "no" ) << std::endl;
return 0;
}

Related

belonging of one string to another string

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.

what is wrong in my logic reversing vowels in a string?

I tried solving a problem in leetcode
which asks the programmer to reverse the vowels in the given string.
When I wrote my code in C, it ran fine and passed all the test cases.
I tried writing the same code in C++ but for a particular test case, it failed.
bool isVowel(char a)
{
if(a == 'a' || a == 'e' || a == 'i' || a == 'o' || a == 'u')
return true;
if(a == 'A' || a == 'E' || a == 'I' || a == 'O' || a == 'U')
return true;
return false;
}
class Solution {
public:
string reverseVowels(string s) {
int i, j, k;
int len = s.length();
j = s.length() - 1;
i = 0;
k = 0;
string result;
//char result[len];
if (j < 0)
return s;
while(j >= 0) {
if (isVowel(s[j])) {
result[k] = s[j];
k++;
}
j--;
}
k = 0;
j = s.length() - 1;
while (i <= j) {
if(isVowel(s[i])) {
s[i] = result[k];
k++;
}
i++;
}
return s;
}
};
For some reason, when the input is "A new order began, a more Roman age bred Rowena." there is an error message AddressSanitizer: stack-buffer-overflow on address 0x7ffd4a543ab0 at pc 0x000000405efb.
When I tried to debug, I found that, the first while loop gets infinite. But when I replace the string result to char result[len], my code is working fine.
What is wrong in my approach?
Thanks
hago
You may not use the subscript operator for an empty string to change its value.
So your program has undefined behavior.
Pay attention to that in any case you are not reversing vowels in a string. You are trying to create a new string with reversed vowels from a given string. But this is not the same thing.
I can suggest the following Solution.:)
#include <iostream>
#include <string>
#include <cstring>
#include <cctype>
class Solution final
{
private:
static bool isVowel( char c )
{
const char *vowels = "AEIOU";
return std::strchr( vowels, std::toupper( static_cast<unsigned char>( c ) ) );
}
public:
static std::string & reverseVowels( std::string &s )
{
auto first = std::begin( s ), last = std::end( s );
do
{
while ( first != last && !isVowel( *first ) ) ++first;
if ( first != last )
{
while ( --last != first && !isVowel( *last ) );
}
if ( first != last ) std::iter_swap( first++, last );
} while ( first != last );
return s;
}
};
int main()
{
std::string s( "I am trying to write a program in C++" );
std::cout << s << '\n';
std::cout << Solution::reverseVowels( s ) << '\n';
return 0;
}
The program output is
I am trying to write a program in C++
i am tryong ta wreti o prigram In C++
Pay into account that the letter 'y' is not included in the set of vowels.
Your solution is correct but with a simple mistake.
When you declare string result; then this variable is declared with 0 size. So whenever you try to place character at some position (i.e result[0], result[1], ...) it finds that there is no allocated memory for this variable. So it throws error.
In stead of placing character to the result, you can add the character to this string.
So you can write result = result + s[j];
Code snap should be like this -
string result = "";
//char result[len];
if (j < 0)
return s;
while(j >= 0) {
if (isVowel(s[j])) {
result = result + s[j];
}
j--;
}
But adding character to a string takes more run-time.
Besides this, you can also use string.push_back() to add a single character to a string. It's complexity is overall O(n), n = length of the final string.
string result = "";
//char result[len];
if (j < 0)
return s;
while(j >= 0) {
if (isVowel(s[j])) {
result.push_back(s[j]);
}
j--;
}

Leetcode 28 - Implement strStr(): question

I am experiencing a bug in my submissions for Leetcode 28 that has thus far eluded me. My code works for most test cases but I am getting hung up on scenarios such as haystack = "mississippi", needle = "issip".
I have tried debugging and found that the entire haystack string is iterated through and it is returning -1 or not found. The substring length it is finding at each occurrence of 'i' is 4, 1, 1.
int strStr(string haystack, string needle) {
if (needle.empty()) {
return 0;
}
if (haystack.empty() && !needle.empty()) {
return -1;
}
int i = 0, j = 0, ans = 0;
for (i; i < haystack.length(); i++) {
if (haystack[i] == needle[0]) {
j = 0;
ans = i;
for (j; j < needle.length(); j++) {
/*
if (haystack[i++] == needle[j]) {
continue;
}
else {
break;
}
*/
if (haystack[i++] != needle[j]) {
break;
}
}
if (j == needle.length()) {
return ans;
}
}
if (j == needle.length()) {
return ans;
}
}
return -1;
}
Input: "mississippi", "issip"
Output: -1 (ans = 10, j = 1)
The function has several drawbacks.
For starters it should be declared like
std::string::size_type strStr( const std::string &haystack, const std::string &needle );
and if the second string is not found in the first string the function should return std::string::npos as all similar member functions of the class std::string do.
The function parameters shell be of constant referenced types.
The condition in this if-statement
if (haystack.empty() && !needle.empty())
has a redundant operand. It could be rewritten like
if (haystack.empty())
This loop
for (i; i < haystack.length(); i++)
should stop its iterations when the size of the tail of the first string is less than the size of the second string.
in this if-statement
if (haystack[i++] != needle[j]) {
the variable i is incremented that results in incrementing the variable two times: one in this statement and the second time in the loop.
The second pair of these statements
if (j == needle.length()) {
return ans;
is redundant.
The function can be written the following way as it is shown in the demonstrative program.
#include <iostream>
#include <string>
std::string::size_type strStr( const std::string &haystack, const std::string &needle )
{
if ( needle.empty() )
{
return 0;
}
else if ( haystack.empty() )
{
return -std::string::npos;
}
else
{
std::string::size_type ans = std::string::npos;
auto n1 = haystack.length();
auto n2 = needle.length();
for ( std::string::size_type i = 0; ans == std::string::npos && i + n2 <= n1; i++ )
{
std::string::size_type j = 0;
while ( j < n2 && haystack[i+j] == needle[j] ) j++;
if ( j == n2 ) ans = i;
}
return ans;
}
}
int main()
{
std::string haystack( "mississippi" );
std::string needle( "issip" );
std::cout << strStr( haystack, needle ) << '\n';
return 0;
}
Its output is
4
The problem is that you modify i in
if (haystack[i++] != needle[j]) {
Thus preventing a second potential match from being explored. Try
if (haystack[i + j] != needle[j]) {
and fix any knock-on issues. I expect it to work as-is, though.

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

how to check whether 2 strings are rotations to each other ?

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