I'm trying to code a simple c++ program that lets the user know if the word they input is palindrome or not. Example: 'mom' is palindrome.
Here's what I have:
#include <iostream>
#include <string>
using namespace std;
// Forward Declaration
string reversed_string(string);
int main(){
string str;
string reversed;
cout << "Enter string to check:\n";
getline(cin, str);
reversed = reversed_string(str);
if(str == reversed){
cout << str << " is palindrome\n\n";
}
else{
cout << "Not palindrome";
}
}
string reversed_string(string str){
string reversed;
for(int i = int(str.length()); i >= 0; i--){
reversed += str[i];
}
return reversed;
}
When I try to input a palindrome word, it always goes to the else statement in my main function. What am I doing wrong?
The last character of a string is at index len - 1, not len. As per the standard (C++11):
Returns *(begin() + pos) if pos < size(). Otherwise, returns a reference to an object of type charT with value charT(), where modifying the object leads to undefined behavior.
What that standardese actually means is that, if pos is not less than the string length, the function returns a reference to a null character. Hence the first character you're putting into your reversed string is the null.
However, you don't really need to reverse the string to find if it's a palindrome, it might be easier to simply use the following (pseudo-code) algorithm:
def isPalindrome(string):
set left to zero
set right to one less than string length
while left is less than right:
if string[left] is not equal to string[right]:
return false
add one to left
subtract one from right
return true
Given you have to process every character to form the reversed string anyway, you may as well use that processing power to just check the characters in the original string. That way, you can exit early if it's not a palindrome.
This will, of course, consider an empty string to be a palindrome, which is arguably correct. If you don't think that's correct, simply put a check in up front:
def isPalindrome(string):
if string length is zero:
return false
set left to zero
... and so on
Related
I am trying to truncate beginning zeros from a string, so I used sequence erase function
string& erase (size_t pos = 0, size_t len = npos);
This is my implementaion:
string str="000010557";
for(char c:str){
cout<<c<<" "<<str<<" "<<"\n";// for debug purpose
if(c=='0')
str.erase(0,1);
else
break;
}
cout<<str;
the output string that I got is 0010557 instead of10557 and debug statements prints:
0 000010557
0 00010557
1 0010557
I read the documentation of erase and this post thinking might there be some iterator invalidation but implementing the code snippet recommended in the accepted answer also gave the same output, please help me understand where is the problem.
I am new to using stl library functions, so please forgive any negligence of mine,Thanks.
Your for loop is incrementing the position from which c is extracted, even if you erase a leading zero. Thus, after two runs of the loop, you have erased the first and third of the leading zeros, then the c value will be the first 1.
Here's an attempt at following what happens in your code:
Start of first loop:
"000010557"
^
c is '0', so erase is called, making the string:
"00010557"
At the end of this first loop, the position is incremented, so...
Start of second loop:
"00010557"
^ (Note that we've skipped a zero!)
c is '0', so erase is called, making the string:
"0010557"
End of loop, position increment, and we skip another zero, so...
Start of third loop:
"0010557"
^
c is not '0', so we break out of the loop.
Instead, you should use a while loop, testing only the first character:
int main()
{
string str = "000010557";
char c;
while ((c = str.at(0)) == '0') {
cout << c << " " << str << " " << "\n";// for debug purpose
str.erase(0, 1);
}
cout << str;
}
Output:
0 000010557
0 00010557
0 0010557
0 010557
10557
Of course, you only need the c variable for your 'debugging' line so, without that, you can just have:
int main()
{
string str = "000010557";
while (str.at(0) == '0') str.erase(0, 1);
cout << str;
}
Even if you get this code to work, it's not a good solution. Removing a single character from the front of a string means moving all of the subsequent characters down one position, and the code does that for every leading zero. Instead, count the leading zeros and remove them all at once:
std::string::size_type non_zero_pos = 0;
while (non_zero_pos < str.size() && str[non_zero_pos] == '0')
++non_zero_pos;
str.erase(0, non_zero_pos);
That way, the (expensive) erase operation is only done once.
Or use iterators:
auto non_zero_it = std::find_first_not_of(std::begin(str), std::end(str), "0");
str.erase(std::begin(str), non_zero_it);
Edit: fixed search for non-0 iterator.
I picked up a challenge on r/dailyprogrammer on reddit which wants me to match a necklace and put the last letter at the beginning of a string. I've considered using nested for loops for this but this has made me really confused.
Instead I chose the way of replacing the last with the first character in an if-statement. But I am not getting my desired output with it, though I've tried everything what comes into my mind.
I used even std::swap() which didn't lead me to success either.
Here's the code:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string same_necklace(string& sInput, string& sOutput)
{
for (string::size_type i = 0; i < sInput.size(); i++)
{
if (sInput[i] == sInput.size())
{
sInput[0] = sInput[sInput.size()];
}
}
for (string::size_type j = 0; j < sOutput.size(); j++)
{
if (sOutput[j] == sOutput.size() - 1)
{
sOutput[0] = sOutput[sOutput.size()];
}
}
return sInput, sOutput;
}
int main()
{
system("color 2");
string sName{ "" };
string sExpectedOutput{ "" };
cout << "Enter a name: ";
cin >> sName;
cout << "Enter expected output: ";
cin >> sExpectedOutput;
cout << "Result: " << same_necklace(sName , sExpectedOutput) << endl;
return 0;
}
And of course the link to my challenge (don't worry, it's just Reddit!):
https://www.reddit.com/r/dailyprogrammer/comments/ffxabb/20200309_challenge_383_easy_necklace_matching/
While I am waiting (hopefully) for a nice response, I will keep on trying to solve my problem.
In your if you compare the value of the current index (inside the loop) with the size of the string. Those are two unrelated things.
Also, you use a loop though you only want to do something on a single, previously known index.
for (string::size_type i = 0; i < sInput.size(); i++)
{
if (sInput[i] == sInput.size())
{
sInput[0] = sInput[sInput.size()];
}
}
You could change the if condition like this to achieve your goal:
if (i == sInput.size()-1) /* size as the index is one too high to be legal */
But what is sufficient and more elegant is to drop the if and the loop. completely
/* no loop for (string::size_type i = 0; i < sInput.size(); i++)
{ */
/* no if (sInput[i] == sInput.size())
{*/
sInput[0] = sInput[sInput.size()-1]; /* fix the index*/
/* }
} */
I.e.
sInput[0] = sInput[sInput.size()-1]; /* fix the index*/
Same for he output, though you got the correct index already correct there.
This is not intended to solve the challenge which you linked externally,
if you want that you need to describe the challenge completely and directly here.
I.e. this only fixes your code, according to the desription you provide here in the body of your question,
"put the last letter at the beginning of a string".
It does not "switch" or swap first and last. If you want that please find the code you recently wrote (surely, during your quest for learning programming) which swaps the value of two variables. Adapt that code to the two indexes (first and last, 0 and size-1) and it will do the swapping.
So much for the loops and ifs, but there is more wrong in your code.
This
return sInput, sOutput;
does not do what you expect. Read up on the , operator, the comma-operator.
Its result is the second of the two expressions, while the first one is only valuated for side effects.
This means that this
cout << "Result: " << same_necklace(sName , sExpectedOutput) << endl;
will only output the modified sExpectedOutput.
If you want to output both, the modified input and the modified output, then you can simply
cout << "Result: " << sName << " " << sExpectedOutput << endl;
because both have been given as reference to the function and hence both contain the changes the function made.
This also might not answer the challenge, but it explains your misunderstandings and you will be able to adapt to the challenge now.
You have not understand the problem i guess.
Here you need to compare two strings that can be made from neckless characters.
Lets say you have neckless four latters word is nose.
Combination is possible
1)nose
2)osen
3)seno
4)enos
your function (same_necklace) should be able to tell that these strings are belongs to same necklace
if you give any two strings as inputs to your function same_necklace
your function should return true.
if you give one input string from above group and second input string from other random word thats not belongs to above group, your function should return false.
In that sense, you just take your first string as neckless string and compare other string with all possible combination of first string.
just move move you first latter of first input string to end and then compare each resulting string to second input string.
below is the function which you can use
void swap_character(string &test)
{
int length = test.length();
test.insert(length, 1, test[0]);
test.erase(0, 1);
}
I am trying to skip the spaces in my code using getline();
I think I solved the spacing problem, but I'm trying to make the code check from the beginning of the word and the end of the word at the same time, so that when I type sentences like "ufo tofu" it will come back as a palindrome.
I've tried removing the spaces, but it only causes the system to return me an error.
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main() {
string userInput;
int startInput;
int endInput;
bool isPalindrome = true;
startInput = userInput.length();
getline (cin, userInput);
cin.ignore();
for (int i = 0; i<(startInput/2); i++){
if (userInput[i] != userInput[(startInput -1) -i])
isPalindrome = false;
}
if (isPalindrome){
cout << userInput << " is a palindrome" << endl;
}
else {
cout << userInput << " is not a palindrome" << endl;
}
return 0;
}
I am trying to make the output come back as "is not a palindrome" when I submit my code to be graded.
These are the two errors that are coming back;
4: Compare output
0 / 2
Output differs. See highlights below.
Special character legend
Input
statistics
Your output
statistics is a palindrome
Expected output
statistics is not a palindrome
6: Compare output
0 / 2
Output differs. See highlights below.
Special character legend
Input
evil is alive
Your output
evil is alive is a palindrome
Expected output
evil is alive is not a palindrome
string s;
do {
getline(cin, s);
}while(s.empty());
s.erase((remove(s.begin(),s.end(),' ')),s.end());
cout<<s<<endl;
Let's say your string s is ufo tofu. It will after erasing all spaces become ufotofu. That way you can easily check if it's palindrome or not.
How does this thing work ?
Well we declare a string called s. In that string, we will store our ufo tofu input.
We use do-while loop to input our "sentence" into a string. We could use just getline(cin, s);, but if you pressed enter-key once, it would stop your program.
Next thing, we use function combination of functions remove and erase: As the beginning parameter we use function remove, which finds all the spaces in the string, pushes them to the end of the container (in our case string s), and returns beginning iterator of that "pushing", and the second parameter tells us to remove every single element of container from that beginning iterator to the end.
We just print out the string, but now without spaces!
I think this is really simple way to do it, but if it can't be useful to you, I am sorry for wasting your time reading all of this! :)
I cannot print the string str2[i].a even though I can print the same in str1[i].a
I am getting the individual characters in the string as I print them by the index values
I can also print the str1[i].a string that I had entered before
Thanks!!
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class st
{
public:
string a;
int col;
}str1[200],str2[200];
int main()
{
int i=0,j=0,num,l=0,len=0;
string str;
for(i=0;;i++)
{
cin>>num;
str1[i].col=num;
if(str1[i].col==0)
break;
cin>>str1[i].a;
cout<<str1[i].a; // I get string entered before
}
for(i=0;;i++)
{
if(str1[i].col==0)
break;
len = str1[i].a.size()-1;
//cout << len << endl;
l=0,j=0;
for(;;)
{
str2[i].a[l]=str1[i].a[j];
l++;
j=((j+str1[i].col)%len);
if(j==0)
{
str2[i].a[l]=str1[i].a[len];
cout << str2[i].a[l];//I get the char assigned above
l++;
str2[i].a[l]='\n';
break;
}
}
cout << str2[i].a; // I get nothing after I print
cout << str2[i].a[0];// I get the required character of string
cout << str2[i].a[5];//I get the required character of string
cout << str2[i].a[8];//I get the required character of string
}
return 0;
}
What you forget to do is to preallocate the buffer for your second string. It is only safe to assign a value to a character in an std::string if that string has at least that many characters (in other words, str2.a[2] = 'a' is safe is std2.a has a length of at least three, but is not safe if it has any smaller length). In your case none of the str2s is ever assigned anything, so they are all empty and have length of 0.
One solution would be to preallocate your string in advance, but even better, since you only write characters to the end, use push_back instead of square brackets, as in
str2[i].push_back(str1[i].a[j]);
instead of
str2[i].a[l]=str1[i].a[j];
To explain why you can print individual characters, but not the entire string, note that what you do is technically an undefined behavior [1], I would assume that what it does is when you print the entire string, it looks at its length, sees that it is zero, and skips printing anything, but when you print individual characters, it looks at the buffer it allocated for the string (which is probably of non-zero size, to make early push_backs effective), and sees the changes you made to them.
[1] http://www.cplusplus.com/reference/string/string/operator%5B%5D/, see in particular:
If pos is less than the string length, the function never throws
exceptions (no-throw guarantee). If pos is equal to the string length,
the const-version never throws exceptions (no-throw guarantee).
Otherwise, it causes undefined behavior.
I have following code that gets and prints a string.
#include<iostream>
#include<conio.h>
#include<string>
using namespace std;
int main()
{
string str;
cout << "Enter a string: ";
getline(cin, str);
cout << str;
getch();
return 0;
}
But how to count the number of characters in this string using strlen() function?
For C++ strings, there's no reason to use strlen. Just use string::length:
std::cout << str.length() << std::endl;
You should strongly prefer this to strlen(str.c_str()) for the following reasons:
Clarity: The length() (or size()) member functions unambiguously give back the length of the string. While it's possible to figure out what strlen(str.c_str()) does, it forces the reader to pause for a bit.
Efficiency: length() and size() run in time O(1), while strlen(str.c_str()) will take Θ(n) time to find the end of the string.
Style: It's good to prefer the C++ versions of functions to the C versions unless there's a specific reason to do so otherwise. This is why, for example, it's usually considered better to use std::sort over qsort or std::lower_bound over bsearch, unless some other factors come into play that would affect performance.
The only reason I could think of where strlen would be useful is if you had a C++-style string that had embedded null characters and you wanted to determine how many characters appeared before the first of them. (That's one way in which strlen differs from string::length; the former stops at a null terminator, and the latter counts all the characters in the string). But if that's the case, just use string::find:
size_t index = str.find(0);
if (index == str::npos) index = str.length();
std::cout << index << std::endl;
Function strlen shows the number of character before \0 and using it for std::string may report wrong length.
strlen(str.c_str()); // It may return wrong length.
In C++, a string can contain \0 within the characters but C-style-zero-terminated strings can not but at the end. If the std::string has a \0 before the last character then strlen reports a length less than the actual length.
Try to use .length() or .size(), I prefer second one since another standard containers have it.
str.size()
Use std::string::size or std::string::length (both are the same).
As you insist to use strlen, you can:
int size = strlen( str.c_str() );
note the usage of std::string::c_str, which returns const char*.
BUT strlen counts untill it hit \0 char and std::string can store such chars. In other words, strlen could sometimes lie for the size.
If you really, really want to use strlen(), then
cout << strlen(str.c_str()) << endl;
else the use of .length() is more in keeping with C++.
Manually:
int strlen(string s)
{
int len = 0;
while (s[len])
len++;
return len;
}
#include<iostream>
#include<conio.h>
#include<string.h>
using namespace std;
int main()
{
char str[80];
int i;
cout<<"\n enter string:";
cin.getline(str,80);
int n=strlen(str);
cout<<"\n lenght is:"<<n;
getch();
return 0;
}
This is the program if you want to use strlen .
Hope this helps!
Simply use
int len=str.length();