Stack ADT C++ Functions - c++

So recently i started to getting into stacks ADT in c++ and i am trying to create a small program which the user inserts a string and the output should be in reverse order
But something is going wrong with my code or i am missing something but i cant figure it out
My output so far is that i can insert the string but then it just output the couts "Reverse string" and nothing else
i tried several ways like to change the pop function but nothing changed
Thank you for any help
#include <iostream>
#include <string>
using namespace std;
class ReverseString {
public:
string str[13];
int topStack;
ReverseString() {
topStack = -1;
}
string Push() {
//char item;
string str("");
cout << "Enter a string " << endl;
cin >> str;
for (char ch : str) {
topStack++;
// str[topStack] = item;
return str;
}
}
string Pop() {
string temp= str[topStack];
for (int i = 0; i <= 13; i++) {
str[i] = temp;
//temp = str[i - 1];
cout << "Reverse String: " << str[topStack] << endl;
return temp;
}
}
};
// main function
int main() {
ReverseString str;
str.Push();
str.Pop();
return 0;
}

Related

Reversing the Character Case of a string

I'm stuck on a particular problem. I'm trying to take a string, and reverse the character cases in the string.
For Example: "HaVinG FuN" should flip to "hAvINg fUn."
I think it has something to do with my loop or my If/Else statements. What am I missing? All capitalized characters come out capitalized still. All lower case characters also come out capitalized as well... My other two functions are behaving correctly, but not my reverseFunct function... FYI I've omitted the other functions to try to cut-down on clutter and focus on my problem.
#include "stdafx.h"
#include <string>
#include <iostream>
#include <cctype>
#include <cstring>
using namespace std;
// Function Prototypes
void upperFunct(char *);
void lowerFunct(char *);
void reverseFunct(char *);
int main()
{
cout << "Enter a string: " << endl;
char ltrs [300];
cin.getline(ltrs, 300);
char *ptr = nullptr;
ptr = ltrs;
upperFunct(ptr);
lowerFunct(ptr);
reverseFunct(ptr);
return 0;
}
//----------------------------------//
void upperFunct(char *ltrptr)
{
int count = 0;
while (ltrptr[count] != '\0')
{
ltrptr[count] = toupper(ltrptr[count]);
count++;
}
{
cout << "---> toupper function: " << ltrptr << endl;
}
}
//------------------------------------//
void lowerFunct(char *ltrptr)
{
int count = 0;
while (ltrptr[count] != '\0')
{
ltrptr[count] = tolower(ltrptr[count]);
count++;
}
cout << "---> tolower function: " << ltrptr << endl;
}
//------------------------------------//
void reverseFunct(char *ltrptr) // <-----NOT REVERSING CHARACTERS
{
int count = 0;
while (ltrptr[count] != '\0')
{
if (isupper(ltrptr[count]))
{
ltrptr[count] = tolower(ltrptr[count]);
}
else
{
ltrptr[count] = toupper(ltrptr[count]);
}
count++;
}
cout << "---> reverse function: " << ltrptr << endl;
}
Your check for lowercase letters reads as
else if (islower(ltrptr[count]));
Notice the extra semicolon.
This semicolon terminates the if statement, and thus the succeeding conversion to uppercase is not a then-clause to this if statement but rather is executed unconditionally on every character.
Change like this
// Function Prototypes "HaVinG FuN" should flip to "hAvINg fUn."
void reverseFunct(char *);
int main()
{
//cout << "Enter a string: " << endl;
char ltrs[300] = "HaVinG FuN";
//cin.getline(ltrs, 300);
char *ptr = nullptr;
ptr = ltrs;
reverseFunct(ptr);
ptr = nullptr;
return 0;
}
void reverseFunct(char *ltrptr) // <-----NOT REVERSING CHARACTERS
{
int count = 0;
while (ltrptr[count] != '\0')
{
if (isupper(ltrptr[count]))
{
ltrptr[count] = tolower(ltrptr[count]);
}
else
{
ltrptr[count] = toupper(ltrptr[count]);
}
count++;
}
cout << "---> reverse function: " << ltrptr << endl;
}
You're writing C code. Here's a C++ way to do it:
#include <string>
#include <algorithm>
char reverse_case_char(char c) {
const auto uc = static_cast<unsigned char>(c); // Sic.
return ::isupper(uc)? ::tolower(uc): ::toupper(uc);
}
void reverse_case(std::string& str) {
std::transform(str.begin(), str.end(), str.begin(), reverse_case_char);
}
#include <cassert>
int main()
{
std::string fun = "HaVinG FuN";
reverse_case(fun);
assert(fun == "hAvINg fUn");
return 0;
}
Others have already pointed out the mistake in your code so no need to repeat that. Instead this answer will give some alternative ways of implementing the task.
Your code is more C-style than C++ style. C++ has a number of functions/features that will allow you to write this in much shorter forms.
char ltrs[300] = "HaVinG FuN";
for (auto& ch : ltrs) ch = islower(ch) ? toupper(ch) : tolower(ch);
std::cout << ltrs << std::endl;
or
char ltrs[300] = "HaVinG FuN";
std::for_each(ltrs, ltrs + strlen(ltrs), [](char& ch)
{ ch = islower(ch) ? toupper(ch) : tolower(ch); });
std::cout << ltrs << std::endl;
or using the std::string
std::string str("HaVinG FuN");
for (auto& ch : str) ch = islower(ch) ? toupper(ch) : tolower(ch);
std::cout << str << std::endl;
Using these C++ functions/features makes the program shorter, easier to understand and the risk of bugs is lower.
Thanks for the help!!! I ended up figuring out my answer, while being able to maintain my less-than elegant code that is fitting with my class. Bipll ended up giving me what I was after, something to think about in terms that my original array was being modified each time.
I realize that my solution is sloppy and not appropriate for a work environment, but it is in-line with my homework assignment, as our teacher is encouraging us to learn C++ from the ground-up, not getting too much direct answers from places like SO. So I'm glad I learned a bit from here, as well as an indirect way to help me see my issues.
I ended up making a copy of my original array, and just passing that copy to my last reversing function. I was able to use the original array for the first 2 functions because the 1st function capitalized each character in the array, while the 2nd made them all lowercase. The 3rd function, the reverse, therefore had to have access to the original array, but in the 3rd order. The easiest way for a noob like me, given where I am in the class, was to make a copy of the 1st array and use that for the 3rd function.
//Snippet of code I needed
int main()
{
int index = 0;
cout << "Enter a string: " << endl;
const int Size = 300;
char ltrs[Size];
cin.getline(ltrs, Size);
char arrayCopy[Size];
char *ptr = nullptr;
char *ptr2 = nullptr;
ptr = ltrs;
//Copy of ltrs Array
//----------------------------------//
while (ptr[index] != '\0') //
{ //
arrayCopy[index] = ptr[index]; //
index++; //
} //
arrayCopy[index] = '\0'; //
//
ptr2 = arrayCopy; //
//----------------------------------//
return 0;
}
// Function to Reverse
void reverseFunct(char *ltrptr)
{
int count = 0;
while (ltrptr[count] != '\0')
{
if (isupper(ltrptr[count]))
{
ltrptr[count] = tolower(ltrptr[count]);
}
else
{
ltrptr[count] = toupper(ltrptr[count]);
}
count++;
}
cout << "---> reverse function: " << ltrptr << endl;
}

