I started C++ literally one day ago and I've been having a problem trying to create a rock, paper, scissors game. This code is not exactly how it will look when it's done, but I made this to demonstrate my issue.
I've made brps, meaning: bot rock paper scissors, a random number from 1-3 where the corresponding number will result in a cout stating what item the bot chose.
The rand part of the code was made from viewing different forums and answers to previous questions, but I can't seem to get this to work out. Whenever I run the program it says "Bot chose the rock" no matter what I do. However if I remove the if statemets, and simply print brps it shows a random number each time. So I need help to figure out why the program chooses the rock every single time when that choice should be defined by what number rand chooses.
Feel free to comment on other parts of the code as well, since I'm expecting it all to be somewhat poorly written :L
EDIT: urps is where the user inputs an answer. I didn't use it in this example.
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
int main()
{
cout<<"Hi! Welcome to ROCK PAPER SCISSORS!\n";
cout<<"To play, press enter.\n";
cin.get();
system("cls");
int game();
{
srand(time(NULL));
int brps = rand()>>4, urps;
brps = brps % 3 + 1;
cout<<"Bot chose ";
if (brps = 1){
cout<<"the rock.\n";}
else if (brps = 2){
cout<<"the paper.\n"; }
else if (brps = 3){
cout<<"the scissors.\n"; }
else{
cout<<"invalid.\n.";}
cin.get();
}
}
You should use == to compare, not =.
If you write brps = 1, you assign the value 1 to the variable brps, and the value of the assignment expression is then the same as the value that was assigned, that is, 1. This is non-zero, and gets converted to true, so you always get "the rock".
Also note that if your intension was to create a function called game, that is not what your code does. The extra semicolon makes it a declaration, saying that there is a function called game somewhere else, and then the { } block is just that, a { } block, not a function body.
And, as chris says in his comment, do turn on the compiler warnings. Different compilers give different warnings, but g++ gives the warning suggest parentheses around assignment used as truth value for your uses of = instead of ==. Compiler warnings is the compiler trying to help you, and programming is difficult enough that you shouldn't turn down any help.
You use the assignment operator = in your if statements which will assign the value 1 to brps and return a true value.
Use the operator == instead.
By the way: You do'nt call your game();.
Edit:
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
int game(); // This one declares the subroutine game()
int main()
{
int exit; /* 0 to continue, something else to exit the game */
cout<<"Hi! Welcome to ROCK PAPER SCISSORS!\n";
cout<<"To play, press enter.\n";
cin.get();
system("cls");
do { // This block will execute at least once
exit = game(); // This one calls the subroutine game()
} while (exit == 0); // ...and will execute again and again until exit != 0
return 0; // Or something useful
}
int game() // This implements the subroutine game()
{
srand(time(NULL));
int brps = rand()>>4, urps;
brps = brps % 3 + 1;
cout<<"Bot chose ";
if (brps == 1) {
cout<<"the rock.\n";
} else if (brps == 2) {
cout<<"the paper.\n";
} else if (brps == 3) {
cout<<"the scissors.\n";
} else{
cout<<"invalid.\n.";
}
cin.get();
if (some_kind_of_exit_condition) {
return 1; // results in exit == 1
}
return 0; // results in exit == 0
}
What I changed in your code:
The line int game(); in your code is neither a function call (since the syntax would be invalid) nor a implementation (because of the ;). The curly braces behind that line simply open a block in your code. This block is not necessary (but not forbidden, though). I changed the code to what I think you wanted to write:
I added a line int game(); at the very beginning that defines the subroutine game() that will enable the compiler to verify the call (in 2.)
I added a line game(); which actually calls the subroutine that is defined in 1.
I removed the ; after your int game(); to make a subroutine implementation of the block below.
I removed the } at the end and moved it to the end of main().
I added return statements at the end of both the main and the game routine.
I changed = to ==
Added a loop
Also note that the system("cls") will only work on systems where such a call exists. This is not very good code, since it it is platform dependent and will spawn at least one new process (perhaps more). In the abstract model of output streams there is no clear screen, since the output may also be a file or a printer (if you call your program with output redirection for example).
If you want to clear your screen, this can not be done with the standard output mechanism (except outputting a bunch of newlines - which is not very good since you don't know how many lines have to be written to clear the screen). If you want to do it better, you may use the Win32 Console API or libncurses. These libraries will enable you to control a visual terminal instead of the abstract line output the standard library gives to you. While the standard output is simple, these libraries aren't, so i'd recommend to continue using the cls but remember to change that later when you are more familar with c++.
You should only call srand() once, at the start of your program. Don't call it every time you need a random number, since this effectively re-initialized the generator.
There are other problems with the code:
1) The if (brps = 1) et al are assignments, not comparisons.
2) The
int game();
{
looks like it's defining a nested function, but it's not. Here game() is a prototype, and the stuff inside the curly braces is simply a nested block directly inside main(). I suspect this is not what you're trying to do.
This page covers the basics of randomization using rand(), srand(), etc. It may be worth a gander for you:
Furthermore, you should use the comparison operator (==), not the assignment operator (=) in your if comparisons; using = will actually set and change the value, and the comparison will be true every time since the result will be assigned to a non-zero value. Since your first if-comparison check succeeds every time for this reason, none of the other tests will even execute, and you'll get rock each time.
Please also note, to get as close to truly random number as possible you have to seed your random number generator with a changing number this is accomplished with: srand(time(0));
This can be placed anywhere before the actual call of the random number.
You will also have to #include <ctime> In order to be able to call time(0).
Related
#include<iostream>
#include<stack>
#include<cmath>
using namespace std;
int Narsic(stack<int> stk)
{
int x=0;
int temp=0;
int val=0;
int power_count = stk.size();
while(! stk.empty())
{
x = stk.top();
stk.pop();
temp = pow(x,power_count);
val = val + temp;
}
cout<<val;
}
int main()
{
int num,indic;
num = 1652;
stack<int> numstack;
while(num>0)
{
indic = num%10;
num = num/10;
numstack.push(indic);
}
Narsic(numstack);
return 0;
}
Basically this program is to find the Narcissistic value of a given integer, my codes can be successfully executed and it is correct, but somehow, i think , maybe it is a bit lengthy, so the purpose of posting this problem is, whether anyone can give me suggestions on how to improve the codes above?
Sorry , I'm a beginner and just started learning C++. I hope this community won't get furious against by sucky codes XD.
(Oh yeah, i do search for some codes online and implement them partially here, so if anyone saw similar codes, please be aware that i have made changes, sorry if this irritates you.)
It looks like you're largely asking about style. I'm going to take your code and edit it to be more in keeping with what I would do, then I'll comment below.
#include <iostream>
#include <stack>
#include <cmath>
using std::cout;
using std::endl;
using std::stack;
/**
* Return the Narcissistic value of the digits stored in the stack.
* A Narcissistic value is (insert description).
*/
int narsic(stack<int> stk)
{
int result = 0;
int power_count = stk.size();
while (! stk.empty() ) {
int digit = stk.top();
stk.pop();
result += pow(digit, power_count);
}
return result;
}
/**
* Entry point.
*/
int main() {
int num;
num = 1652;
stack<int> numstack;
while (num>0)
{
int indic = num % 10;
num /= 10;
numstack.push(indic);
}
int result = narsic(numstack);
cout << "Result: " << result << endl;
return 0;
}
I use Java's naming conventions. Class names begin with an upper case letter. Variables and methods begin with lower case letters. This isn't necessarily the C++ way of doing it, but I programmed Java a long time, and it's what I prefer. You'll want to find a style for your academic work, and then use whatever your future employer uses.
I prefer more whitespace to make code readable -- especially for myself. I'm nearly 60 years old, with old eyes, and as code runs all together, it gets harder and harder to read. I've added whitespace here and there.
A blanket using namespace std is considered dangerous, but I don't like sticking std:: all over the place, so I tend to add specific using statements, although not too many.
You were missing a return statement in narsic().
And you had an unusual indentation style. Old-school C/C++ is either 4 spaces or use a tab, but set your editor to 4-space tabs. You indented the braces and then indented again. That would be odd. Some people put the open brace on the same line (I moved them) and some on the next line the way you did. I actually will put them on the next line if it makes the code more readable -- like if there's an obnoxiously long and complicated if-clause.
I moved variable declaration to just as the variables were about to used. This is better for a variety of reasons, including one less initialization plus makes your code smaller. Plus, it keeps scoping rules much tighter.
I switched a num = num / 10 to num /= 10. Similar thing with result +=.
I don't like the variable name val. I changed to result. I think I might have made one or two other variables more descriptive, too.
I added function comments and I did it in the doxygen style. Commenting each method means tools can auto-generate documentation. It also helps break code up a little bit better visually. For comments, it's important to provide information not in the code. The comment for main is trivial, but having it still helps if you actually use a documentation generator -and- provides a visual break.
A change I did NOT make but would normally do: I prefer main to be the first method in my files (at the top), so I would have made a forward reference to narsic() and moved it below main. I didn't do that just because I wanted to keep the code in the same order you had it.
I moved the cout statement and included an endl.
I'm trying to solve this problem as few lines of code as possible.
problem statement:
someone managed to say hello if several letters can be deleted from the typed word so that it resulted in the word "hello"... I'm testing if he could or not
#include <iostream>
int main() {
char c;
int i=0;
while(i!=5 && (cin>>c) && c!='\n'){
if(c=="hello"[i])
i++;
}
cout<<((i==5)?"YES":"NO");
}
There's a bug when it should print "NO". The program waits for more input. I think the loop doesn't finish until i==5 but it never finishes when c=='\n'.
Before you pack your program to minimize the LOC (and I assume that you have a really good reason to care about this because otherwise it is a foolish thing to do) make it right!
Try putting the i != 5 test BEFORE the cin >>c test. Otherwise you read one extra character when you do get a "hello"
Edit: Just to be clear, the code in the question has now been modified to incorporate this suggestion.
You have a while loop there
while(i!=5 && (cin>>c) && c!='\n')
{ ... }
...which you can rewrite for easier debugging. In general, instead of any loop...
while (X)
{ Y }
...you can also write...
while (true)
{
if (!X) break;
Y
}
For your loop, that would be this code:
while (true)
{
if (!(i!=5 && (cin>>c) && c!='\n'))
break;
...
}
Now, I assume you are aware of the short circuit evaluation of the logical AND operator. If not, search the web for that term! With that knowledge, you can rewrite your loop like this:
while (true)
{
if (!(i!=5))
break;
if (!(cin>>c))
break;
if (!(c!='\n'))
break;
...
}
Of course, you can still simplify a few double negations there, but the idea should be clear. This change now allows you to e.g. step through this in a debugger to evaluate each loop exit condition separately. This is important, because the second loop condition also has side effects! In addition, you could e.g. add some debug output that tells you the reason why the loop was exited. Further, for the check that has side effects, you can inspect the intermediate state (or output the state, if you prefer that way), which will give you further insight on the issue.
Lastly, all >> operators on istreams by default skip whitespace, which includes spaces, tabs and newlines, so your last check will never cause the loop to exit. You can tell the stream to not skip whitespace though, if that's what you want. How to do that should be really simple to find out using another websearch. ;)
I'm extremely new to Ubuntu and PuTTY and putting a C++ file into it, but I'm having a problem with my C++ file. What I need the program to do is take a string entered from the Ubuntu side, put into the C++ program, and have it count how many strings are entered in and it sends back like so:
./myfile Supplying arguments now
Argument #0: ./myfile
Argument #1: Supplying
Argument #2: arguments
Argument #3: now
Number of arguments printed: 4
So, when I run my program down below, the program goes on forever and I can't step through it. What is causing it and why and/or what can I do to fix the problem?
#include <stdio.h>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int count = 0;
while (*argv[argc] != NULL)
{
count++;
}
cout << count << endl;
system("PAUSE");
return 0;
}
Your code is an infinite loop because your while loop always checks the same condition. That's because argc never changes in your code.
What you meant to write is while (*argv[count] != NULL). However, what you meant isn't correct either.
C doesn't check array boundaries. When you read past an array boundary, you will not necessarily encounter a 0 value. You will read random garbage data which is in memory at that place.
You don't need to count the number of arguments yourself, because you already have it in the variable argc.
So a better solution to iterate all the command line arguments would be a for loop which increments count from 0 to argc.
hi guys can anyone tell me what's wrong with my 3-way mergesort code?the code I wrote can only sort 4 numbers if you give it more than 4 numbers(by changing size) it ends up with stack overflow error,here is the code:
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
const int size=4;
vector <int> s(size);
void merge(int,int,int);
void mergesort(int,int);
int main(){
for(int i=0;i<size;i++){
cout<<"enter number "<<i+1<<":";
cin>>s.at(i);
}
system("CLS");
cout<<"here are the unsorted numbers:\n";//prints the input values so U can see'em
for(int j=0;j<size;j++)
cout<<s.at(j)<<".";
mergesort(0,size-1);//calls mergesort
cout<<"\nhere are the sorted numbers:\n";
for(int j=0;j<size;j++)
cout<<s.at(j)<<".";
cin.get();
cin.get();
return 0;
}
void merge(int low,int one_third,int high){
int i=low;
int j=one_third+1;
int k=0;
int length=(high-low)+1;
vector <int> u(length,0);
if(k<length){
while((i<=one_third)&&(j<=high)){
if(s.at(i)<=s.at(j)){
u.at(k)=s.at(i);
i++;
k++;
}//end for
else{
u.at(k)=s.at(j);
j++;
k++;
}//end elseif
}//end while
if(j>high)
while(i<=one_third)
{
u.at(k)=s.at(i);
i++;
k++;
}
if(i>one_third)
while(j<=high)
{
u.at(k)=s.at(j);
j++;
k++;
}
for(int n=low;n<k;n++)
s.at(n)=u.at(n);
}
}//end if
void mergesort(int low,int high){
if(low<high){
int one_third=(high-low)/3;//division,it's 3-way mergesort so obviously it's divided by 3
int two_third=2*one_third;
mergesort(low,one_third);
mergesort(one_third+1,two_third);
mergesort(two_third+1,high);
merge(low,one_third,two_third);
merge(low,two_third,high);
}//end if
}
at this point I guess I'm done thinking,Any answer/idea would be appreciated.
Here's a partial inspection of your code. I believe there is an issue debugging a 3 way merge sort with 4 values. You should use more values, such as 6 or 7.
Spaces not tabs for StackOverflow
I'll take a guess that the indentation is because you use tab characters in your code and pasted directly. You'll want to expand the tabs in your next post.
Precompiled Headers
Is your project huge? Does it significantly reduce the build time when you change a header or modify the source code?
I find that stdafx usually is more of a hassle and the time spent resolve defects it causes negates any potential savings by having a precompiled header.
Function prototypes should use named parameters
Can you tell the purpose of the different parameters in your declaration of merge and mergeSort?
Ambiguity breeds defects. 'nuff said.
Main function declared wrong.
The main function always returns an int to the operating system, always. The OS can ignore it.
This mechanism is so that script files can execute your program and test for errors.
Readability prevents defects
Invest in spaces around operators. The time saved by sacrificing spaces is negligible. The debugging time saved by having easy to read code is tremendous, especially when having other people review or inspect your code.
Use intermediate variables
Intermediate variables help clarify your program. They don't cost memory when you tell the compiler to optimize. During debugging, they can help show values during calculations.
The typical idiom for reading into a vector is:
int value;
cin >> value;
s.push_back(value);
The at method may have an overflow issue (or at least your not checking for out of bounds issues). The push_back method will cause the vector to expand as necessary.
Meaningful variable names reduces defects
The variable s has no meaning. Something like original_values or number_container are more descriptive. And again, variable name lengths have nothing to do with improving performance. Readable names help reduce the defects injected.
Not checking state of cin
If I enter "Lion" in response to your 2nd prompt, what will be in the 2nd slot of the array?
Don't trust the Users, they aren't perfect.
Don't clear the screen
It may contain useful data, such as the actual numbers entered. So when you are debugging, and want to know what the User actually typed in, it will be lost and gone forever.
Why cin.get twice?
You are asking the User for input without prompting. And twice. Bad Karma between your program and the User.
See cin.ignore if you want to ignore characters until a specific one is received. Something like this perhaps:
cout << "Paused. Press Enter to continue.\n";
cin.ignore(100000, '\n');
Magic numbers
In function mergesort, you use the numbers 2 and 3. Why? What's their purpose?
Redundant comments
Most programmers realize that the '/' character in a math expression is division. The comment is redundant.
Also, why divide by 3? It's a nasty number. Do you realize you are performing integer division and your product will be truncated? For example: 1/3 == 2/3 == 0.
USE A DEBUGGER
Lastly, a lot of your program's functionality can be verified easier and quicker by using a debugger. A debugger allows you to execute a statement and see the variable values. You can set breakpoints to stop execution at different places. It's a worthwhile educational investment, start now.
A "classic" 3 way merge sort merges runs 3 at a time, alternating between a source and destination array (or vector or list). The code needs to perform up to 3 compares in order to determine the "smallest" of 3 values from each of the 3 runs, then move the smallest value from it's corresponding run to the destination array. The code also has to handle the case where the end of a run is reached, leaving only 2 runs to merge, then the case where the end of the second run is reached, in which case the rest of the third run is moved to the destination array.
For a ram based sort, I'm not sure this is any faster than a normal 2 way merge. For an external sort, with multiple devices or very large read and writes, then a k way merge with k up to 12 or 16 will be faster.
Im creating an infix problem solver and it crashes in the final while loop to finish the last part a of the equations.
I call a final while loop in main to solve whats left on the stack and it hangs there and if i pop the last element from the stack it will leave the loop and return the wrong answer.
//
//
//
//
//
#include <iostream>
#include<stack>
#include<string>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <sstream>
using namespace std;
#define size 30
int count=0;
int count2=0;
int total=0;
stack< string > prob;
char equ[size];
char temp[10];
string oper;
string k;
char t[10];
int j=0;
char y;
int solve(int f,int s, char o)
{
cout<<"f="<<f<<endl;
cout<<"s="<<s<<endl;
cout<<"o="<<o<<endl;
int a;
if (o== '*')//checks the operand stack for operator
{
cout << f << "*" << s << endl;
a= f*s;
}
if (o == '/')//checks the operand stack for operator
{
cout << f << "/" << s << endl;
if(s==0)
{
cout<<"Cant divide by 0"<<endl;
}
else
a= f/s;
}
if (o == '+')//checks the operand stack for operator
{
cout << f << "+" << s << endl;
a= f+s;
}
if (o == '-')//checks the operand stack for operator
{
cout << f << "-" << s << endl;
a= f-s;
}
return a;
}
int covnum()
{
int l,c;
k=prob.top();
for(int i=0;k[i]!='\n';i++)t[i]=k[i];
return l=atoi(t);
}
char covchar()
{
k=prob.top();
for(int i=0;k[i]!='\n';i++)t[i]=k[i];
return t[0];
}
void tostring(int a)
{
stringstream out;
out << a;
oper = out.str();
}
void charstack(char op)
{
oper=op;
prob.push(oper);
}
void numstack(char n[])
{
oper=n;
prob.push(oper);
}
void setprob()
{
int f,s;
char o;
char t;
int a;
int i;
t=covchar();
if(ispunct(t))
{
if(t=='(')
{
prob.pop();
}
if(t==')')
{
prob.pop();
}
else if(t=='+'||'-')
{
y=t;
prob.pop();
}
else if(t=='/'||'*')
{
y=t;
prob.pop();
}
}
cout<<"y="<<y<<endl;
i=covnum();
cout<<"i="<<i<<endl;
s=i;
prob.pop();
t=covchar();
cout<<"t="<<t<<endl;
if(ispunct(t))
{
o=t;
prob.pop();
}
i=covnum();
cout<<"i="<<i<<endl;
f=i;
prob.pop();
t=covchar();
if (t=='('||')')
{
prob.pop();
}
a=solve(f,s, o);
tostring(a);
prob.push(oper);
cout<<"A="<<prob.top()<<endl;
}
void postfix()
{
int a=0;
char k;
for(int i=0;equ[i]!='\0';i++)
{
if(isdigit(equ[i]))//checks array for number
{
temp[count]=equ[i];
count++;
}
if(ispunct(equ[i]))//checks array for operator
{
if(count>0)//if the int input is done convert it to a string and push to stack
{
numstack(temp);
count=0;//resets the counter
}
if(equ[i]==')')//if char equals the ')' then set up and solve that bracket
{
setprob();
i++;//pushes i to the next thing in the array
total++;
}
while(equ[i]==')')//if char equals the ')' then set up and solve that bracket
{
i++;
}
if(isdigit(equ[i]))//checks array for number
{
temp[count]=equ[i];
count++;
}
if(ispunct(equ[i]))
{
if(equ[i]==')')//if char equals the ')' then set up and solve that bracket
{
i++;
}
charstack(equ[i]);
}
if(isdigit(equ[i]))//checks array for number
{
temp[count]=equ[i];
count++;
}
}
}
}
int main()
{
int a=0;
char o;
int c=0;
cout<<"Enter Equation: ";
cin>>equ;
postfix();
while(!prob.empty())
{
setprob();
a=covnum();
cout<<a<<" <=="<<endl;
prob.pop();
cout<<prob.top()<<"<top before c"<<endl;
c=covnum();
a=solve(c,a,y);
}
cout<<"Final Awnser"<<a<<endl;
system ("PAUSE");
return 0;
}
Hope this isn't too harsh but it appears like the code is riddled with various problems. I'm not going to attempt to address all of them but, for starters, your immediate crashes deal with accessing aggregates out of bounds.
Example:
for(int i=0;k[i]!='\n';i++)
k is an instance of std::string. std::string isn't null-terminated. It keeps track of the string's length, so you should be do something like this instead:
for(int i=0;i<k.size();i++)
Those are the more simple kind of errors, but I also see some errors in the overall logic. For example, your tokenizer (postfix function) does not handle the case where the last part of the expression is an operand. I'm not sure if that's an allowed condition, but it's something an infix solver should handle (and I recommend renaming this function to something like tokenize as it's really confusing to have a function called 'postfix' for an infix solver).
Most of all, my advice to you is to make some general changes to your approach.
Learn the debugger. Can't stress this enough. You should be testing your code as you're writing it and using the debugger to trace through it and make sure that state variables are correctly set.
Don't use any global variables to solve this problem. It might be tempting to avoid passing things around everywhere, but you're going to make it harder to do #1 and you're also limiting the generality of your solution. That small time you saved by not passing variables is easily going to cost you much more time if you get things wrong. You can also look into making a class which stores some of these things as member variables which you can avoid passing in the class methods, but especially for temporary states like 'equ' which you don't even need after you tokenize it, just pass it into the necessary tokenize function and do away with it.
initialize your variables as soon as you can (ideally when they are first defined). I see a lot of obsolete C-style practices where you're declaring all your variables at the top of a scope. Try to limit the scope in which you use variables, and that'll make your code safer and easier to get correct. It ties in with avoiding globals (#2).
Prefer alternatives to macros when you can, and when you can't, use BIG_UGLY_NAMES for them to distinguish them from everything else. Using #define to create a preprocessor definition for 'size' actually prevents the code above using the string's 'size' method from working. That can and should be a simple integral constant or, better yet, you can simply use std::string for 'equ' (aside from making it not a file scope global).
Prefer standard C++ library headers when you can. <ctype.h> should be <cctype>, <stdlib.h> should be <cstdlib>, and <stdio.h> should be <stdio>. Mixing non-standard headers with .h extension and standard headers in the same compilation unit can cause problems in some compilers and you'll also miss out on some important things like namespace scoping and function overloading.
Finally, take your time with the solution and put some care and love into it. I realize that it's homework and you're under a deadline, but you'll be facing even tougher deadlines in the real world where this kind of coding just won't be acceptable. Name your identifiers properly, format your code legibly, document what your functions do (not just how each line of code works which is something you actually shouldn't be doing so much later as you understand the language better). Some coding TLC will take you a long way. Really think about how to design solutions to a problem (if we're taking a procedural approach, decompose the problem into procedures as general units of work and not a mere chopped up version of your overall logic). #2 will help with this.
** Example: rather than a function named 'postfix' which works with some global input string and manipulates some global stack and partially evaluates the expression, make it accept an input string and return* the individual tokens. Now it's a general function you can reuse anywhere and you also reduced it to a much easier problem to solve and test. Document it and name it that way as well, focusing on the usage and what it accepts and returns. For instance:
// Tokenize an input string. Returns the individual tokens as
// a collection of strings.
std::vector<std::string> tokenize(const std::string& input);
This is purely an example and it may or may not be the best one for this particular problem, but if you take a proper approach to designing procedures, the end result is that you should have built yourself a library of well-tested, reusable code that you can use again and again to make all your future projects that much easier. You'll also make it easier to decompose complex problems into a number of simpler problems to solve which will make everything easier and the whole coding and testing process much smoother.
I see a number of things which all likely contribute to the issue of it not working:
There are no error or bounds checking. I realize that this is homework and as such may have specific requirements/specifications which eliminate the need for some checks, but you still need some to ensure you are correctly parsing the input. What if you exceed the array size of equ/tmp/t? What if your stack is empty when you try to pop/top it?
There are a few if statements that look like else if (t == '+' || '-') which most likely doesn't do what you want them to. This expression is actually always true since '-' is non-zero and is converted to a true value. You probably want else if (t == '+' || t == '-').
As far as I can tell you seem to skip parsing or adding '(' to the stack which should make it impossible for you to actually evaluate the expression properly.
You have a while loop in the middle of postfix() which skips multiple ')' but doesn't do anything.
Your code is very hard to follow. Properly naming variables and functions and eliminating most of the globals (you don't actually need most of them) would help a great deal as would proper indentation and add a few spaces in expressions.
There are other minor issues not particularily worth mentioning. For example the covchar() and covnum() functions are much more complex than needed.
I've written a few postfix parsers over the years and I can't really follow what you are trying to do, which isn't to say the way you're trying is impossible but I would suggest re-examining at the base logic needed to parse the expression, particularly nested levels of brackets.