Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
#include <stdio.h>
#define MAXLEN 100
typedef struct
{
char element[MAXLEN];
int top;
} stack;
stack init(stack s)
{
s.top=-1;
return s;
}
int isEmpty(stack s){
return(s.top==-1);
}
int isFull(stack s){
return (s.top==MAXLEN-1);
}
stack push(stack s,char ch){
if(s.top==MAXLEN-1){
printf("\n the stack is full\n");
return s;
}
else{
++s.top;
s.element[s.top]=ch;
return s;
}
}
stack pop(stack s){
if(s.top==-1){
printf("\n the stack is empty");
return s;
}
else{
--s.top;
return s;
}
}
void top(stack s){
if(s.top==-1){
printf("\n empty stack");
}
else
printf("%c",s.element[s.top]);
}
void print(stack s){
int i;
printf(" serial no character ");
for(i=0;i<s.top;++i){
printf(" %d %c \n",i,s.element[i]);
}
}
int main(){
stack s;
s.top=-1;
init(s);
char e;
int n,j=1,k;
while(j==1){
printf("\n enter your choice 1.push 2.pop 3.top 4.print 5.exit:");
scanf("%d",&n);
switch(n)
{
case 1:
printf("\n enter the element to be pushed: ");
scanf("%ch",&e);
s=push(s,e);
break;
case 2:
s=pop(s);
break;
case 3:
top(s);
break;
case 4:
print(s);
break;
case 5:
j=0;
break;
default:
printf("\n wrong choice entered enter correct one ");
break;
}
}
}
The error occurs after I compiled and run it and have scanned a character; it goes out of the switch and is not scanning the value of n for consecutive time and is just going into switch with the pre-assigned value and it comes out of switch and asks for n to enter t. In this way I am encountering space as character automatically in the stack elements and the top is getting doubled. Please help me with this. You can once compile it and check for yourself.
Change
scanf("%ch",&e); /* %ch ? */
To
scanf(" %c",&e); // notice a whitespace in the format string
As scanf("%c",&e); leaves a newline, which is consumed again.
which tells scanf to ignore whitespaces.
OR
if (scanf(" %c",&e) != 1)
//Print error
It doesn't take a lot to make the code work sanely. In the fixed code below, I pre-declare the functions because of the compiler options I use. An alternative is to define the functions as static.
#include <stdio.h>
#define MAXLEN 100
typedef struct
{
char element[MAXLEN];
int top;
} stack;
int isEmpty(stack s);
int isFull(stack s);
stack init(stack s);
stack pop(stack s);
stack push(stack s, char ch);
void print(stack s);
void top(stack s);
stack init(stack s)
{
s.top = -1;
return s;
}
int isEmpty(stack s)
{
return(s.top == -1);
}
int isFull(stack s)
{
return(s.top == MAXLEN - 1);
}
stack push(stack s, char ch)
{
if (s.top == MAXLEN - 1)
{
printf("the stack is full\n");
}
else
{
++s.top;
s.element[s.top] = ch;
}
return s;
}
stack pop(stack s)
{
if (s.top == -1)
{
printf("the stack is empty\n");
}
else
{
--s.top;
}
return s;
}
void top(stack s)
{
if (s.top == -1)
printf("empty stack\n");
else
printf("TOS: %c\n", s.element[s.top]);
}
void print(stack s)
{
int i;
printf("serial no character\n");
for (i = 0; i <= s.top; ++i)
{
printf(" %3d %c\n", i, s.element[i]);
}
}
int main(void)
{
stack s;
s.top = -1;
init(s);
char e;
int n, j = 1;
while (j == 1)
{
printf("\nenter your choice 1.push 2.pop 3.top 4.print 5.exit: ");
if (scanf("%d", &n) != 1)
{
fprintf(stderr, "Failed to read a number.\n");
return 1;
}
switch (n)
{
case 1:
printf("\nenter the element to be pushed: ");
if (scanf(" %c", &e) != 1)
{
fprintf(stderr, "Failed to read a character.\n");
return 1;
}
s = push(s, e);
break;
case 2:
s = pop(s);
break;
case 3:
top(s);
break;
case 4:
print(s);
break;
case 5:
j = 0;
break;
default:
printf("incorrect choice (%d not in range 1-5); enter correct one\n", n);
break;
}
}
return 0;
}
Apart from making the indentation consistent (I use uncrustify, but there are other tools that can do the job too), I added error checking to the scanf() statements, fixed the "%ch" format string (the h is superfluous, though mostly harmless), removed trailing spaces from printing, used a newline at the end of non-prompting printf() statements.
Your printing code wasn't printing enough; because of the way you're running your stack pointer, you need to print for (i = 0; i <= s.top; i++) with <= instead of <. A more orthodox way of using top has it showing the next space to use (so the number starts at zero and goes up to MAXLEN). There'd be a number of consequential changes to make.
However, there are some major curiosities left. You keep on passing stacks by value and returning them by value, rather than passing them by pointer. You're therefore passing 104 bytes to and from functions, which is quite a lot. In this code, efficiency isn't a big issue, but the style is unorthodox, shall we say. Your initialization stanza in main() is problematic, too:
stack s;
s.top = -1;
init(s);
The first line is fine. The second line sets top, and is OK in terms of "it works", but violates encapsulation. The next line has multiple problems. It takes a copy of the already initialized stack, sets top to -1, and returns the modified value. Your calling code, however, ignores the returned value.
If you passed pointers to your functions, you'd use:
void init(stack *s)
{
s->top = -1;
}
and then:
stack s;
init(&s);
If you pass values, you could use:
stack s;
s = init(s);
though that's a bit pointless and you could use:
stack init(void)
{
stack s;
s.top = -1;
return s;
}
and then call:
stack s = init();
Of these, passing by pointer is the normal mechanism for largish structures (where, if asked to specify 'largish', I'd say "16 bytes or more"). You can make exceptions on an informed basis, but be careful of the hidden costs of passing large structures by value. Also, changes made to the structures passed by value are not reflected in the calling function. You circumvent that by returning the modified value, but be cautious.
Related
sorry for such a stupid question but I couldn't find any obvious answer.
I need to read from stdin first an int n with the size of an array, and then integer values from a string in the format "1 2 3 4 5 6" with n elements.
If I knew the number of parameters at compile time I could use something like a scanf (or the safe alternatives) with a format string like "%d %d %d %d %d %d", but here I will only know that value at run time.
What would be the best way to do this in C++? Performance is important but more than that safety.
How should I read a format string of variable length in C++ from stdin?
You should not attempt to do such thing. Only ever use constant format strings.
I need to read from stdin first an int n with the size of an array, and then integer values
What would be the best way to do this in C++?
Read one value at a time. Repeat using a loop.
Here's a function that does what errorika describes:
const int SIZE = //as much of your memory as you'd like the user to have access to
***caller function must include this:
//allocate a string to hold some data;
char* buffer = NULL;
buffer = malloc (SIZE * sizeof(char));
if (buffer == NULL) {
printf("malloc error terminating\n");
return;
}
***
void getEntry(char* buffer) {
int count = 0;
int maxlen = SIZE - 1;
char a = '0';
for (int i = 0; i < SIZE; i++) {
buffer[i] = '0';
}
while (a != '\n' && count < maxlen) {
a = fgetc(stdin);
buffer[count] = a;
count++;
}
if (a == '\n') {
buffer[count - 1] = '\0';
}
else {
buffer[count] = '\0';
do {
a = fgetc(stdin);
} while (a != '\n');
}
}
This is all basic C code but user entry is evil. Here is what I've come up with for more C++ idiomatic user input functions (query is just the message string you pass in):
template<typename T>
void getInput(const std::string query, T& entry) {
std::string input;
std::cout << query << std::endl;
getline(std::cin, input);
std::stringstream buffer{input};
buffer >> entry;
}
OR
template<typename T>
void getInput2(std::string query, T& entry) {
bool validInput = false;
while (validInput == false)
{
validInput = true;
std::cout << query << std::endl;
std::cin >> entry;
if (std::cin.fail()) {
validInput = false;
std::cout << "Unacceptable entry\n" << std::endl;
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
I am a beginner in solving algorithmic questions. Until now, I have only self-taught coding. So, I am not sure about the proper conventions.
I was trying to solve a question to reverse a string.There is some problem with the code but I am not sure what it is after debugging step-by-step.
class Solution {
public:
string reverseString(string s) {
int n = s.length();
string reverse;
for (int i=0;i<s.length();i++)
{
reverse[i] = s[n-1];
n=n-1;
}
return reverse;
}
};
Input: "Hello"
Output needed: "olleh"
My output: "olleh " (extra space)
Input: A man, a plan, a canal: Panama
Output: No output
I searched online for solutions. There were related to pointers. It would be great if someone helped me understand why this logic doesn't work and why using pointers is a better idea.
ALREADY GIVEN. CANNOT CHANGE:
string stringToString(string input) {
assert(input.length() >= 2);
string result;
for (int i = 1; i < input.length() -1; i++) {
char currentChar = input[i];
if (input[i] == '\\') {
char nextChar = input[i+1];
switch (nextChar) {
case '\"': result.push_back('\"'); break;
case '/' : result.push_back('/'); break;
case '\\': result.push_back('\\'); break;
case 'b' : result.push_back('\b'); break;
case 'f' : result.push_back('\f'); break;
case 'r' : result.push_back('\r'); break;
case 'n' : result.push_back('\n'); break;
case 't' : result.push_back('\t'); break;
default: break;
}
i++;
} else {
result.push_back(currentChar);
}
}
return result;
}
int main() {
string line;
while (getline(cin, line)) {
string s = stringToString(line);
string ret = Solution().reverseString(s);
string out = (ret);
cout << out << endl;
}
return 0;
}
As you create reverse, you have to pass the length of the string as an argument, else the created string will be of size 0. This could look like this:
string reverseString(string s) {
int n = s.length();
string reverse(n,'0');
for (int i=0;i<s.length();i++)
{
reverse[i] = s[n-1];
n=n-1;
}
return reverse;
}
Reversing a string is trivial. Just construct a new one from the reverse iterators:
std::string reverse_str(s.rbegin(), s.rend());
or
std::string reverse_str(s.crbegin(), s.crend());
Here's how I would write your function:
string reverseString(const string& s) {
return {s.crbegin(), s.crend()};
}
Try this out
class Solution {
public:
string reverseString(string s) {
//cout<<"inside func";
int n = s.length();
cout<<n<<endl;
char reverse[sizeof(char)*n];// reverse stores the reverse of original string s
int i= 0;
for ( i=0;i<s.length();i++)
{
reverse[i] = s[n-i-1];
}
return reverse;
}
}
int main()
{
string s,r;
Solution sol;
s= "hello";
r= sol.reverseString(s);
cout<<r<<endl;
cout<<r.length()<<endl;
return 0;
}
when i= 0, n-i-1= n-1 which is the last element of the original string s. So the first element of the reverse string is the last element of s. Next i becomes i+1 i.e 1. This time second element of the reverse string is the last but one element in string s. This procedure is repeated till i < s.length(). The element to get copied is for index i= n-1 and n becomes n-(n-1)-1= 0, so the last element of reverse string is the first element of s. After this the loop exists. No additional extra characters are added.
im busy writing a line of code for my study.
I already have gotten quite far on the assignment but i keep running into the same problem.
On the swap function i keep running into a segmentation fault when a character is inputted(word & word2) that is not in the main 'dictionary' string.
Could someone explain to me what is causing the problem and how i can solve it? Sorry if anything isnt clear, i've just started learning c++.
code where segmentation fault occures:
void swapWords(char **dict, char *word, char *word2)
{
int i;
int d;
int x;
int y;
char *tmp;
while (1){
for(i = 0; i < MAX_NUMBER_OF_WORDS; i++)
{
if(strcmp(word, dict[i]) != 0)
{
if(i == MAX_NUMBER_OF_WORDS -1)
{
printf("Cannot swap words. Atleast one word missing in the dictionary.\n");
goto error;
}
}
else
{
x = i;
break;
}
}
for(d = 0; d < MAX_NUMBER_OF_WORDS; d++)
{
if(strcmp(word2, dict[d]) != 0)
{
if(d == MAX_NUMBER_OF_WORDS -1)
{
printf("Cannot swap words. Atleast one word missing in the dictionary.\n");
goto error;
}
}
else
{
y = d;
break;
}
}
tmp = dict[x];
dict[x] = dict[y];
dict[y] = tmp;
error: break;
}
}
The entire code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#define MAX_NUMBER_OF_WORDS 10
void swapWords(char **dict, char *word, char *word2)
{
int i;
int d;
int x;
int y;
char *tmp;
while (1){
for(i = 0; i < MAX_NUMBER_OF_WORDS; i++)
{
if(strcmp(word, dict[i]) != 0)
{
if(i == MAX_NUMBER_OF_WORDS -1)
{
printf("Cannot swap words. Atleast one word missing in the dictionary.\n");
goto error;
}
}
else
{
x = i;
break;
}
}
for(d = 0; d < MAX_NUMBER_OF_WORDS; d++)
{
if(strcmp(word2, dict[d]) != 0)
{
if(d == MAX_NUMBER_OF_WORDS -1)
{
printf("Cannot swap words. Atleast one word missing in the dictionary.\n");
goto error;
}
}
else
{
y = d;
break;
}
}
tmp = dict[x];
dict[x] = dict[y];
dict[y] = tmp;
error: break;
}
}
void removeWord(char **dict, char *word)
{
int i;
int d;
for(i = 0; i < MAX_NUMBER_OF_WORDS; i++)
{
if(strcmp(dict[i], word) == 0)
{ dict[i] = NULL;
for(d = i+1; d < MAX_NUMBER_OF_WORDS; d++)
{ if(dict[d] == NULL)
{ dict[i] = dict[d-1];
dict[d-1] = NULL;
break;
}
}
break;
}
}
}
void printDict(char **dict)
{
int i = 0;
if(dict[0] == NULL)
{
printf("The dictionary is empty.\n");
}
else{
while (dict[i] != NULL)
{
printf("- %s\n", dict[i]);
i++;
}
}
}
void addWord(char **dict, char *word)
{
int d;
char *word1;
for(d = 0; d < MAX_NUMBER_OF_WORDS; d++)
{
if (dict[d] == NULL)
{
word1 = (char*) malloc(sizeof(char)*(strlen(word) + 1));
strcpy(word1, word);
dict[d] = word1;
break;
}
}
}
int numberOfWordsInDict(char **dict)
{
int i = 0;
int d;
for (d = 0; d < MAX_NUMBER_OF_WORDS; d++){
if(dict[d] != NULL)
{
i++;
}
}
return i;
}
int main()
{
char *dict[MAX_NUMBER_OF_WORDS] = {};
char word[36];
char word2[36];
char c;
int i;
while(printf("Command (a/p/r/s/q): "))
{
scanf(" %c", &c);
switch (c){
case 'p': printDict(dict);
break;
case 'a': printf("Enter a word: ");
scanf("%s", word);
addWord(dict, word);
break;
case 'n': i = numberOfWordsInDict(dict);
printf("%d\n", i);
break;
case 'r': printf("Remove a word: ");
scanf("%s", word);
removeWord(dict, word);
break;
case 's': printf("Swap two words:\n");
printf("Enter first word: ");
scanf("%s", word);
printf("Enter second word: ");
scanf("%s", word2);
swapWords(dict, word, word2);
break;
case 'q': return 0;
}
}
}
It will be most helpful to your studies as a student if you find the actual error yourself, though Marco and πάντα ῥεῖ may be right. However, here are a few things to think about, as this will definitely not be your last segfault problem as a programmer (I had at least 20 this month alone).
A segmentation fault is almost always caused by the code trying to modify or read memory that it doesn't have permission to read or modify. When the program starts, it is given a chunk of memory (RAM) to work with. For security reasons, no program is allowed to work with memory outside of that chunk. There are other limitations at play too.
As a general rule, if you try to read memory past the end of an array, you have a high risk of getting a segfault, or in other cases, garbled data. The official word on this actually comes from C, C++'s parent language, in that accessing past the end of an array causes "undefined behavior". Or, as it was once said on USENET, "it is legal for the compiler to make demons fly out of your nose". The behavior is totally unpredictable. Thankfully, that undefined behavior usually IS a segfault.
By the way, if you try to access an uninitialized array, similar weirdness can happen.
NOW, since you are accessing the elements of your array via a loop, another possible cause is that your loop is continuing beyond where you think it is. Sometimes it is helpful to modify your code so that the loop's iterator (i in your case) is printed out each iteration. This can help you catch if the loop is going beyond where it should.
In short, check...
Did I initialize all of my arrays before I tried to read or write
them?
Are my loops starting and stopping where I expected? Check for
"off-by-one" errors (i.e. starting at 1 instead of 0), infinite
loops (forgot to increment the iterator or the stop condition is
never true), and other logical errors.
Am I trying to read/write past the end of the array?
If I'm working with a C-string, did I forget the NULL terminator?
In addition to your debugger, which you should learn how to use well, tools like valgrind are instrumental in finding the cause of memory errors. Oftentimes, it can point you to the exact line of code where the segfault is occuring.
I had figured out myself the problem was in the strcmp. I know that figuring out a problem by myself is the best way to learn and I tried, but I just couldn't figure out why it was returning a seg fault. As this is my fifth assignment I'm only just getting to know how array's and pointers work. I assumed that the array was already initialized as 'NULL', as seen I was already comparing the pointer to 'NULL' in the addWord function. To assume this is ofcourse very stupid of me. I might not have figured the problem out by myself, yet it is still something I will not be forgetting anymore.
Most probably the segmentation fault happens here:
if(strcmp(word, dict[i]) != 0)
Infact it is quite likely that that i > becomes bigger than the size of your dict and if your dict has 3 elements and you try to access the 4th you are accessing an unknown area or ram and that causes a segmentation fault.
The solution is to make sure your for loop stops at the last element of the dictionary with the solution πάντα ῥεῖ has proposed in the above comment.
I'm working on a program involving the use of templates to evaluate postfix expressions. I'm not allowed to modify the code in any way; only fill in the blanks, so to speak (most of which have been filled, but errors are turning up). This being said:
1) The template header, template specialization, and main program files are all separate. How do I implement the template in the main program? I'm already using #include at the end of the header file as the specialization substitute.
2) FIXED
3) In the specialization file, do I need to use #include "templateheader.h" above using namespace std, or do I just put template above every function? I'll post an example as I have it now below.
Two asterisks mark the lines where we have to fill in the blanks. If it's only part of a line, it's one star on each side.
stackType.h
#pragma once**
// Catherine Stringfellow and Trey Brumley
// A Stack is a ???**
// Class specification for Stack ADT in file StackType.h
using namespace std;
static const int MAXITEMS = 50;
template <class stack>**
class StackType
{
public:
// Class constructors
StackType();
StackType (const StackType & other);
void makeEmpty();
// Function: Sets stack to an empty state.
// Post: Stack is empty.
bool isFull() const;
// Function: Determines whether the stack is full.
// Pre: Stack has been initialized.
// Post: Function value = (stack is full)
bool isEmpty() const;
// Function: Determines whether the stack is empty.
// Pre: Stack has been initialized.
// Post: Function value = (stack is empty)
void push(*stack* item);
// Function: Adds newItem to the top of the stack.
// Pre: Stack has been initialized.
// Post: If (stack is full), PushOnFullStack exception is thrown;
// otherwise, newItem is at the top of the stack.
void pop(*stack* & item);
// Function: Removes top item from the stack and returns it in item.
// Pre: Stack has been initialized.
// Post: If (stack is empty), PopOnEmptyStack exception is thrown;
// otherwise, top element has been removed from stack.
// item is a cop of the removed item.
int getStackNum ();
//Function: returns the number of items in the stack
//Pre: Stack has been initialized
//Post: Returns the number of items in the stack
private:
int top;
stack items[MAXITEMS]; //statically allocated array
};
#include "stackType.cpp";**
stackType.cpp
// Catherine Stringfellow and Trey Brumley
// File: StackType.cpp
// Templated member function implementations for class StackType.
// This is the statically allocated array-based stack.
#include "stack"**
using namespace std;
template <class stack>**
StackType *StackType<stack>*::StackType()
{
top = -1;
}
template <class stack>**
StackType *StackType<stack>*::StackType (const StackType & other)
{
top = other.top;
for (int i=0; i < top; i++)
items[i] = other.items[i];
}
template <class stack>**
StackType*<stack>*::makeEmpty()
{
top = -1;
}
template <class stack>**
*bool StackType<stack>*::isEmpty() const
{
return (top == -1);
}
template <class stack>**
bool StackType*<stack>*::isFull() const
{
return (top == MAXITEMS-1);
}
template <class stack>**
StackType*<stack>*::push(StackType newItem)
{
if( !isFull() )
{
top++;
items[top] = newItem;
}
}
template <class stack>**
StackType*<stack>*::pop( & item)
{
if( !isEmpty() )
{
item = items[top];
top--;
}
}
template <class stack>**
int StackType*<stack>*::getStackNum ()
{
return top+1;
}
main
/* Erik Malone and Catherine Stringfellow and Trey Brumley Date: December-5-2013
File: prog5.cpp
Program Specifications
Narrative: Program that evaluates and converts postfix expressions.
Interface:
Introductory Screen:
"Postfix Calculator and Converter"
Exit Screen:
"Goodbye..."
Input:
numbers in expressions should be separated by a space.
(from keyboard, see attached)
Output:
(all to screen, see attached)
Constants:
STACK_MAX
*/
#include "stack"**
#include <string>
#include <iostream>
#include <cmath>
#include <iomanip>
#include <cstdlib>
#include <cctype>
int getValidChoice ();
/* purpose: get valid option choice from menu
prereq: NONE
postcond: int (for a valid choice returned)
*/
void readString(string& s);
/* purpose: Reads a line into a string
recieves: string <s>
returns: NONE
*/
void printString(const string& s);
/* purpose: Prints a string
recieves: const string <s>
returns: NONE
*/
void convertPostfix(string& post, string& result);
/* purpose: converts a prefix expression to infix
recieves: string <post>, string <result>
returns: NONE
*/
void convert(StackType & s, char ch);
/* purpose: pops two operands off a string stack and pushes the result
recieves: string <post>, char <ch>
returns: NONE
*/
void evalPostfix(string& post, double& answer);
/* purpose: calculates the value of the prefix expression
recieves: string <post>, double <answer>
returns: NONE
*/
void evaluate(StackType & s, char ch);
/* purpose: pops two operands off a double stack and pushes the result
recieves: Stack <s>, char <ch>
returns: NONE
*/
void error(int m);
//prints an error message, based on int parametet
//print the introduction and exit screens
void intro();
void outro();
void main()
{
string post;
double answer;
int choice;
//intro screen
intro();
//while user wants to continue
choice = getValidChoice();
while (choice != 3) {
//switch menu options
switch (choice)
{
case 1:
cout<<"Please enter a postfix expression: ";
readString(post);
if (post == "") //error if string empty
error(1);
else
{
evalPostfix(post, answer);
printString(post);
cout<<" = "<<answer<< endl << endl;
}
break;
case 2:
cout<<"Please enter a postfix expression: ";
readString(post);
if (post == "")
error(1);
else
{ string tempString = "";
convertPostfix(post, tempString);
cout<<"Postfix expression: ";
printString(post);
cout<<"\nEpression converted to infix: "<<tempString << endl<<endl;
}
break;
default: //if choice is not recognized print error
error(3);
} //end switch
choice = getValidChoice();
} //end while
outro();
//exit screen on return
system("pause");
}
int getValidChoice ()
{
int choice;
//display menu options
cout<<" Options \n";
cout<< " (1) Evaluate postfix expression " << endl;
cout<< " (2) Convert postfix to infix " << endl;
cout<< " (3) Quit " << endl;
//get menu option
cout<<"Enter option: ";
cin>>choice;
cout <<endl;
//validate menu option
while ((choice < 1) || (choice > 3)) {
cout << "Enter a value between 1 and 3: ";
cin >> choice;
}
return choice;
}
void printString(const string& s)
{
if (s.empty())
cout<<"Empty"; //if string is empty print "empty"
else
cout<<s;
}
void readString(string& s)
{
char temp[40];
cin.ignore(80,'\n'); //clear buffer
cin.getline(temp, 40); //copy line to string
s = temp;
}
void evalPostfix(string& post, double& answer)
{
int index = 0, total = 0;
double tempDbl;
bool negative = false; //to detect negative signs
StackType s; //declare a stack of doubles
//loop index until end of string
while (index < (int) post.length())
{
//pass over spaces in string
while (isspace(post[index]))
index++ ;
//if operator evaluate incrementing index
if (!isdigit(post[index]) &&
!((index+1 < (int) post.length()) &&
(post[index] == '-' && isdigit(post[index+1]))))
//if (!isdigit(post[index]))
evaluate(s, post[index++]);
else
{ //if number, checks for negative sign
if (post[index] == '-')
{
index++;
negative = true;
}
//add up the digits from string
while ((post[index] >= '0') && (post[index] <= '9'))
total = (total * 10) + (post[index++] - '0');
//if there was a negative sign, negate total
if (negative)
{
total = total * -1;
negative = false;
}
//push number onto stack
s.push(total);
total = 0;
}
index++;
}
//pop answer from stack
s.pop(tempDbl);
answer = tempDbl;
}
void evaluate(StackType & s, char ch)
{
double op1, op2;
//check if empty before popping operands
if (!s.isEmpty())
{
s.pop(op2);
if (!s.isEmpty())
{
s.pop(op1);
//push result
switch(ch)
{
case '+':
s.push(op1 + op2);
break;
case '-':
s.push(op1 - op2);
break;
case '*':
s.push(op1 * op2);
break;
case '/':
s.push(op1 / op2);
break;
default:
return;
}
}
}
}
void convertPostfix(string& post, string& result)
{
int index = 0;
string tempString;
StackType s; //declare a stack of strings
//loop index until end of string
while (index < (int) post.length())
{
//pass over spaces in string
if (isspace(post[index]))
index++ ;
//if operator convert incrementing index
if (!isdigit(post[index]) &&
!((index+1 < (int) post.length()) &&
(post[index] == '-' && isdigit(post[index+1]))))
//if (!isdigit(post[index]))
convert(s, post[index++]);
else
{
//clear string
tempString.erase();
//concatenate numbers to string
while (!isspace(post[index]))
tempString = tempString + post[index++];
//push string onto stack
s.push(tempString);
}
index++;
}
//pop resulting string from stack
s.pop(result);
}
void convert(StackType & s, char ch)
{
string op1, op2, tempString;
//check if empty before popping
if (!s.isEmpty())
{
s.pop(op2);
if (!s.isEmpty())
{
s.pop(op1);
//constructing string for result
tempString = tempString + "( ";
tempString = tempString + op1;
//concatenate sign to string
switch(ch)
{
case '+':
tempString = tempString + " + ";
break;
case '-':
tempString = tempString + " - ";
break;
case '*':
tempString = tempString + " * ";
break;
case '/':
tempString = tempString + " / ";
break;
default:
return;
}
//adding rest of the string
tempString = tempString + op2;
tempString = tempString + " )";
//push resulting string onto stack
s.push(tempString);
}
}
}
void error(int m)
{
system("cls"); //clear screen
cout<<"\a"; //system beep
//displays error message according to parameter passed
switch (m)
{
case -1:
cout<<"INTERNAL ERROR";
break;
case 1:
cout<<"ERROR - Postfix expression empty.";
break;
case 3:
cout<<"ERROR - invalid entry.";
break;
default:
cout <<"UNKNOWN ERROR.";
}
cout << endl << endl;
}
void intro()
{
system("cls"); //clear screen
//displays welcome message
cout<<"Postfix Calculator and Converter\n\n";
}
void outro()
{
cout<<"Goodbye...\n\n"; //display exit message
}
As for 2) it has to be std::string, or you could say
using std::string;
or
using namespace std;
and then you should be able to say just string. I would recommend the former, unless you are pulling in a lot of stuff from std::
Other bits of trivia:
name your header file “stack.h”
you do not need a stack.cpp, just implement the functions in stack.h, e.g.
template
class Stack {
….
void doSomething(ElementType& object) {…}
….
};
This tends to be cleaner. You could also do it out of line but it still needs to be in the same file, and if you do it out-of-line, you need to prefix every function with the template keyword
you might want to pick a better more descriptive name than “stack” for the template argument.
You should switch the name of your class with the name of the template argument, that would make more sense. This would become
template <typename StackType>
class Stack
{
...
};
For example
void push(stack item);
Would be
void push(StackType item);
1) You can put the declaration and the definition of the methods into separate files but you need to include them at the end like you did but I suggest your rename you stack.cpp to stack.inl (.inl for inline) or something else.
3) If you use 2 files like above there's no need to include stack.h inside stack.cpp/inl. Think of this like it's the same file. And be careful with that using namespace std since everyone that include your stack.h will be "using namespace std" and that might cause issues...
Finally, there's no template specialization in your source code and there's is no such thing as specialization file. However, template specialization do exist and it's probably not what you expect. More info here
I have the following code and I have defined the functions that I am calling here, the problem here is : I run the code
input: 1
input: 2
input: 2
input: 6
input: 5 6 // for the scanf associated with i=6;
after this I get the output on the screen as
enter ur choice and then it exits out of the program ... its like the scanf gets the value from somewhere but I dunno from where I also tried fflush(stdin) doesnt seem to work can any one please help
int main()
{
int i,*j,k,pos,val;
Element *stacka = new Element;
stacka =NULL;
while(i!=5)
{
printf("Enter ur choice \n");
fflush(stdin);
scanf("%d",&i);
if(i==1)
{
if(createStack(&stacka))
{
printf("yes");
}
}
if(i==2)
{
k=2;
if(push(&stacka,&j))
{
printf("yes");
}
}
if(i==3)
{
if(pop(&stacka,&k))
{
printf("yes %d",k);
}
}
if(i==4)
{
if(emptyStack(&stacka))
{
printf("yes");
}
}
if(i==6)
{
scanf("%d,%d",&pos,&val);
fflush(stdin);
insert_at_pos(pos,val,&stacka);
}
}
return 0;
}
Try inserting a space before %d:
scanf(" %d,%d",&pos,&val);
This will eat any leading whitespace that might be in the input buffer, e.g., the newline from the earlier entry of i.
Also, initialize i before the loop.