c++ palindrome program using array - c++

I am having a problem with my palindrome program. I am required to use arrays and show how a push and pop would work without .push or .pop. The trouble I am having is when I enter a 3 letter word it will say yes it is a palindrome but if I enter a word that is 4 or more characters it will say not a palindrome even if it is. ex. kayak. Dont see where I am going wrong.
#include <iostream>
#include <string>
using namespace std;
int main()
{
char original[13];
int stkptr=-1;
int x = strlen(original)-1;
cout <<"Enter a character"<<endl;
for( ++stkptr ; stkptr<13;stkptr++)
//store user input into the array
{
cin>>original[stkptr];
if(original[stkptr]=='0')
break;
cout<<original[stkptr]<<" Stack pointer is: "<<stkptr<<endl;
}
//POP
for (--stkptr; stkptr>=0;stkptr--)
cout<<original[stkptr]<<" Stack pointer is: "<<stkptr<<endl;
for(int i = 0; i <= x; i++)
{
if (original[i] == original[x-i])
{
continue;
}
else
{
cout<<"\nNot a palidrome\n"<<endl;
system("pause");
return 0;
}
}
cout << "\nIndeed Palidrome\n"<<endl;
system("pause");
return 0;
}

Though you overly complicated the logic, I will tell what is wrong the current code.
you are going wrong with x. You initialize it to string length when there is no "string" (Also, your char array should have a \0 at the end for strlen() to work). Assign stkptr-1 to x before pop and remove pop.
And in your loop you should iterate only till half of the array, since you are comparing char-by-char from begin and end
for(int i = 0; i <= x/2; i++)

bool checkIsPalindrome(string s){
int nLength = s.length();
string s1, s2;
if(nLength & 1) // is Odd
nLength--;
nLength = nLength/2;
//take the first half
s1 = s.substr(0,nLength);
//pop off the last half of characters into the string
for(int i = s.length()-1; i > nLength; i--)
s2+= s.at(i);
if(s1 == s2)
return true;
else
return false;
}

Related

Reversing string using stack (static array) in c++

i am new to this concept in c++
i am trying to reverse string using stack static array implementation in c++.
Input: qwerty
expected output: ytrewq
output which i am getting is: trewq
Can some one explain me why is this happening and any possible solution.
Here's my code
#include <iostream>
#include <string>
using namespace std;
#define SIZE 10
string arr[SIZE];
unsigned a = -1;
void push(char ch) {
a = a + 1;
arr[a] = ch;
}
void pop() {
a = a - 1;
}
void display() {
for (int j = a; j >= 0; j--)
cout << arr[j];
}
int main() {
string str;
getline(cin, str);
for (int i = 0; i < (str.length() - 1); i++)
push(str[i]);
display();
}
Remove the "-1" in :
for(int i=0;i<(str.length())-1;i++)
Else your array doesn't contains the last character.
I made the test without the -1, it works well.
The condition "< str.length()" is enough to loop on all string caracter.
In similar case, use the debugger to see what contains your variable. In these case the variable "arr" don't contains the last input caracter.
You push everything on the stack, so the last element can be popped first. Then do popping to fill a reversed strng. The stack should be a char array.
As this is typically a task, the rest is your puzzle.
Pop typically gives you the top element as:
char pop() {
char ch = arr[a];
--a;
return ch;
}
The correct way to reverse a string would be to do:
std::reverse(str.begin(), str.end());
But I think this might be homework/study so look at your output. You are just missing the last letter. That suggests the upper limit of your loop is wrong doesn't it?

Store and print characters but the output is not what is expected

I'm very new to C++. This code is supposed to store and print out every other number and stop when given the symbol #, but the output is weird. It outputs something like 0x6fdd90. Any help would be much appreciated.
#include <iostream>
#include <string>
using namespace std;
int main(){
string s[11];
int count = 1, wordlength = 0;
char a;
cin.get(a);
while (a != '#'){
if (wordlength == 10)
break;
if (count % 2 != 0){
s[wordlength] = a;
wordlength++;
}
cin.get(a);
count++;
}
s[wordlength] = '\0';
cout << s;
return 0;
}
cout << s;
Is printing the address of the 1st element in your array s.
You may want to loop through s to print all the elements.
for (int i =0; i < sizeof(s)/sizeof(s[0]); i++) {
cout<< s[i] << "\n";
}
It is better to user char array than string array for your purpose.

