undesired output of the Palindrome program using C++ - c++

So I started learning C++ two weeks ago and I want to build a program that checks if a string is a palindrome or not.
I tried different ways including the str1==str2 method in the following way:
#include<iostream>
#include<string>
using namespace std;
string empty;
string word;
bool inverse(string word)
{
for (int i=0;i<=word.length();i++)
{
empty+=word[word.length()-i];
}
return empty==word;
}
int main()
{
cout<<inverse("civic");
}
The output is always 0
Second way: the str1.compare(str2) method
#include<iostream>
#include<string>
using namespace std;
string empty;
string word;
bool inverse(string word)
{
for (int i=0;i<=word.length();i++)
{empty+=word[word.length()-i];}
if (word.compare(empty))
return true;
else
return false;
}
int main()
{
if (inverse(word)==true)
cout<<"is a palindrome";
else
cout<<"is not a palindrome";
cout<<inverse("ano");
cout<<inverse("madam");
}
the output is always: is palindrome1 (with 1 or two ones at the end of "palindrome")
even if the string is not a palindrome.
please explain to me what mistakes I made and how I can correct them.
Also If I want to make my program handle a string that has white space in it, how can I do it?

There are a couple of problems
Your code is looping too many times. For example a word of three letters should loop three times, but your code loops for 4 (i=0, i=1, i=2, and i=3). To fix this you need to change the final condition to use < instead of <=.
You are computing the symmetrical index with the wrong formula. If for example you have a word of length three the letters be word[0], word[1] and word[2]. However your code uses length - i and for i=0 this will use word[3] that is outside the allowed limits for the word. You need to do the indexing using as formula length - 1 - i instead of length - i.
Both of these errors are quite common in programming and they're called "off-by-one" errors. Remember to always double-check the boundary conditions when you write code so that you can keep this kind of error away from your programs.

For first one you need to change
for (int i=0;i<=word.length();i++)
{empty+=word[word.length()-i];}
to this
for (int i=0;i<word.length();i++)
{empty+=word[word.length()-(i+1)];}

Your program's behavior will become undefined after this line:
for (int i = 0;i <= word.length(); i++)
empty += word[word.length() - i];
Since length is always one plus the last element (Since the first index is zero), when i is 0, then: word[word.length()] will give you the element after the last element, which is not possible and thus your program will invoke undefined behavior since C/C++... word[word.length()] is also possible when i itself becomes word.length(), so change <= (less than or equal to) to < (less than)
So, it should be:
for (int i = 0;i < word.length(); i++)
empty += word[word.length() - 1 - i];

Related

C++ character variable value of '\x1'

I'm failing to understand why would the loop exit at the value of character variable i = '\x1'
#include <iostream>
using namespace std;
int main()
{
char i;
for (i = 1; i < 10, i++;)
{
cout << i << endl;
}
return 0;
}
Can somebody please explain this behavior ?
This is wrong
for (i = 1; i < 10, i++;)
/* ^ should be ; */
You only declared 3 regions for the loop, but put your increment statement in the middle area, and left your increment area empty. I have no idea which statement in the middle area your compiler will choose to execute. Best not to try to be cute and deceive your compiler. Let alone some colleague who will read your code years from now and go WTF???
A for loop has 3 distinct areas delimited by semi-colons:
The initialization area. You can declare as many variables in here as you want. These can be delimited by commas.
The test area. This is where an expression goes to test if the loop should continue.
The post loop area. This region of code gets executed after every loop.
Try to keep it simple. If it is going to be more complicated then use a while loop.
The reason that i ends up being 1 is that when i++ is zero, which terminates the loop, then i will become 1 (That is what the form of the ++ operator you used does). As the other answered have pointed out, once you fix your code by moving i++ out of the condition by replacing the comma with a semicolon, then i will make it all the way to 10 as desired.
for (i = 1; i < 10; i++)
You wrote for statement wrong.