c++ ifstream , Reading from file crashes

At the beginning I apologize for my English.
I was trying to write a XML Parser that I encountered a weird problem.
to explain my problem I should say, I have a xml parser class that has an ifstream member. And this class has a function which reads until it reaches an open tag matching with the given input.
this is the parser class I was working on:
// XMLParser.cpp
#include <fstream>
#include "Stack.h"
using namespace std;
class XMLParser{
private:
int charReadRate = 3;
public:
ifstream *stream;
XMLParser(string add){
stream = new ifstream(add); // open input stream
}
void nextTag(string tag){
// find the first occurance of open-tag with name 'tag'
cout << "nextTag\n";
char * readData;
string tagName="";
stream->read(readData, charReadRate);
int len = string(readData).length();
int i = 0;
// cout << len << endl;
while(true){
if((*readData) == '<'){
readData++;
i++;
while(*readData != '>'){
tagName+=*readData;
readData++;
i++;
if(i>=len){
if(stream->eof()){
return ; // error didn't find
}
stream->read(readData, charReadRate);
// cout << readData << endl;
len = string(readData).length();
i = 0;
}else{
if(tagName == tag){
// cout << "find\n";
stream->seekg(i-len, ios::cur);
return;
}
}
}
}else{
readData++;
i++;
if(i>=len){
if(stream->eof()){
return ; // error didn't find
}
stream->read(readData, charReadRate);
len = string(readData).length();
i = 0;
}
}
}
}
};
in the nextTag function I read the file until I reach the open tag which name's matches with the given input.
and here is my main function
int main(){
XMLParser parser("test.xml");
cout << "ready\n";
parser.nextTag("Log");
char *c;
parser.stream->read(c,3);
cout << c << endl;
return 0;
}
I have figured out that the program crashes when the fifth line of the main function [parser.stream->read(c,3);] is executed.
I wonder why this happens?
The char pointer you pass to ifstream::read is not initialized and thus points to an invalid memory region, causing your program to crash. You need it to point to a buffer you allocated:
int main(){
XMLParser parser("test.xml");
cout << "ready\n";
parser.nextTag("Log");
char c[3];
parser.stream->read(c,3);
cout << c << endl;
return 0;
}