How to display duplicate characters in a string in C++?

I am working on some code for a class that requires me to output duplicates in a string. This string can have any ascii character but the output needs to show only the repeated character and the total number of times it repeats.
Here are some sample inputs and outputs
mom, m:2
taco, No duplicates
good job, o:3
tacocat, t:2 c:2 a:2
My code works for all but the last test case, the t:2 and a:2 appears twice, Now I have come to the conclusion that I need to store duplicated characters somewhere and run a check on that list to see if that duplicate has already been printed so I tried using a vector.
My method is to push the character into the vector as the duplicates are printed and if a character is already in the vector then it is skipped in the printing. But I have not been able to find a way to this. I tried to use the find() from #include<algorithm> but got a syntax error that I am unable to fix. Is there a function that I can apply for this? Or am I going about this in a bad way?
I found the implementation of find() here & I looked here but they don't match and it breaks my code completely when I try to apply it.
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
vector <char> alreadyprintedcharacters;
void findrepeats(string const&);
int main()
{
string input;
cout << "Enter the input : ";
getline(cin, input);
findrepeats(input);
return 0;
}
void findrepeats(string const &in)
{
int trackerOfDuplicates = 0;
int asciiArray[256];
char ch;
int charconv;
for (int i = 0; i < 256; i++) // creates my refference array for the comparison and sets all the values equal to zero
asciiArray[i] = 0;
for (unsigned int i = 0; i < in.length(); i++)
{
ch = in[i];
charconv = static_cast<int>(ch);
if (asciiArray[charconv] == 0)
{
asciiArray[charconv] = 1;
}
else if (asciiArray[charconv] > 0)
{
asciiArray[charconv] = asciiArray[charconv]++;
}
}
bool trip = false;
for (unsigned int i = 0; i < in.length(); i++)
{
char static alreadyprinted;
char ch = in[i];
if ((asciiArray[ch] > 1) && (ch != alreadyprinted) && (find(alreadyprintedcharacters.begin(), alreadyprintedcharacters.end(), ch)!= alreadyprintedcharacters.end()))// change reflected HERE
{
cout << in[i] << " : " << asciiArray[ch] << endl;//???? maybe a nested loop
trip = true;
alreadyprinted = ch;
alreadyprintedcharacters.push_back(alreadyprinted);
}
}
if (trip == false)
cout << "No repeated characters were found.\n";
}
Your code works fine for me (gives the correct output for tacocat) if you fix the error related to std::find:
std::find doesn't return a bool, it returns an iterator (in your case, a std::vector<char>::iterator). If you want to check if std::find found something, you should compare it to alreadyprintedcharacters.end(), because that's what std::find returns if it didn't find something.
You can create an integer array of 256 and initialize it to 0 at first. Then loop over characters in the string and increment each index that corresponds to that letter. In the end, you can print out letters that have values greater than 1. Just change your findrepeats function to the following:
void findrepeats(string const &in)
{
int asciiArray[256];
char ch;
int charconv;
bool foundAny = false;
for (int i = 0; i < 256; i++) asciiArray[i] = 0;
for (unsigned int i = 0; i < in.length(); i++)
{
ch = in[i];
charconv = static_cast<int>(ch);
asciiArray[charconv]++;
}
for (unsigned int i = 0; i < 256; i++)
{
char static alreadyprinted;
if (asciiArray[i] > 1)
{
foundAny = true;
cout << static_cast<char>(i) << " : " << asciiArray[i] << endl;
}
}
if (!foundAny)
cout << "No repeated characters were found.\n";
}
You have to make following changes in your code
change the loop body where you are updating the reference array for the comparison and sets all the values like this:
//your code
else if (asciiArray[charconv] > 0)
{
asciiArray[charconv] = asciiArray[charconv]++;
}
in the above code the value of asciiArray[charconv] doesn't change because it is a post increment asciiArray[charconv]++; , either change it to a pre increment ++asciiArray[charconv]; or write asciiArray[charconv] = asciiArray[charconv]+1;
Here is a link to this why it doesn't increment.
Also you can change the loop like this,more simplified:
for (unsigned int i = 0; i < in.length(); i++)
{
ch = in[i];
charconv = static_cast<int>(ch);
asciiArray[charconv]++;
}
change the type of found to std::vector<char>::iterator coz find returns an iterator to the first element in the range that compares equal to val & if no elements match, the function returns last.
std::vector<char>::iterator found = find(alreadyprintedcharacters.begin(), alreadyprintedcharacters.end(), ch);
Then your condition should be like
if((asciiArray[ch] > 1) && (ch!=alreadyprinted) && (found == alreadyprintedcharacters.end()))
I don't quite get why you need all of that code (given you stated you can't use std::map).
You declared an array of 256 and set each item to 0, which is OK:
for (int i = 0; i < 256; i++)
asciiArray[i] = 0;
Now the next step should be simple -- just go through the string, one character at a time, and increment the associated value in your array. You seem to start out this way, then go off on a tangent doing other things:
for (unsigned int i = 0; i < in.length(); i++)
{
ch = in[i]; // ok
asciiArray[ch]++;
We can set a boolean to true if we discover that the character count we just incremented is > 1:
bool dup = false;
for (unsigned int i = 0; i < in.length(); i++)
{
ch = in[i]; // ok
asciiArray[ch]++;
if ( asciiArray[ch] > 1 )
dup = true;
}
That is the entire loop to preprocess the string. Then you need a loop after this to print out the results.
As to printing, just go through your array only if there are duplicates, and you know this by just inspecting the dup value. If the array's value at character i is > 1, you print the information for that character, if not, skip to the next one.
I won't show the code for the last step, since this is homework.
Just met similar question last week, here is what I did, maybe not a best solution, but it did work well.
string str("aer08%&#&%$$gfdslh6FAKSFH");
vector<char> check;
vector<int> counter;
//subscript is the bridge between charcheck and count. counter[sbuscript] store the times that check[subscript] appeared
int subscript = 0;
bool charisincheck = false;
for (const auto cstr : str) //read every char in string
{
subscript = 0;
charisincheck = false;
for (const auto ccheck : check) // read every element in charcheck
{
if (cstr == ccheck)//check if the char get from the string had already existed in charcheck
{
charisincheck = true; //if exist, break the for loop
break;
}
subscript++;
}
if (charisincheck == true) //if the char in string, then the count +1
{
counter[subscript] += 1;
}
else //if not, add the new char to check, and also add a counter for this new char
{
check.push_back(cstr);
counter.push_back(1);
}
}
for (decltype(counter.size()) i = 0; i != counter.size(); i++)
{
cout << check[i] << ":" << counter[i] << endl;
}met
import java.util.*;
class dublicate{
public static void main(String arg[]){
Scanner sc =new Scanner(System.in);
String str=sc.nextLine();
int d[]=new int[256];
int count=0;
for(int i=0;i<256;i++){
d[i]=0;
}
for(int i=0;i<str.length();i++){
if(d[str.charAt(i)]==0)
for(int j=i+1;j<str.length();j++){
if(str.charAt(i)==str.charAt(j)){
d[str.charAt(i)]++;
}
}
}
for(char i=0;i<256;i++){
if(d[i]>0)
System.out.println(i+" :="+(d[i]+1));
}
}
}
//here simple code for duplicate characters in a string in C++
#include<iostream.h>
#include<conio.h>
#include<string.h>
void main(){
clrscr();
char str[100];
cin>>str;
int d[256];
int count=0;
for(int k=0;k<256;k++){
d[k]=0;
}
for(int i=0;i<strlen(str);i++){
if(d[str[i]]==0)
for(int j=i+1;j<strlen(str);j++){
if(str[i]==str[j]){
d[str[i]]++;
}
}
}
for(int c=0;c<256;c++){
if(d[c]>0)
cout<<(char)c<<" :="<<(d[c]+1)<<"\n";
}
getch();
}

I'm having trouble with my conversion program

For my class, I am to write a program in C++ that converts each character in a sentence to the opposite case (upper to lower, lower to upper). We are supposed to use arrays and a user-defined method, and this is what I came up with:
#include <iostream>
using namespace std;
// declare variables
int count = 0; // array counter
int i = 0; // loop control
char ch[100]; // each character entered will be stored in this array
char newCh[100]; // this will hold each character after its case has been changed
main()
{
cout << "Enter a sentence." << endl; // prompts user
while ( ch[count] != '\n' ) // loop continues until "enter" is pressed
{
cin >> ch[count]; // store each character in an array
count += 1; // increment counter
}
int convert(); // call user-defined function
}
// even though it isn't necessary, we are using a user-defined function to perform the conversion
int convert()
{
for ( i = 0; i >= 0; i++ )
{
if ( (ch[i] > 64) and (ch[i] < 91)
)
{
newCh[i] = tolower(ch[i]);
}
else
{
newCh[i] = toupper(ch[i]);
}
cout << newCh[i];
}
}
I'm not sure why, but it doesn't work. I don't believe that my while loop is terminating and executing the rest of the program. Any advice would be greatly appreciated.
The loop condition in while ( ch[count] != '\n' ) is wrong, as all entries in ch will be initialized to zero by the compiler, and as you increase count inside the loop the condition will never be false and you have an infinite loop, causing you to write beyond the limits of the array.
And writing beyond the limits of an array leads to undefined behavior, and will cause your whole program to be illegal.
I suggest you learn about std::string and std::getline.
There's a problem with your for loop - you want for ( i = 0; i < count; i++ ). Also your function can be void and you need to pass the count value into it (and you just need to invoke it with convert() without int or void in front.
I have rewrite your code with some modification. The following code works perfectly in my machine -
#include <iostream>
#include<cstdio>
#include<string>
using namespace std;
void convert(char *, int);
string line;
char input[1024];
char output[1024];
main()
{
cout << "Enter a sentence." << endl;
while (getline(cin, line)) { // POINT 1
cout<< line<<endl;
//converting to char array since you need char array
//POINT 2
for(int i=0; i< line.length(); i++){
input[i]=line[i];
}
convert(input, line.length());
cout<<output<<endl;
input[1024] = {0}; //POINT 3
output[1024] = {0};
}
}
//Custom Convert Method
void convert(char input[], int size){
for(int i = 0; i < size; i++){
if(input[i] >= 'a' && input[i] <= 'z'){
output[i] = toupper(input[i]);
} else {
output[i] = tolower(input[i]);
}
}
}
Note some points (in my comment) here -
POINT 1: reading a n entire line using getline() method. Here line is a string
POINT 2: since you need char array here I am converting the string line to char array input[1024]
POINT 3: input and output array are being reset to work with the next value;
Output of the code:
"Ctrl+C" will terminate the program
Hope it will help you.
Thanks a lot.

Algorithm to print asterisks for duplicate characters [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I was asked this question in an interview:
Given an array with the input string, display the output as shown below
Input
INDIA
Output
INDA
****
*
I iterated through the array and stored each character as a key in std::map with value as number of occurrence. Later I iterate the map and print the asteriks and reduce the value in the map for each character.
Initially, I was asked not to use any library. I gave a solution which needed lot of iterations. For every character, iterate the complete array till the index to find previous occurrences and so on.
Is there any better way, e.g. better complexity, such as faster operation, by which this can be achieved?
Essentially what you are asking is how to implement map without using the STL code, as using some kind of data structure which replicates the basic functionality of map is pretty much the most reasonable way of solving this problem.
There are a number of ways of doing this. If your keys (here the possible characters) come from a very large set where most elements of the set don't appear (such as the full Unicode character set), you would probably want to use either a tree or a hash table. Both of these data structures are very important with lots of variations and different ways of implementing them. There is lots of information and example code about the two structures around.
As #PeterG said in a comment, if the only characters you are going to see are from a set of 256 8-bit chars (eg ASCII or similar), or some other limited collection like the upper-case alphabet you should just use an array of 256 ints and store a count for each char in that.
here is another one:
You can see it working HERE
#include <stdio.h>
int main()
{
int i,j=0,f=1;
char input[50]={'I','N','D','I','A','N','A','N'};
char letters[256]={0};
int counter[256]={0};
for(i=0;i<50;i++)
{
if(input[i])
counter[input[i]]++;
if(counter[input[i]]==1)
{
putchar(input[i]);
letters[j]=input[i];
j++;
}
}
putchar('\n');
while(f)
{
f=0;
for(i=0;i<j;i++)
if(counter[letters[i]])
{
putchar('*');
counter[letters[i]]--;
f=1;
}
else
{
putchar(' ');
}
putchar('\n');
}
return 0;
}
If the alphabet under consideration is fixed, it can be done in two passes:
Create an integer array A with the size of the alphabet, initialized with all zeros.
Create a boolean array B with size of the input, initialize with all false.
Iterate the input; increase for every character the corresponding content of A.
Iterate the input; output a character if its value it B is false and set its value in B to true. Finally, output a carriage return.
Reset B.
Iterate input as in 4., but print a star if if the character's count in A is positive, then decrease this count; print a space otherwise.
Output a carriage return; loop to 5 as long as there are any stars in the output generated.
This is interesting. You shouldnt use a stl::map because that is not a hashmap. An stl map is a binary tree. An unordered_map is actually a hash map. In this case we dont need either. We can use a simple array for char counts.
void printAstr(std::string str){
int array[256] ;// assumining it is an ascii string
memset(array, 0, sizeof(array));
int astrCount = 0;
for(int i = 0; i < str.length()-1; i++){
array[(int) str[i]]++;
if(array[(int) str[i]] > 1) astrCount++;
}
std::cout << str << std::endl;
for(int i = 0; i < str.length()-1;i++) std::cout << "* ";
std::cout << std::endl;
while(astrCount != 0){
for(int i= 0; i< str.length() - 1;i++){
if(array[(int) str[i]] > 1){
std::cout << "* ";
array[(int) str[i]]--;
astrCount--;
}else{
std::cout << " ";
}
}
std::cout << std::endl;
}
}
pretty simple just add all values to the array, then print them out the number of times you seem them.
EDIT: sorry just made some logic changes. This works now.
The following code works correctly. I am assuming that you can't use std::string and take note that this doesn't take overflowing into account since I didn't use dynamic containers. This also assumes that the characters can be represented with a char.
#include <iostream>
int main()
{
char input[100];
unsigned int input_length = 0;
char letters[100];
unsigned int num_of_letters = 0;
std::cin >> input;
while (input[input_length] != '\0')
{
input_length += 1;
}
//This array acts like a hash map.
unsigned int occurrences[256] = {0};
unsigned int max_occurrences = 1;
for (int i = 0; i < input_length; ++i)
{
if ((occurrences[static_cast<unsigned char>(input[i])] += 1) == 1)
{
std::cout<< " " << (letters[num_of_letters] = input[i]) << " ";
num_of_letters += 1;
}
if (occurrences[static_cast<unsigned char>(input[i])] > max_occurrences)
{
max_occurrences = occurrences[static_cast<unsigned char>(input[i])];
}
}
std::cout << std::endl;
for (int row = 1; row <= max_occurrences; ++row)
{
for (int i = 0; i < num_of_letters; ++i)
{
if (occurrences[static_cast<unsigned char>(letters[i])] >= row)
{
std::cout << " * ";
}
else
{
std::cout << " ";
}
}
std::cout << std::endl;
}
return 0;
}
The question is marked as c++ but It seems to me that the answers not are all quite C++'ish, but could be quite difficult to achieve a good C++ code with a weird requirement like "not to use any library". In my approach I've used some cool C++11 features like in-class initialization or nullptr, here is the live demo and below the code:
struct letter_count
{
char letter = '\0';
int count = 0;
};
int add(letter_count *begin, letter_count *end, char letter)
{
while (begin != end)
{
if (begin->letter == letter)
{
return ++begin->count;
}
else if (begin->letter == '\0')
{
std::cout << letter; // Print the first appearance of each char
++begin->letter = letter;
return ++begin->count;
}
++begin;
}
return 0;
}
int max (int a, int b)
{
return a > b ? a : b;
}
letter_count *buffer = nullptr;
auto testString = "supergalifragilisticoespialidoso";
int len = 0, index = 0, greater = 0;
while (testString[index++])
++len;
buffer = new letter_count[len];
for (index = 0; index < len; ++index)
greater = max(add(buffer, buffer + len, testString[index]), greater);
std::cout << '\n';
for (int count = 0; count < greater; ++count)
{
for (index = 0; buffer[index].letter && index < len; ++index)
std::cout << (count < buffer[index].count ? '*' : ' ');
std::cout << '\n';
}
delete [] buffer;
Since "no libraries are allowed" (except for <iostream>?) I've avoided the use of std::pair<char, int> (which could have been the letter_count struct) and we have to code many utilities (such as max and strlen); the output of the program avobe is:
supergaliftcod
**************
* ******* *
* *** *
* *
*
*
My general solution would be to traverse the word and replace repeated characters with an unused nonsense character. A simple example is below, where I used an exclamation point (!) for the nonsense character (the input could be more robust, some character that is not easily typed, disallowing the nonsense character in the answer, error checking, etc). After traversal, the final step would be removing the nonsense character. The problem is keeping track of the asterisks while retaining the original positions they imply. For that I used a temp string to save the letters and a process string to create the final output string and the asterisks.
#include <iostream>
#include <string>
using namespace std;
int
main ()
{
string input = "";
string tempstring = "";
string process = "";
string output = "";
bool test = false;
cout << "Enter your word below: " << endl;
cin >> input;
for (unsigned int i = 0; i < input.length (); i++)
{ //for the traversed letter, traverse through subsequent letters
for (unsigned int z = i + 1; z < input.length (); z++)
{
//avoid analyzing nonsense characters
if (input[i] != '!')
{
if (input[i] == input[z])
{ //matched letter; replace with nonsense character
input[z] = '!';
test = true; //for string management later
}
}
}
if (test)
{
tempstring += input[i];
input[i] = '*';
test = false; //reset bool for subsequent loops
}
}
//remove garbage symbols and save to a processing string
for (unsigned int i = 0; i < input.size (); i++)
if (input[i] != '!')
process += input[i];
//create the modified output string
unsigned int temp = 0;
for (unsigned int i = 0; i < process.size (); i++)
if (process[i] == '*')
{ //replace asterisks with letters stored in tempstring
output += tempstring[temp];
temp++;
}
else
output += process[i];
//output word with no repeated letters
cout << output << endl;
//output asterisks equal to output.length
for (unsigned int a = 0; a < output.length (); a++)
cout << "*";
cout << endl;
//output asterisks for the letter instances removed
for (unsigned int i = 0; i < process.size (); i++)
if (process[i] != '*')
process[i] = ' ';
cout << process << endl << endl;
}
Sample output I received by running the code:
Enter your word below:
INDIA
INDA
****
*
Enter your word below:
abcdefgabchijklmnop
abcdefghijklmnop
****************
***
It is possible just using simple array to keep count of values.
#include<iostream>
#include<string>
using namespace std;
int main(){
string s;
char arr[10000];
cin>>s;
int count1[256]={0},count2[256]={0};
for(int i=0;i<s.size();++i){
count1[s[i]]++;
count2[s[i]]++;
}
long max=-1;
int j=0;
for(int i=0;i<s.size();++i){
if(count1[s[i]]==count2[s[i]]){ //check if not printing duplicate
cout<<s[i];
arr[j++]=s[i];
}
if(count2[s[i]]>max)
max=count2[s[i]];
--count1[s[i]];
}
cout<<endl;
for(int i =1; i<=max;++i){
for(int k=0;k<j;++k){
if(count2[arr[k]]){
cout<<"*";
count2[arr[k]]--;
}
else
cout<<" ";
}
cout<<endl;
}
}