Home > Mobile >  Output not matching the expected output for almost palindrome program in C
Output not matching the expected output for almost palindrome program in C

Time:06-23

I can't find any error in my code for an almost palindrome. The statement

'r = isPalindrome(str, p[0], p[1]-1);'

is not getting executed while the function calls for p&q are getting executed fine. It prints values of only p & q. Can someone please explain what is wrong with the flow of the program?

#include <iostream>
#include<vector>
using namespace std;

int arr[2];


int* isPalindrome(string &s, int i, int j){

    int sz = s.length();

    if(i==j) return NULL;

    while(i<j){

        if(s[i] == s[j]){
            i  ;
            j--;
        }

        else{
            arr[0] = i;
            arr[1] = j;
            return arr;
        }
    }

    return NULL;
}


int main()
{

   string s = "abcdefdba", str;
   int *p, *q, *r;

   // removes any additional character or spaces and make lower-case
   for(int i=0; i<s.length();i  ){
    if(s[i] >= 65 && s[i]<=90) str.push_back(s[i] 32);
    if((s[i] >=97 && s[i]<=122) || (s[i]>=48 && s[i]<=57)) str.push_back(s[i]);
   }

    p = isPalindrome(str, 0, str.length()-1);

    cout<<"pointer p: "<<p[0]<<p[1]<<endl;

    if(p==NULL) cout<<"true";

    else{
         q = isPalindrome(str, p[0] 1, p[1]);

         r = isPalindrome(str, p[0], p[1]-1); // not getting executed
        }


    cout<<"pointer q: "<<q[0]<<q[1]<<endl;
    cout<<"pointer r: "<<r[0]<<r[1]<<endl;

    if(q==NULL || r==NULL) cout<<"true";
    else cout<<"false";


    return 0;

}

CodePudding user response:

Lets assume you are right and the function isn't execute and lets find out why the compiler might optimize it in such a way that the function call is not needed:

int* isPalindrome(string &s, int i, int j) returns a pointer to the global array arr or NULL and other than writing to arr it has no side effect.

Lets analyze the main function then:

p = isPalindrome(str, 0, str.length()-1);

cout<<"pointer p: "<<p[0]<<p[1]<<endl;

if(p==NULL) cout<<"true";
else {

You dereferrence p so p must not be NULL, the compiler can always take the else branch.

     q = isPalindrome(str, p[0] 1, p[1]);

     r = isPalindrome(str, p[0], p[1]-1); // not getting executed
    }


cout<<"pointer q: "<<q[0]<<q[1]<<endl;
cout<<"pointer r: "<<r[0]<<r[1]<<endl;

if(q==NULL || r==NULL) cout<<"true";
else cout<<"false";

Again you dereferrence q and r so they can not be NULL. So isPalindrom must have returned the address of arr in both cases and must have written arr[0] and arr[1], which is p, q and r. The second isPalindrom call changes p[0] and p[1] and that changes what the thrid isPalindrom call does. I don't think any of them can be skipped.

But the compiler can potentially compute it all at compile time and eliminate it all.

In the output you should see that the last two cout calls print the same thing. Maybe that makes you think one of the function calls is skipped. But what you see is that they both just print the same global arr.


What you should do is return std::optional<std::pair<int, int>> instead of the global array.

Better: int is not the right type of an index, that should be std::size_t. So std::optional<std::pair<std::size_t, std::size_t>>

Why not return iterators of the substring instead? And make it const, the argument should be a const std::string &: std::optional<std::pair<std::string::const_iterator, std::string::const_iterator>>

Or lets get really modern and return a string view: std::optional<std::string_view>

  • Related