ARRAYS DEBUGGING incorrect outputs, complex algorithm

I made this algorithm, i was debugging it to see why it wasnt working, but then i started getting weird stuff while printing arrays at the end of each cycle to see where the problem first occurred.
At a first glance, it seemed my while cycles didn't take into consideration the last array value, but i dunno...
all info about algorithm and everything is in the source.
What i'd like to understand is, primarily, the answer to this question:
Why does the output change sometimes?? If i run the program, 60-70% of the time i get answer 14 (which should be wrong), but some other times i get weird stuff as the result...why??
how can i debug the code if i keep getting different results....plus, if i compile for release and not debug (running codeblocks under latest gcc available in debian sid here), i get most of the times 9 as result.
CODE:
#include <iostream>
#include <vector>
/*void print_array
{
std::cout<<" ( ";
for (int i = 0; i < n; i++) { std::cout<<array[i]<<" "; }
std::cout<<")"<<std::endl;
}*/
///this algorithm must take an array of elements and return the maximum achievable sum
///within any of the sub-arrays (or sub-segments) of the array (the sum must be composed of adjacent numbers within the array)
///it will squeeze the array ...(...positive numbers...)(...negative numbers...)(...positive numbers...)...
///into ...(positive number)(negative number)(positive number)...
///then it will 'remove' any negative numbers in case it would be convienent so that the sum between 2 positive numbers
///separated by 1 negative number would result in the highest achievable number, like this:
// -- (3,-4,4) if u do 'remove' the negative number in order to unite the positive ones, i will get 3-4+4=3. So it would
// be better not to remove the negative number, and let 4 be the highest number achievable, without any sums
// -- (3,-1,4) in this case removing -1 will result in 3-1+4=6, 6 is bigger than both 3 and 4, so it would be convienent to remove the
// negative number and sum all of the three up into one number
///so what this step does is shrink the array furthermore if it is possible to 'remove' any negatives in a smart way
///i also make it reiterate for as long as there is no more shrinking available, because if you think about it not always
///can the pc know if, after a shrinking has occured, there are more shrinkings to be done
///then, lastly, it will calculate which of the positive numbers left is highest, and it will choose that as remaining maximum sum :)
///expected result for the array of input, s[], would be (i think), 7
int main() {
const int n=4;
int s[n+1]={3,-2,4,-4,6};
int k[n+1]={0};
///PRINT ARRAY, FOR DEBUG
std::cout<<" ( ";
for (int i = 0; i <= n; i++) { std::cout<<k[i]<<" "; }
std::cout<<")"<<std::endl;
int i=0, j=0;
// step 1: compress negative and postive subsegments of array s[] into single numbers within array k[]
/*while (i<=n)
{
while (s[i]>=0)
{
k[j]+=s[i]; ++i;
}
++j;
while (s[i]<0)
{
k[j]+=s[i]; ++i;
}
++j;
}*/
while (i<=n)
{
while (s[i]>=0)
{
if (i>n) break;
k[j]+=s[i]; ++i;
}
++j;
while (s[i]<0)
{
if (i>n) break;
k[j]+=s[i]; ++i;
}
++j;
}
std::cout<<"STEP 1 : ";
///PRINT ARRAY, FOR DEBUG
std::cout<<" ( ";
for (int i = 0; i <= n; i++) { std::cout<<k[i]<<" "; }
std::cout<<")"<<std::endl;
j=0;
// step 2: remove negative numbers when handy
std::cout<<"checked WRONG! "<<unsigned(k[3])<<std::endl;
int p=1;
while (p!=0)
{
p=0;
while (j<=n)
{
std::cout<<"checked right! "<<unsigned(k[j+1])<<std::endl;
if (k[j]<=0) { ++j; continue;}
if ( k[j]>unsigned(k[j+1]) && k[j+2]>unsigned(k[j+1]) )
{
std::cout<<"checked right!"<<std::endl;
k[j+2]=k[j]+k[j+1]+k[j+2];
k[j]=0; k[j+1]=0;
++p;
}
j+=2;
}
}
std::cout<<"STEP 2 : ";
///PRINT ARRAY, FOR DEBUG
std::cout<<" ( ";
for (int i = 0; i <= n; i++) { std::cout<<k[i]<<" "; }
std::cout<<")"<<std::endl;
j=0; i=0; //i will now use "i" and "p" variables for completely different purposes, as not to waste memory
// i will be final value that algorithm needed to find
// p will be a value to put within i if it is the biggest number found yet, it will keep changing as i go through the array....
// step 3: check which positive number is bigger: IT IS THE MAX ACHIEVABLE SUM!!
while (j<=n)
{
if(k[j]<=0) { ++j; continue; }
p=k[j]; if (p>i) { std::swap(p,i); }
j+=2;
}
std::cout<<std::endl<<"MAX ACHIEVABLE SUM WITHIN SUBSEGMENTS OF ARRAY : "<<i<<std::endl;
return 0;
}
might there be problems because im not using vectors??
Thanks for your help!
EDIT: i found both my algorithm bugs!
one is the one mentioned by user m24p, found in step 1 of the algorithm, which i fixed with a kinda-ugly get-around which ill get to cleaning up later...
the other is found in step2. it seems that in the while expression check, where i check something against unsigned values of the array, what is really checked is that something agains unsigned values of some weird numbers.
i tested it, with simple cout output:
IF i do unsigned(k[anyindexofk]) and the value contained in that spot is a positive number, i get the positive number of course which is unsigned
IF that number is negative though, the value won't be simply unsigned, but look very different, like i stepped over the array or something...i get this number "4294967292" when im instead expecting -2 to return as 2 or -4 to be 4.
(that number is for -4, -2 gives 4294967294)
I edited the sources with my new stuff, thanks for the help!
EDIT 2: nvm i resolved with std::abs() using cmath libs of c++
would there have been any other ways without using abs?
In your code, you have:
while (s[i]>=0)
{
k[j]+=s[i]; ++i;
}
Where s is initialized like so
int s[n+1]={3,-2,4,-4,6};
This is one obvious bug. Your while loop will overstep the array and hit garbage data that may or may not be zeroed out. Nothing stops i from being bigger than n+1. Clean up your code so that you don't overstep arrays, and then try debugging it. Also, your question is needs to be much more specific for me to feel comfortable answering your question, but fixing bugs like the one I pointed out should make it easier to stop running into inconsistent, undefined behavior and start focusing on your algorithm. I would love to answer the question but I just can't parse what you're specifically asking or what's going wrong.

