윤성필
윤성필

Reputation: 85

Answer difference between two compiler

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,

  1. lol
  2. Was it a car or a cat i saw?
  3. 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;
}

Upvotes: 1

Views: 140

Answers (2)

Slava
Slava

Reputation: 44268

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

Upvotes: 1

R Sahu
R Sahu

Reputation: 206717

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:

  1. Initialize the arrays.

    char text[256] = {0}, fixed[256] = {0};
    
  2. 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.

Upvotes: 4

Related Questions