I wanted to create function that returns true/false according if the input is a palindrome or not, when given abcddcba or aba it does not give true, but it should . plz help
bool checkPalindrome(char input[],int p=0) {
if(input[1]=='\0'){
return true;
}
if(sizeof(input)%2==0) {
int a = sizeof(input);
for(int i=0;i<(a/2);i++) {
if(input[0+i]==input[a-i-2]){
p++;
}
}
if(p==a/2){
return true;
} else{
return false;
}
}
else{
int a = sizeof(input);
for(int i=0;i<((a-1)/2);i++)
{
if(input[0+i]==input[a-i-2]){
p++;
}
}
if(p==(a-1)/2){
return true;
} else{
return false;
}
}
}
C++ style:
bool checkPalindrome(const std::string& str)
{
size_t len = str.size();
for (size_t i = 0; i < len/2; i++)
{
if (str[i] != str[len-1-i])
return false;
}
return true;
}
C style:
bool checkPalindrome(const char* str)
{
size_t len = str ? strlen(str) : 0;
for (size_t i = 0; i < len/2; i++)
{
if (str[i] != str[len-1-i])
return false;
}
return true;
}
In either case, you may need to evaluate (ask) if an empty string should be considered a palindrome or not.
your code is too long. There's a simple way: iterating once over the elements of the string comparing the n-1 with 0 and n-2 with 1 and so on.
If two characters are not identical return false otherwise continue checking:
bool checkPalindrome(char* str) {
const int size = strlen(str);
for(int i(0), j(size) - 1); i < size / 2; i++, j--)
if(str[i] != str[j])
return false;
return true;
}
int main(){
char* str = "level";
cout << checkPalindrome(str);
cout << endl << endl;
return 0;
}
C++ version based on strings and iterators (only for the sake of completeness, the other answers are already very nice) :
bool checkPalindrome(const string& str) {
for (auto p = str.begin(),q = str.end(); p!=q && p!=q+1; p++ )
if (*p!=*--q) // if char from front doesn't match char from rear ?
return false; // then it's not a palindrome !
return true;
}
Explanations: the iterator p starts at the front of the string and q at the rear (after the last char). p will advance and q will go backwards. If p reaches q or if p has passed q (special case if the word has an even length), it's over and we can conclude a palindrome. But if before, there is any difference between the char at p and the char preceeding q , it's not a palindrome.
Online demo, with little test suite
Related
I've been working on a C++ program, I've made the logic but I'm unable to execute it. The question is:
Task: Write a program, using functions only, with the following features.
Program reads paragraph(s) from the file and stores in a string.
Then program counts the occurrence of each word in the paragraph(s) and stores all words with their number of occurrences.
If that word has appeared more than one time in whole string, it should store the word only once along its total occurrences.
The output described in above (in part 3) must be stored in a new file.
Sample input:
is the is and the is and the and is and only that is
Sample output:
is 5
the 3
and 4
only 1
that 1
I'll cut short to Occurrence program that I've written,
My logic is to store token into character array and then compare that array with main character array and do the increment:
void occurances() {
char* string = getInputFromFile();
char separators[] = ",.\n\t ";
char* token;
char* nextToken;
char* temp[100];
token = strtok_s(string, separators, &nextToken);
cout << temp;
int counter = 0;
int i = 0;
while ((token != NULL)) {
temp[i] = token;
i++;
for (int i = 0; i < strlen(string); i++) {
for (int j = 0; j < 100; j++) {
if ((strcmp(token, *temp)) == 0) {
counter++;
}
}
cout << temp << " : " << counter << endl;
}
if (token != NULL) {
token = strtok_s(NULL, separators, &nextToken);
}
}
}
This code is preposterous I know that, But please anyone be kind enough to give me a clue, actually I'm new to C++ . Thank you
If you store token into array this array should grow dynamically because the number of tokens is not known at the beginning. And according to the task description, you cannot use C++ standard containers, so, it is necessary to implement dynamic array manually, for example:
#include <iostream>
std::size_t increase_capacity_value(std::size_t capacity) {
if (capacity == 0) {
return 1;
}
else if (capacity < (SIZE_MAX / 2)) {
return capacity * 2;
}
return SIZE_MAX;
}
bool increase_array_capacity(char**& tokens_array, std::size_t*& tokens_count, std::size_t& capacity) {
const std::size_t new_capacity = increase_capacity_value(capacity);
if (new_capacity <= capacity) {
return false;
}
const std::size_t tokens_array_byte_size = new_capacity * sizeof(char*);
char** const new_tokens_array = static_cast<char**>(std::realloc(tokens_array, tokens_array_byte_size));
if (new_tokens_array == nullptr) {
return false;
}
tokens_array = new_tokens_array;
const std::size_t tokens_count_byte_size = new_capacity * sizeof(std::size_t);
std::size_t* const new_tokens_count = static_cast<std::size_t*>(std::realloc(tokens_count, tokens_count_byte_size));
if (new_tokens_count == nullptr) {
return false;
}
tokens_count = new_tokens_count;
capacity = new_capacity;
return true;
}
bool add_token(char* token, char**& tokens_array, std::size_t*& tokens_count, std::size_t& array_size, std::size_t& array_capacity) {
if (array_size == array_capacity) {
if (!increase_array_capacity(tokens_array, tokens_count, array_capacity)) {
return false;
}
}
tokens_array[array_size] = token;
tokens_count[array_size] = 1;
++array_size;
return true;
}
std::size_t* get_token_count_storage(char* token, char** tokens_array, std::size_t* tokens_count, std::size_t array_size) {
for (std::size_t i = 0; i < array_size; ++i) {
if (std::strcmp(token, tokens_array[i]) == 0) {
return tokens_count + i;
}
}
return nullptr;
}
bool process_token(char* token, char**& tokens_array, std::size_t*& tokens_count, std::size_t& array_size, std::size_t& array_capacity) {
std::size_t* token_count_ptr = get_token_count_storage(token, tokens_array, tokens_count, array_size);
if (token_count_ptr == nullptr) {
if (!add_token(token, tokens_array, tokens_count, array_size, array_capacity)) {
return false;
}
}
else {
++(*token_count_ptr);
}
return true;
}
int main() {
char string[] = "is the is and the is and the and is and only that is";
char separators[] = ",.\n\t ";
std::size_t token_array_capacity = 0;
std::size_t token_array_size = 0;
char** tokens_array = nullptr;
std::size_t* tokens_count = nullptr;
char* current_token = std::strtok(string, separators);
while (current_token != nullptr) {
if (!process_token(current_token, tokens_array, tokens_count, token_array_size, token_array_capacity)) {
break;
}
current_token = std::strtok(nullptr, separators);
}
// print the report only if all tokens were processed
if (current_token == nullptr) {
for (std::size_t i = 0; i < token_array_size; ++i) {
std::cout << tokens_array[i] << " : " << tokens_count[i] << std::endl;
}
}
std::free(tokens_array);
std::free(tokens_count);
}
godbolt.org
okay what if i want to store any token once, in an array and then replace it with new word while deleting duplicates in character array
It is also possible solution. But in general case, it is also necessary to allocate the memory dynamically for the current token. Because the lengths of tokens are also not known at the beginning:
void replace_chars(char* str, const char* chars_to_replace) {
while (str && *str != '\0') {
str = std::strpbrk(str, chars_to_replace);
if (str == nullptr) {
break;
}
const std::size_t number_of_delimiters = std::strspn(str, chars_to_replace);
for (std::size_t i = 0; i < number_of_delimiters; ++i) {
str[i] = '\0';
}
str += number_of_delimiters;
}
}
bool keep_token(char*& token_storage, const char* new_token) {
if (new_token == nullptr) {
return false;
}
const std::size_t current_token_len = token_storage ? std::strlen(token_storage) : 0;
const std::size_t requried_token_len = std::strlen(new_token);
if (token_storage == nullptr || current_token_len < requried_token_len) {
token_storage =
static_cast<char*>(std::realloc(token_storage, (requried_token_len + 1) * sizeof(char)));
if (token_storage == nullptr) {
return false;
}
}
std::strcpy(token_storage, new_token);
return true;
}
std::size_t count_tokens_and_replace(char* str, std::size_t str_len, const char* token) {
std::size_t number_of_tokens = 0;
std::size_t i = 0;
while (i < str_len) {
while (str[i] == '\0') ++i;
if (std::strcmp(str + i, token) == 0) {
replace_chars(str + i, token);
++number_of_tokens;
}
i += std::strlen(str + i);
}
return number_of_tokens;
}
int main() {
char string[] = "is the is and the is and the and is and only that is";
char separators[] = ",.\n\t ";
const std::size_t string_len = std::strlen(string);
replace_chars(string, separators);
std::size_t i = 0;
char* token = nullptr;
while (true) {
while (i < string_len && string[i] == '\0') ++i;
if (i == string_len || !keep_token(token, string + i)) break;
std::cout << token << " : " << count_tokens_and_replace(string + i, string_len - i, token) << std::endl;
}
std::free(token);
}
godbolt.org
But if it is known that the token length cannot be greater than N, it is possible to use the static array of chars to keep the current token. And it will allow to remove dynamic memory allocation from the code.
How should I go about finding the length of a char array in C++? I've tried two methods already, but they both have resulted in the wrong number of characters in the array. I've used strlen and the sizeof operator so far, to no avail.
void countOccurences(char *str, string word)
{
char *p;
string t = "true";
string f = "false";
vector<string> a;
p = strtok(str, " ");
while (p != NULL)
{
a.push_back(p);
p = strtok(NULL, " ");
}
int c = 0;
for (int i = 0; i < a.size(); i++)
{
if (word == a[i])
{
c++;
}
}
int length = sizeof(str); //This is where I'm having the problem
string result;
cout << length << "\n";
if (length % 2 != 0)
{
if (c % 2 == 0)
{
result = "False";
}
else
{
result = "True";
}
}
else
{
if (c % 2 == 0)
{
result = "True";
}
else
{
result = "False";
}
}
if (strlen(str) != 0)
{
cout << result;
}
}
int boolean()
{
char str[1000];
cin.getline(str, sizeof(str));
string word = "not";
countOccurences(str, word);
return 0;
}
sizeof(str) is wrong. It gives you the size of a pointer (str is a pointer), which is a fixed number, normally either 4 or 8 depending at your platform.
std::strlen(str) is correct, but strtok inserts a bunch of \0 into your array before you try to obtain the size. strlen will stop at the first \0, and give you the number of characters preceeding it.
Call strlen before strtok and save its return value to a variable.
Here you can find a modern c++ solution:
#include <iostream>
#include <string_view>
#include <string>
#include <type_traits>
template<typename String>
inline std::size_t StrLength(String&& str)
{
using PureString = std::remove_reference_t<std::remove_const_t<String>>;
if constexpr(std::is_same_v<char, PureString>){
return 1;
}
else
if constexpr(std::is_same_v<char*, PureString>){
return strlen(str);
}
else{
return str.length();
}
}
template<
typename String,
typename Lambda,
typename Delim = char
>
void ForEachWord(String&& str, Lambda&& lambda, Delim&& delim = ' ')
{
using PureStr = std::remove_reference_t<std::remove_reference_t<String>>;
using View = std::basic_string_view<typename PureStr::value_type>;
auto start = 0;
auto view = View(str);
while(true)
{
auto wordEndPos = view.find_first_of(delim, start);
auto word = view.substr(start, wordEndPos-start);
if (word.length() > 0){
lambda(word);
}
if (wordEndPos == PureStr::npos)
{
break;
}
start = wordEndPos + StrLength(delim);
}
}
int main() {
std::string text = "This is not a good sentence.";
auto cnt = 0;
ForEachWord(
text,
[&](auto word)
{
//some code for every word... like counting or printing
if (word == "not" ){
++cnt;
}
},
' '
);
std::cout << cnt << "\n";
}
The "end of a string" is the char '\0' check for that character to stop the search.
I will be given string. I can remove only 1 element from it. After removing it if the new string becomes palindrome I have to print "Yes" otherwise "No".
For example, I am given a string "abdbca". Here I can remove 5th index 'c' and make it palindrome and i have to print "Yes". On the other hand if the string is something like "abcd" I can not make it palindrome by removing only one character. Hence I have to print "No".
I tried to do it but my code is not efficient enough. Can anybody please suggest me a efficient way to do it? I have to check strings of 10^5 length in less than 2.5 seconds.
the way I tried to do it is shown bellow :
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#define REP(i,n) for(int i=0;i<n;i++)
#define MAX 100010
using namespace std;
bool isPalindrome(char abc[]){
int len = strlen(abc), lem = len/2;
for(int i=0,n=len-1;i<=lem;i++,n--) if(abc[i]!=abc[n]) return false;
return true;
}
int main()
{
int tc;
char str[MAX];
scanf("%d",&tc);
while(tc--){
scanf("%s", str);
int length = strlen(str), len = length - 1, z = length % 2, res = 0, ans = 0, b=0,lem = length / 2;
for(int i = 0;i<length;i++){
int n=0, m=1;
for(int x = 0, y = len;x<i && y!=i;x++,y--){
n++;
if(str[x]!=str[y]){
m=0; ++res;
break;
}
}
if(i>lem) for(int x=n,y=len-n-1;x<y;x++,y--){
if(str[x]!=str[y]){
m=0; ++res;
break;
}
}
else for(int x=n+1,y=len-n;x<y;x++,y--){
if(str[x]!=str[y]){
m=0; ++res;
break;
}
}
if(m==1) {printf("YES\n");b++;break;}
}
//if(length <= res) printf("NO\n");
if(b==0) printf("NO\n");
}
return 0;
}
Since you you only need to remove one character, you can do so in linear time by modifying palindrome checking. The idea is that you compare characters from the beginning to characters from the end and stop at the first mismatch. If you remove one character from the mismatching pair and get a palindrome, then return true, otherwise return false. I implemented the idea in C++ below.
#include<iostream>
#include<string>
using namespace std;
bool palindromeExists(string s)
{
int i = 0;
int j = s.length()-1;
while(i < j)
{
if(s[i] != s[j]) //first mismatch
break;
i++;
j--;
}
int tempj = j-1; //remove s[j]
int tempi = i;
while(tempi < tempj)
{
if(s[tempi] != s[tempj])
break;
tempi++;
tempj--;
}
if(tempi >= tempj) //palindrome found?
return true;
tempi = i+1; //remove s[i]
tempj = j;
while(tempi < tempj)
{
if(s[tempi] != s[tempj])
return false;
tempi++;
tempj--;
}
return true;
}
int main()
{
string s = "abca";
if(palindromeExists(s))
cout << "YES" << endl;
else
cout << "NO" << endl;
return 0;
}
This should return true if the string is already a palindrome, or if it can be a palindrome after the removal of one character. I hope I didn't miss any corner cases.
You can refer complete program in c++ here. Input the string to get the index of character to be removed. String reversal is performed in palim() function. It returns -1 if string is already palindrome.
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
bool palim(string s)
{
string s2;
s2=string(s.rbegin(),s.rend());
if(s2==s)
{
return true;
}
else
{
return false;
}
}
int check(string s)
{
int x;
if(s.length()%2==0)
{
for(int i=0,j=s.length()-1;i<s.length()/2,j>=s.length()/2;i++,j--)
{
if(s[i]!=s[j])
{
string s1=s;
s1.erase(j,1);
if(palim(s1))
{
x=j;
break;
}
else
{
string s1=s;
s1.erase(i,1);
if(palim(s1))
{
x=i;
break;
}
}
}
}
}
else
{
for(int i=0,j=s.length()-1;i<s.length()/2,j>s.length()/2;i++,j--)
{
if(s[i]!=s[j])
{
string s1=s;
s1.erase(j,1);
if(palim(s1))
{
x=j;
break;
}
else
{
string s1=s;
s1.erase(i,1);
if(palim(s1))
{
x=i;
break;
}
}
}
}
}
return x;
}
int main()
{
string s;
cin>>s;
if(palim(s))
{
cout<<"-1"<<endl;
}
else
{
cout<<check(s)<<endl;
}
return 0;
}
Similar to turingcomplete, but with sub functions:
bool isPalindrome(std::string::const_iterator& start, std::string::const_iterator& end)
{
while (start < end) {
--end;
if (*start != *end) {
return false;
}
++start;
}
return true;
}
bool test(const std::string& s)
{
auto start = s.begin();
auto end = s.end();
if (isPalindrome(start, end)) {
// If we remove the middle character of a palindrome,
// We still have a palindrome.
return true;
}
// Now test if there is a palindrome
// if we skip the mismatch char from the start or from the end.
auto start2 = start;
auto end2 = end;
++start2;
--end;
return isPalindrome(start, end) || isPalindrome(start2, end2);
}
Live example
bool isLangle(string);
int main()
{
string urstr;
cout <<"enter any str "<<endl;
cin>>urstr;
cout<<isLangle(urstr)<<endl;
return 0;
}
bool isLangle(string str){
for (int i=0; i<str.length(); i++)
{
if (str[i] == '<')
return true;
else
return false;
}
}
/*I am iterating through a html line but the function only checks for the first char and returns. I expect it to output true when I input "silver<" or any other string that contains left angle brackets
*/
Move return false; outside of the loop:
bool isLangle(string str) {
for (int i=0; i<str.length(); i++)
{
if (str[i] == '<')
return true;
}
return false;
}
You could look at the standard string::find function too:
bool isLangle(string str) { // or, better, const string&, see #Cyber's answer
size_t pos = str.find('<');
return (pos != string::npos);
}
You can use string::find to search for that character. If it was not found, it will return string::npos
bool isLangle(std::string const& str)
{
std::size_t found = str.find("<");
return found != std::string::npos;
}
I cannot figure out why this code isn't working. It doesn't even seem to be going through my for loops and nested loops. I'm very new to programing. I have been trying to answer Euler questions for practice. Sorry if my code is awful.
#include <iostream>
#include <string>
using namespace std;
bool isPalindrome(int x) {
string str = to_string(x);
for(string::reverse_iterator rit=str.rbegin(); rit!=str.rend(); ++rit) {
string pal = to_string(*rit);
if(pal == str) {
return true;
}else {
return false;
}
}
}
int main() {
int max[] = {0, 0};
for(int i=999; i>99; i--) {
for( int j =999; j>99; j--) {
int pal = i*j;
if(isPalindrome(pal) == true) {
max[1] = pal;
if(max[1] > max[0]){
max[0] = pal;
}
}
}
}
cout << max[0];
}
I think you need to return true in isPalindrome after comparing complete string. ie return true; should be outside for loop
And for checking largest 3 digit palindrome why are you passing int pal = i*j; ie for first iteration 999*999. Check this
bool isPalindrome(int x) {
string str = to_string(x);
string pal = str;
std::reverse(pal.begin(),pal.end());
if(pal == str) {
return true;
}else {
return false;
}
}