how to push and pop elements read from a textfile to an array in c++ and output the stack in revserse order?

Hi I am new to c++ and am having trouble understanding on how I would push and pop elements read from a text file to an array and displaying those elements in reverse order for example if i have a text file called hero.txt with elements Goku Luffy Naruto I would like the output to be Naruto Luffy Goku
this is what I have so far
string hero[100]; // array to store elements
int count=0;
int main()
{
fstream myfile;
string nameOffile;
string text;
string mytext;
cout << "Enter name of file" << endl;
cin >> nameOffile
myfile.open(nameOffile.c_str());
if (!myfile)
{
cerr << "error abort" << endl;
exit(1);
}
while (myfile >> text )
{
Push(mytext); //Note I know this is wrong I just don't know how to write it in a manner that will push the first element of the textfile to the top
}
myfile.close();
while(hero[count]=="")
{
//Again I know these two lines are incorrect just don't know how to implement in correct manner
cout <<hero[0] << " " <<endl;
Pop(mytext);
}
}
// Function for push
void Push(string mytext)
{
count = count + 1;
hero[count] = mytext;
}
void Pop(string mytext)
{
if(count=0)
{
mytext = " ";
}
else
{
mytext = hero[count];
count = count - 1;
}
}
Normally, a stack will begin with index = -1 to indicate that the stack is empty. So you need to replace
int count = 0
with
int count = -1
After you do all the pushing, your stack will look like this:
hero[0] = "Goku"
hero[1] = "Luffy"
hero[2] = "Naruto"
Now, to print it out in reverse order, you can just loop from the last index to the first. After pushing all the heroes string, count is now equal to 2. The last heroes will be at index = 0. So you can rewrite the loop as
while(count >= 0)
{
cout << hero[count] << " " <<endl;
Pop();
}
Your Pop function is also incorrect. In the if statement, you will replace the value of count to 0. What you need to do in Pop is just to decrement the value of count.
So you can rewrite it as
void Pop()
{
count = count - 1;
}
The vector class defined in the standard library acts like a stack.
For example:
// include the library headers
#include <vector>
#include <string>
#include <iostream>
// use the namespace to make the code less verbose
using namespace std;
int main()
{
// declare the stack
vector<string> heroStack;
// insert the elements
heroStack.push_back("Goku");
heroStack.push_back("Luffy");
heroStack.push_back("Naruto");
// print elements in reverse order
while(!heroStack.empty())
{
// get the top of the stack
string hero = heroStack.back();
// remove the top of the stack
heroStack.pop_back();
cout << hero << endl;
}
}
ok let's tart by improving your functions
push function works good but just change the order of it to be like this
void Push(string mytext)
{
hero[count] = mytext; //now you will start at index 0
count = count + 1;
}
pop function should be like this
you need to return a string value and you don't need to pass a parameter
string Pop()
{
if(count == 0)
{
return "";
}
else
{
count = count - 1;
mytext = hero[count];
return mytext;
}
}
now you are functions are ready let's use them
you are using the push function correctly in your main
we need to change the while which displays the output
it should be like this
while(true)
{
tempText = pop(); // this function will get you the last element and then remove it
if ( tempText == "" ) // now we are on top of the stack
break;
cout <<tempText << " " <<endl;
}
#include "stdafx.h"
#include <fstream>
#include <stack>
#include <string>
#include <iostream>
class ReadAndReversePrint
{
std::stack<std::string> st;
std::ifstream file;
public:
ReadAndReversePrint(std::string path)
{
file.open(path);
if (file.fail())
{
std::cout << "File Open Failed" << std::endl;
return;
}
std::string line;
while (!file.eof())
{
file >> line;
st.push(line);
}
file.close();
std::cout << "Reverse printing : " << std::endl;
while (!st.empty())
{
std::cout << st.top().c_str() << "\t";
st.pop();
}
std::cout << std::endl;
}
};
int main()
{
ReadAndReversePrint rrp("C:\\awesomeWorks\\input\\reverseprint.txt");
return 0;
}