C++ program to compute lcm of numbers between 1 to 20 (project euler )

as the title explains this is a program to find lcm of numbers between 1 to 20. i found an algorithm to do this, here's the link
http://www.cut-the-knot.org/Curriculum/Arithmetic/LCM.shtml
there is a java applet on the webpage that might explain the algorithm better
Problem: i wrote the code compiler shows no error but when i run the code the program goes berserk, i guess may be some infinite loopig but i can't figure it out for the life of me. i use turbo c++ 4.5 so basically if anyone can look at the code and help me out it would be great . thanks in advance
Algorithm:
say we need to find lcm of 2,6,8
first we find the least of the series and add to it the number above it, i.e the series become
4,6,8
now we find the least value again and add to it the intitial value in the column i.e 2
6,6,8
so the next iteration becomes
8,6,8
8,12,8
10,12,8
10,12,16
12,12,16
14,12,16
14,18,16
16,18,16
18,18,16
18,18,24
20,18,24
20,24,24
22,24,24
24,24,24
as you can see at one point all numbers become equal which is our lcm
#include<iostream.h>
/*function to check if all the elements of an array are equal*/
int equl(int a[20], int n)
{
int i=0;
while(n==1&&i<20)
{
if (a[i]==a[i+1])
n=1;
else
n=0;
i++;
}
return n;
}
/*function to calculate lcm and return that value to main function*/
int lcm()
{
int i,k,j,check=1,a[20],b[20];
/*loading both arrays with numbers from 1 to 20*/
for(i=0;i<20;i++)
{
a[i]=i+1;
b[i]=i+1;
}
check= equl(a,1);
/*actual implementation of the algorith*/
while(check==0)
{
k=a[0]; /*looks for the least value in the array*/
for(i=0;i<20;i++)
{
if(a[i+1]<k)
{
k=a[i+1]; /*find the least value*/
j=i+1; /*mark the position in array */
}
else
continue;
}
a[j]=k+b[j]; /*adding the least value with its corresponding number*/
check= equl(a,1);
}
return (a[0]);
/*at this point all numbers in the array must be same thus any value gives us the lcm*/
}
void main()
{
int l;
l=lcm();
cout<<l;
}
In this line:
a[j]=k+b[j];
You use j but it is unitialized so it's some huge value and you are outside of the array bounds and thus you get a segmentation fault.
You also have some weird things going on in your code. void main() and you use cout without either saying std::cout or using namespace std; or something similar. An odd practice.
Also don't you think you should pass the arrays as arguments if you're going to make lcm() a function? That is int lcm(int a[], int b[]);.
You might look into using a debugger also and improving your coding practices. I found this error within 30 seconds of pasting your code into the compiler with the help of the debugger.
Your loop condition is:
while(n==1&&i<20)
So your equl function will never return 1 because if n happens to be 1 then the loop will just keep going and never return a 1.
However, your program still does not appear to return the correct result. You can split the piece of your code that finds the minimum element and replace it with this for cleanliness:
int least(int a[], int size){
int minPos = 0;
for(int i=0; i<size ;i++){
if (a[i] < a[minPos] ){
minPos = i;
}
}
return minPos;
}
Then you can call it by saying j = least(a, 20);. I will leave further work on your program to you. Consider calling your variables something meaningful instead of i,j,k,a,b.
Your equl function is using array indices from 0-20, but the arrays only have 1-19
j in lcm() is uninitialized if the first element is the smallest. It should be set to 0 at the top of the while loop
In the following code, when i=19, you are accessing a[20], which is out of the bounds of the array. Should be for(i=0;i<19;i++)
for(i=0;i<20;i++) {
if(a[i+1]<k)
You are not actually using the std namespace for the cout. this should be std::cout<<l
Your are including iostream.h. The standard is iostream without the .h, this may not work on such an old compiler tho
instead of hard-coding 20 everywhere, you should use a #define. This is not an error, just a style thing.
The following code does nothing. This is the default behavior
else
continue;

Do I need more space?

I have code that is supposed to separate a string into 3 length sections:
ABCDEFG should be ABC DEF G
However, I have an extremely long string and I keep getting the
terminate called without an active exception
When I cut the length of the string down, it seems to work. Do I need more space? I thought when using a string I didn't have to worry about space.
int main ()
{
string code, default_Code, start_C;
default_Code = "TCAATGTAACGCGCTACCCGGAGCTCTGGGCCCAAATTTCATCCACT";
start_C = "AUG";
code = default_Code;
for (double j = 0; j < code.length(); j++) { //insert spacing here
code.insert(j += 3, 1, ' ');
}
cout << code;
return 0;
}
Think about the case when code.length() == 2. You're inserting a space somewhere over the string. I'm not sure but it would be okay if for(int j=0; j+3 < code.length(); j++).
This is some fairly confusing code. You are looping through a string and looping until you reach the end of the string. However, inside the loop you are not only modifying the string you are looping through, but you also change the loop variable when you say j += 3.
It happens to work for any string with a multiple of 3 letters, but you are not correctly handling other cases.
Here is a working example of the for loop that is a bit more clear it what it's doing:
// We skip 4 each time because we added a space.
for (int j = 3; j < code.length(); j += 4)
{
code.insert(j, 1, ' ');
}
You are using an extremely inefficient method to do such an operation. Every time you insert a space you are moving all the remaining part of the string forward and this means that the total number of operations you will need is in the order of o(n**2).
You can instead do this transormation with a single o(n) pass by using a read-write approach:
// input string is assumed to be non-empty
std::string new_string((old_string.size()*4-1)/3);
int writeptr = 0, count = 0;
for (int readptr=0,n=old_string.size(); readptr<n; readptr++) {
new_string[writeptr++] = old_string[readptr];
if (++count == 3) {
count = 0;
new_string[writeptr++] = ' ';
}
}
A similar algorithm can be written also to work "inplace" instead of creating a new string, simply you have to first enlarge the string and then work backward.
Note also that while it's true that for a string you don't need to care about allocation and deallocation still there are limits about the size of a string object (even if probably you are not hitting them... your version is so slow that it would take forever to get to that point on a modern computer).

trying to sort a simple string in c++

#include "stdio.h"
#include "conio.h"
#include <iostream>
using namespace std;
int main (void)
{
char my_char[] = "happy birthday";
int i;
bool j=false;
char my_char_temp[1];
do
{
for (i=0;i<sizeof(my_char)-2;i++)
{
j=false;
if (my_char[i+1] < my_char[i])
{
my_char_temp[0]=my_char[i+1];
my_char[i+1] = my_char[i];
my_char[i] = my_char_temp[0];
j=true;
}
}
}while (j);
cout << my_char;
}
What am I doing wrong?
I'm just trying to sort the letters within the char.
The output I get is completely wrong.
You want to use strlen() rather than sizeof.
You are resetting j to false each and every time you compare two characters.
This means that, if you swap two characters, and you are NOT at the end of your array, you will forget that you have swapped them.
Move the j=false; from inside the for-loop to just inside the do-loop.
And you owe me a bottle of Jack for saving your ass on a homework assignment on Sunday afternoon.
I don't know what are you trying to implement with your sizeof(...) - 2 and etc, but what you probably want to get can be done this way:
#include <iostream>
#include <algorithm>
int main() {
std::string s("happy birthday");
std::sort(s.begin(), s.end());
}
Consider what happens inside this loop:
for (i=0;i<sizeof(my_char)-2;i++)
If you find a pair of values to swap, setting j to true, you'll continue iterating through that loop, and set j back to false on the next iteration. As a result, the program is going to exit as soon as the last two characters in the string are in sorted order, regardless of whether the rest of the string is sorted.
Instead, as soon as you find a pair of characters to swap, you want to start over again at i=0. The simplest way to do that is add a break; statement after your j = true line. With that fix, this works correctly.
Alternately, you could move the initial j = false line outside the loop, which would solve the problem in a slightly different way.
You are actually very close. The only problem is that
j=false;
needs to be in the outer loop. As is, j is cleared every time the inner loop executes.
With this fix, your program works fine for me.
Stylistic errors, however, are another story.
I could be mistaken but it looks like you're trying to do a bubble sort?
And it's i < sizeof(my_char)-2 because he's using a 0-based, null terminated string, and he doesn't want to sort the null terminator.
Try just repeating the condition of the inner loop, using j instead of i, and see if that works? Note that this has a run time of O(n^2) and you can get sorts down much much faster than that if you need to. Alternately you can move the boolean out of the for and into the do loop.
for (i=0;i < sizeof(my_char)-2;i++)
for (i=0;i<sizeof(my_char)-2;i++)
{
if (my_char[i+1] < my_char[i])
{
my_char_temp[0]=my_char[i+1];
my_char[i+1] = my_char[i];
my_char[i] = my_char_temp[0];
}
}