Compilier not Entering Functions Properly

I am trying to write a program that calls a custom function. Unfortunately, once it enters the function, it ceases to print what I told it to and gets stuck indefinitely. (I run a mac 10.9, and the newest Xcode)
The two functions are:
int main(void)
{
string filePath;
treeNode* root;
int words;
//filePath = getFileName();
cout << "Choosing pathway.\n";
root = readIn(words, "/Users/Noah/Desktop/SmallFile.txt");
cout << "File read.\n";
root->printInOrder(root);
}
and:
treeNode* readIn (int& count, string file)
{
cout << "Here. ";
treeNode* root = new treeNode;
string insert;
ifstream reading;
count = 0; // DECLARE VARIABLES!
int size = 0;
cout << "Made variables. ";
reading.open(file); // Open and check file
cout << "File up. ";
//for (int i = 0; i < 15; i++) // See coder's note at top.
while (!reading.eof())
{
cout << "In loop. ";
char c = reading.get(); // Obtain character to check
if (isalnum(c))
{
insert += c; // Word Storage update
}
else
{
if (count != 0)
{
insertWord(insert, root); // Insert word
insert.clear();
size = 0;
count ++;
}
}
}
reading.close();
return root; // Gives top node back.
}
My question is: Are there any obvious errors that would cause this? If not, is it compiler related? And is there anything I can do about it?

Binary Tree insert function not working correctly C++

I'm working on a program that uses a binary tree. The program reads from a text file, storing each word in a binary tree alphabetically and finds how many times the word appeared in the file.
The problem I'm having is that my insert function is not working (the program crashes when attempting to run it). I don't know what's exactly wrong, but I suspect it has to do with my else statement towards the end of the function that deals with the right side of the tree.
Any help with fixing it would be appreciated.
Header File
#include <iostream>
#include <string>
using namespace std;
#ifndef TREE_H
#define TREE_H
class Tree
{
public:
Tree();
Tree(string str);
void traversal (Tree *);
void read_file();
void insert(string str);
~Tree();
private:
Tree *left;
Tree *right;
string word;
int count;
};
#endif // TREE_H
Cpp File
#include <iostream>
#include <string>
#include <fstream>
#include "tree.h"
using namespace std;
Tree::Tree()
{
left = NULL;
right = NULL;
count = 0;
}
Tree::Tree(string s)
{
word = s;
}
Tree::~Tree() { }
void Tree::read_file()
{
ifstream myfile;
myfile.open("input.txt", ios::out | ios::in | ios::binary);
if(myfile.is_open()){
while(myfile.good()) {
string buffer;
while(true) {
char c = myfile.get();
if(c == '-' || c == '\'' || isalpha(c) ){
if(isupper(c)) c = tolower(c);
buffer+=c;
}
else break;
}
if(buffer.length() >= 4){
insert(buffer);
}
}
myfile.close();
traversal(this);
}
else { cout << "Unable to open file!" << endl; }
}
void Tree::insert(string str) {
if(str.empty()){ // Also I'm debating whether I need this or not since the string
// cannot possibly be empty as it's part of the condition before
//insert is even called.
this->word = str;
count++;
}
else if(this->word == str) count++;
else if(str < this->word){
if(this->left == NULL) this->left = new Tree(str);
else this->left->insert(str);
}
else {
if(this->right == NULL) this->right = new Tree(str);
else this->right->insert(str);
}
}
void Tree::traversal(Tree *T) {
if(T != NULL) {
traversal(T->left);
cout << T->word << " (" << count << ")" << endl;
traversal(T->right);
}
}
Main
#include <iostream>
#include "tree.h"
using namespace std;
int main()
{
Tree tree;
tree.read_file();
return 0;
}
the problem is that you have 2 constructors, and the second one doesn't initialize pointers left/right to NULL.
edit you are showing properties from different objects: use
cout << T->word << " (" << T->count << ")" << endl;
since the recursive procedure doesn't works calling the member function of the received T. You could do it static, or change it
void Tree::traversal() {
if(this) {
traversal(left);
cout << word << " (" << count << ")" << endl;
traversal(right);
}
}
Personally, I do prefer this last 'style'.
Tree::Tree()
{
word.clear();
left = NULL;
right = NULL;
count = 0;
}
Tree::Tree(string s)
{
word = s;
left = NULL;
right = NULL;
count = 0;
}