I've spent several hours on this and it's starting to drive me crazy. It's homework so I just need a point in the right direction, a hint or two...maybe three. The program doesn't calculate the balance correctly and I'd like to put a blank line between deposit and withdrawal entries. Suggestions, corrections, clues?
include <stdio.h>
int main(void)
{
/* Declare Array Variables */floatdeposits[50]={0};floatwithdrawals[50]={0};charfirstName[20]={0};/* Declare Variables */intnumWithdrawals,numDeposits,x;floatcurrentBalance=0;floatinitialBalance;floattotalDeposits;floattotalWithdrawals;floatbalance;/* Greeting */printf("\nWelcometotheSearsBankingSystem.\n");printf("\nPleaseenteryourfirstname:");scanf("%s",firstName);printf("\nHello,%s.\n\n",firstName);/* Prompt user for balance */do{printf("%s,Pleaseenteryourcurrentbalanceindollarsandcents:");scanf("%f",&initialBalance);if(initialBalance<0)printf("Error:Beginningbalancemustbeatleastzero,pleasere-enter!\n\n");}while(initialBalance<0);/* End do while *//* Prompt user for number of withdrawals */do{printf("\nEnterthenumberofwithdrawals:");scanf("%i",&numWithdrawals);printf("\n");if(numWithdrawals<0||numWithdrawals>50)printf("Error:Numberofwithdrawalsmustbebetweenzeroand50,pleasere-enter!\n\n");}while(numWithdrawals<0||numWithdrawals>50);/* End do while loop *//* Prompt user for number of deposits */do{printf("Enterthenumberofdeposits:");scanf("%i",&numDeposits);printf("\n");if(numDeposits<0||numDeposits>50)printf("Error:Numberofdepositsmustbebetween0and50,pleasere-enter!\n\n");}while(numDeposits<0||numDeposits>50);/* End do while loop */for(x=0;x<=numDeposits-1;x++){do{printf("Entertheamountofdeposit#%i:",x+1);scanf("%f",&deposits[x]);if(deposits[x]<=0)printf("***Depositamountmustbegreaterthanzero.Pleasere-enter!***\n");}while(deposits[x]<=0);totalDeposits=totalDeposits+deposits[x];currentBalance=totalDeposits+initialBalance;}/* end for loop *//* Prompt user for withdrawals */for(x=0;x<=numWithdrawals-1;x++){do{printf("Entertheamountofwithdrawal#%i:",x+1);scanf("%f",&withdrawals[x]);if(withdrawals[x]>currentBalance)printf("***Withdrawalamountexceedscurrentbalance.***\n");elseif(withdrawals[x]<=0)printf("***Withdrawalamoutmustbegreaterthanzero.Pleasere-enter!***");}while(withdrawals[x]>currentBalance||withdrawals[x]<=0);/* End do while loop */totalWithdrawals=totalWithdrawals+withdrawals[x];currentBalance=currentBalance-withdrawals[x];}/* end for loop */balance=currentBalance-totalWithdrawals+totalDeposits;if(balance==0){printf("\n***Balanceisnowzero.Nomorewithdrawalscanbemadeatthistime.***\n");numWithdrawals=x;}/* Calculate and display balance */{printf("\n***Theclosingbalance%sis$%.2f***\n",firstName,balance);if(balance>=5000.00)printf("***it'stimetoinvestsomemoney!***\n");elseif(balance>=15000.00&&balance<=49999.99)printf("\n***maybeyoushouldconsideraCD.***\n");elseif(balance>=1000.00&&balance<=14999.99)printf("\n***keepupthegoodwork.***\n\n");elseprintf("***%syourbalanceisgettinglow!***\n",firstName);}/* Calculate and display bank record */printf("\n***BankRecord***\n");printf("\nStartingBalance:$%.2f\n\n",initialBalance);for(x=0;x<=numDeposits-1;x++){printf("Deposit#%i:%.2f\n",x+1,deposits[x]);}for(x=0;x<=numWithdrawals-1;x++){printf("\nWithdrawal#%i:%.2f",x+1,withdrawals[x]);}printf("\n\nEndingBalanceis:$%.2f\n",balance);getchar();
} / end main /
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
sandbox.cpp(83) : warning C4700: uninitialized local variable 'totalDeposits' used
sandbox.cpp(106) : warning C4700: uninitialized local variable 'totalWithdrawals' used
I imagine Dev-C++ issued somethiong similar. If not add the following options compiler options; -Wall -Werror. Since you are usiing C's stdio library add -Wformat also.
Warnings are errors, read them, understand them, fix them. These are certainly causing you problems. When the execition gets to:
>> Ran in DEV-C++, no compile errors to on this end???
Well they were warnings not errors. My opinion is that warnings should be considered errors however, if you care about teh quality of your code. Did you add the warning options I suggested? Post the compile log.
Either way, you still need to initialise the variables. VC++ 2008 Express Edition is free too you know, you could just use that.
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Compiler: Default compiler
Executing gcc.exe...
gcc.exe "C:\ANSI_C\bankbal.c" -o "C:\ANSI_C\bankbal.exe" -Wall -Werror -ansi -traditional-cpp -pg -g3 -I"C:\Dev-Cpp\include" -L"C:\Dev-Cpp\lib" -lgmon -pg -g3
C:\ANSI_C\bankbal.c: In function `main':
C:\ANSI_C\bankbal.c:195: warning: control reaches end of non-void function
Execution terminated
Compilation successful
Here's the program written in ANSI C after some clean up. I have no clue why it doesn't calculate the balance correctly. I've rearanged the variables a bit and back without success.
include <stdio.h>
int main(void)
{
/* Declare Array Variables */floatdeposits[50]={0};floatwithdrawals[50]={0};charfirstName[20]={0};/* Declare Variables */intnumWithdrawals,numDeposits,x;floatcurrentBalance=0;floatinitialBalance;floattotalDeposits;floattotalWithdrawals;floatbalance;/* Greeting */printf("\nWelcometotheSearsBankingSystem.\n");printf("\nPleaseenteryourfirstname:");scanf("%s",firstName);fflush(stdin);printf("\nHello,%s.\n\n",firstName);/* Prompt user for balance */do{printf("Nowenteryourcurrentbalanceindollarsandcents:");scanf("%f",&initialBalance);fflush(stdin);if(initialBalance<0)printf("Error:Beginningbalancemustbeatleastzero,pleasere-enter!\n\n");}while(initialBalance<0);/* End do while *//* Prompt user for number of withdrawals */do{printf("\nEnterthenumberofwithdrawals:");scanf("%i",&numWithdrawals);fflush(stdin);printf("\n");if(numWithdrawals<0||numWithdrawals>50)printf("Error:Numberofwithdrawalsmustbeatleastzeroandnomorethanfifty,pleasere-enter!\n\n");}while(numWithdrawals<0||numWithdrawals>50);/* End do while *//* Prompt user for number of deposits */do{printf("Enterthenumberofdeposits:");scanf("%i",&numDeposits);fflush(stdin);printf("\n");if(numDeposits<0||numDeposits>50)printf("Error:Numberofdepositsmustbeatleastzeroandnomorethanfifty,pleasere-enter!\n\n");}while(numDeposits<0||numDeposits>50);/* End do while */for(x=0;x<=numDeposits-1;x++){do{printf("Entertheamountofdeposit#%i:",x+1);scanf("%f",&deposits[x]);fflush(stdin);if(deposits[x]<=0)printf("***Depositamountmustbegreaterthanzero.Pleasere-enter!***\n");}while(deposits[x]<=0);/* End do while loop */totalDeposits=totalDeposits+deposits[x];}/* end for loop */currentBalance=totalDeposits+initialBalance;/* Prompt user for withdrawals */for(x=0;x<=numWithdrawals-1;x++){do{printf("Entertheamountofwithdrawal#%i:",x+1);scanf("%f",&withdrawals[x]);fflush(stdin);if(withdrawals[x]>currentBalance)printf("***Withdrawalamountexceedscurrentbalance.***\n");elseif(withdrawals[x]<=0)printf("***Withdrawalamountmustbegreaterthanzero.Pleasere-enter!***");}while(withdrawals[x]>currentBalance||withdrawals[x]<=0);/* End do while loop */totalWithdrawals=totalWithdrawals+withdrawals[x];currentBalance=currentBalance-withdrawals[x];}/* end for loop */balance=currentBalance-totalWithdrawals+totalDeposits;if(balance==0){printf("\n***Yourbalanceisnowzero.Nomorewithdrawalscanbemadeatthistime.***\n");numWithdrawals=x;}/* End if *//* Calculate and display balance */{printf("\n***Theclosingbalance%sis$%.2f***\n",firstName,balance);if(balance>=5000.00)printf("***it'stimetoinvestsomemoney!***\n");elseif(balance>=15000.00&&balance<=49999.99)printf("\n***maybeyoushouldconsideraCD.***\n");elseif(balance>=1000.00&&balance<=14999.99)printf("\n***keepupthegoodwork.***\n\n");elseprintf("***%syourbalanceisgettinglow!***\n",firstName);}/* End if else and display comment*//* Calculate and display bank record */printf("\n***BankRecord***\n");printf("\nStartingBalance:$%.2f\n\n",initialBalance);for(x=0;x<=numDeposits-1;x++){printf("Deposit#%i:%.2f\n",x+1,deposits[x]);}/* End for loop */for(x=0;x<=numWithdrawals-1;x++){printf("\nWithdrawal#%i:%.2f",x+1,withdrawals[x]);}/* End for loop */printf("\n\nEndingBalanceis:$%.2f\n",balance);getchar();
} / end main /
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks guys, I figured it out I think, you both pointed at the "total..." nonsense. I took those entries out and moved some stuff around a little and it seems to compile and run ok now. I do appreciate your help as always.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
unless you are really sure that you need them and know what they are for. Note that you have -pg specified twice, probably in the project options and the global compiler options. -traditional-cpp is particularly problematic and almost certainly unnecessary - it is probably not what you think it is, the "cpp" refers to the C pre-processor, and not C++ as you might think.
> C:\ANSI_C\bankbal.c:195: warning: control reaches end of non-void function
> Execution terminated
> Compilation successful
That is very odd. You have a warning and specified -Werror, yet compilation was successful. Moreover you are indeed not getting the uninitialised variable warning. Neither should happen.; what version of Dev-C++ is this you are using?
> I have no clue why it doesn't calculate the balance correctly.
I told you twice, and then Ron told you again! I could have posted the fix as code, but you said you only wanted a push in the right direction, you seem to be perversely resisting the nudge!
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I follow you now (I think)...I removed the total... stuff but I still have a calculation problem that I don't quite see yet. Here's what I have so far...DEV-C++ Version 4.9.9.2
/* Declare Array Variables */floatdeposits[50]={0};floatwithdrawals[50]={0};charfirstName[20]={0};/* Declare Variables */intx;intnumDeposits;intnumWithdrawals;floatcurrentBalance;floatinitialBalance;floatbalance;/* Greeting */printf("\nWelcometotheBankingSystem.\n");printf("\nPleaseenteryourfirstname:");scanf("%s",firstName);fflush(stdin);printf("\nHello,%s.\n\n",firstName);/* Prompt user for balance */do{printf("Nowenteryourcurrentbalanceindollarsandcents:");scanf("%f",&initialBalance);fflush(stdin);if(initialBalance<0)printf("Error:Beginningbalancemustbeatleastzero,pleasere-enter!\n\n");}while(initialBalance<0);/* End do while *//* Prompt user for number of withdrawals */do{printf("\nEnterthenumberofwithdrawals:");scanf("%i",&numWithdrawals);fflush(stdin);printf("\n");if(numWithdrawals<0||numWithdrawals>50)printf("Error:Numberofwithdrawalsmustbeatleastzeroandnomorethanfifty,pleasere-enter!\n\n");}while(numWithdrawals<0||numWithdrawals>50);/* End do while *//* Prompt user for number of deposits */do{printf("Enterthenumberofdeposits:");scanf("%i",&numDeposits);fflush(stdin);printf("\n");if(numDeposits<0||numDeposits>50)printf("Error:Numberofdepositsmustbeatleastzeroandnomorethanfifty,pleasere-enter!\n\n");}while(numDeposits<0||numDeposits>50);/* End do while */for(x=0;x<=numDeposits-1;x++){do{printf("Entertheamountofdeposit#%i:",x+1);scanf("%f",&deposits[x]);fflush(stdin);if(deposits[x]<=0)printf("***Depositamountmustbegreaterthanzero.Pleasere-enter!***\n");}while(deposits[x]<=0);/* End do while loop */}/* end for loop */currentBalance=+initialBalance+deposits[x];printf("\n");/* Prompt user for withdrawals */for(x=0;x<=numWithdrawals-1;x++){do{printf("Entertheamountofwithdrawal#%i:",x+1);scanf("%f",&withdrawals[x]);fflush(stdin);if(withdrawals[x]>currentBalance)printf("***Withdrawalamountexceedscurrentbalance.***\n");elseif(withdrawals[x]<=0)printf("***Withdrawalamountmustbegreaterthanzero.Pleasere-enter!***");}while(withdrawals[x]>currentBalance||withdrawals[x]<=0);/* End do while loop */currentBalance=currentBalance-withdrawals[x];}/* end for loop */balance=currentBalance-withdrawals[x]+deposits[x];if(balance==0){printf("\n***Yourbalanceisnowzero.Nomorewithdrawalscanbemadeatthistime.***\n");numWithdrawals=x;}/* End if *//* Calculate and display balance */{printf("\n***Theclosingbalance%sis$%.2f***\n",firstName,balance);if(balance>=5000.00)printf("***it'stimetoinvestsomemoney!***\n");elseif(balance>=15000.00&&balance<=49999.99)printf("\n***maybeyoushouldconsideraCD.***\n");elseif(balance>=1000.00&&balance<=14999.99)printf("\n***keepupthegoodwork.***\n\n");elseprintf("***%syourbalanceisgettinglow!***\n",firstName);}/* End if else and display comment*//* Calculate and display bank record */printf("\n***BankRecord***\n");printf("\nStartingBalance:$%.2f\n\n",initialBalance);for(x=0;x<=numDeposits-1;x++){printf("Deposit#%i:%.2f\n",x+1,deposits[x]);}/* End for loop */for(x=0;x<=numWithdrawals-1;x++){printf("\nWithdrawal#%i:%.2f",x+1,withdrawals[x]);}/* End for loop */printf("\n\nEndingBalanceis:$%.2f\n",balance);return(0);
} / end main /
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I removed the typo + sign for currentBalance = + initialBalance + deposits[x]; didn't make a difference. Thanks again for your assistance, it seems to be accumulating wrong.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This is not a C problem, it is a clarity of thought problem. Don't hack away at it without really understanding. Think about it, print it out and walk through it with simple values.
The line
currentBalance = initialBalance + deposits[x] ;
is obviously wrong outside the loop since x will be equal to numDeposits, so you will have indexed past the end of teh array, and it will have ignored all inputs. Putting it inside the loop is also wrong because you will add the end up with the sum of all the inputs plus numDeposits * initialBalance.
The rather obvious solution is:
currentBalance = initialBalance ; // before the loop
and then
currentBalance += deposit[x] ; // within the loop but only if input was validated (i.e. >= 0 )
This is the same pattern you used for withdrawals, why would you not make deposit the same?
Note your error messages are wrong, since the code allows a deposit/withdrawl equal to zero, but the message says it must be greater than zero. I would suggest that the code is correct, there is no good reason to disallow a zero deposit.
Your for loop is unnecessarily complicated; you have:
> for (x = 0; x <= numDeposits - 1; x++)
which is functionally identical to;
> for (x = 0; x < numDeposits ; x++)
which is more usual and more efficient way of writing a 0 to n-1 loop.
but currentBalance is already the correct value as you accumulated it as the values were entered. This line creates an incorrect value for 'balance', and moreover only accounts for one value of withdrawl and deposit (an x may not be a valid index for either!). That line should be removed.
What is the line for?;
numWithdrawals = x;
It is unnecessary, numWithdrawals is already correct at that point - it is what determined the value of x!
From a user point of view asking to enter transactions in a different order to asking how many there are is counter intuitive. In fact I would get deposits immediatly after asking for the number, then ask for the number of withdrawals then get those transactions. Asking for both counts up-front is weird.
A better way still is not to get a count at all, and simply have the user enter a sentinel value when done (with a count limit). Why should a user have had to count their transactions before starting when the computer can do that for them?
Stepping this code in a debugger would be a more efficient method of debugging than asking on a forum. If your tutor did not address debugging very early on in the course (like right after writing "hello, world"), then you are doomed to make slow progress. It is the single most useful programming tool after the compiler itself. Unfortunately for you the one in Dev-C++ sucks, which is why I used VC++ on your code - that's free too.
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
When all else fails, one can also use the "old fashioned" method for debugging - i.e. printing out the values of variables through strategically placed printf's in your code. This can help you understand what is going on with the flow of your program. I still do it from time to time.
Note that you should get in the habit of insuring that you print is done when you want it, i.e.
printf("My code made it here\n");
fflush(stdout);
Wayne
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Please do not ignore the idea of putting print statements in your code as you go along to check that things are doing what you think they should.
You can learn a lot from this "in line" debugging process.
And don't miss Clliffords point about logical problem solving. Despite what someone new to programming might think, programming is not mostly about putting magic words in the right order, its about logic.
Wayne
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
If you must use printf debugging (no substitute for a working debugger IMO), then at least do it like this:
// debug.h - basic debug macros
ifndef DEBUG_H
define DEBUG_H
ifndef _NDEBUG
include <stdio.h>
if defined( GNUC )
define DEBUGPRINTF( format, args... ) printf( "%s(%d):%s: " format "\n", FILE, LINE, FUNCTION, ## args ) ;
else
define DEBUGPRINTF( format, ... ) printf( "%s(%d):%s: " format "\n", FILE, LINE, FUNCTION, ## VA_ARGS )
endif
else
define DEBUGPRINTF()
endif
endif
Note there are no commas between the strings in the printf call; that is intentional, not a bug!
Put that code in a header file debug.h, and include it where necessary. That way you can write code like this:
include "debug.h"
int main()
{
int x = 10 ;
DEBUGPRINTF( "x = %d", x ) ;
system("pause") ;
}
Which for debug builds will output:
c:\projects\sandbox\main.cpp(6):main: x = 10
and for release builds will output nothing without any changes to the code. The automatic insertion of the filename, line number and function is useful since it means you can simply write:
DEBUGPRINTF() ;
if you simply want a trace statement. In fact what I do is add:
define HERE() DEBUGPRINTF()
to the debug macros, then rather than DEBUGPRINTF() you can write the perhaps more intuitive HERE(). You don't actually need the parentheses in the definition or usage, but it retains the 'function call' semantics that code-readers might expect. Simply writing HERE in the middle of your code just looks odd.
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am not asking anyone to understand it or be comfortable with it, merely to copy&paste it and use it (and reap the benefits). That is no more complex that using printf(), which is still complicated, but made simple by the fact that it is done for you, just as this is.
It is simple code re-use, you don't need to understand it to use it. If that were true few would ever use the STL, or even printf()!
As it happens that code was written for compatibility with with GCC 2.95 which used a non-standard form for variadic macros (not standardised until C99). In 3.x and later the following simplification can be used:
// debug.h - basic debug macros
ifndef DEBUG_H
define DEBUG_H
ifndef _NDEBUG
include <stdio.h>
define DEBUGPRINTF( format, ... ) printf( "%s(%d):%s: " format "\n", FILE, LINE, FUNCTION, ## VA_ARGS )
else
define DEBUGPRINTF()
endif
endif
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Despite my advocacy for using a debugger, in real-time systems it is not always possible to stop the code and have it behave correctly in the face of asynchronous events or threads, so debug output is still sometimes necessary. Where there are multiple concurrent threads, the automatic location information is invaluable. In those situations I would also add a timestamp and thread ID to the default output.
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hey guys,
I've spent several hours on this and it's starting to drive me crazy. It's homework so I just need a point in the right direction, a hint or two...maybe three. The program doesn't calculate the balance correctly and I'd like to put a blank line between deposit and withdrawal entries. Suggestions, corrections, clues?
include <stdio.h>
int main(void)
{
} / end main /
Thank you in advance for your assistance.
I compiled it with VC++ 2008 and got:
sandbox.cpp(83) : warning C4700: uninitialized local variable 'totalDeposits' used
sandbox.cpp(106) : warning C4700: uninitialized local variable 'totalWithdrawals' used
I imagine Dev-C++ issued somethiong similar. If not add the following options compiler options; -Wall -Werror. Since you are usiing C's stdio library add -Wformat also.
Warnings are errors, read them, understand them, fix them. These are certainly causing you problems. When the execition gets to:
totalWithdrawals = totalWithdrawals + withdrawals[x];
for example, the initial value of totalWithdrawls is not deterministic, and quite unlikely to be zero.
Clifford
Ran in DEV-C++, no compile errors to on this end??? I'll work with the totalWithdrawls until I check back. Thanks for your help...
Hey Clifford,
I'm not sure whats up...I tried the compile on both Dev-C++ and C-Free 4 Pro and no errors on either?
Compiling C:\ANSI_C\bankbal.c...
Complete Compile C:\ANSI_C\bankbal.c: 0 error(s), 0 warning(s)
Generated C:\ANSI_C\bankbal.o
Checking file dependency...
Linking...
Complete Make bankbal: 0 error(s), 0 warning(s)
Generated C:\ANSI_C\bankbal.exe
>> Ran in DEV-C++, no compile errors to on this end???
Well they were warnings not errors. My opinion is that warnings should be considered errors however, if you care about teh quality of your code. Did you add the warning options I suggested? Post the compile log.
Either way, you still need to initialise the variables. VC++ 2008 Express Edition is free too you know, you could just use that.
Clifford
Clifford,
Here's the compile log as requested.
Compiler: Default compiler
Executing gcc.exe...
gcc.exe "C:\ANSI_C\bankbal.c" -o "C:\ANSI_C\bankbal.exe" -Wall -Werror -ansi -traditional-cpp -pg -g3 -I"C:\Dev-Cpp\include" -L"C:\Dev-Cpp\lib" -lgmon -pg -g3
C:\ANSI_C\bankbal.c: In function `main':
C:\ANSI_C\bankbal.c:195: warning: control reaches end of non-void function
Execution terminated
Compilation successful
Here's the program written in ANSI C after some clean up. I have no clue why it doesn't calculate the balance correctly. I've rearanged the variables a bit and back without success.
include <stdio.h>
int main(void)
{
} / end main /
I subsituted return (0); for getchar( ); before ending main and this is the compile log:
Compiler: Default compiler
Executing gcc.exe...
gcc.exe "C:\ANSI_C\bankbal.c" -o "C:\ANSI_C\bankbal.exe" -Wall -Werror -ansi -traditional-cpp -pg -g3 -I"C:\Dev-Cpp\include" -L"C:\Dev-Cpp\lib" -lgmon -pg -g3
Execution terminated
Compilation successful
It looks like the warnings are gone? How about your end? Any idea why the balance is wacked?
The problem is that your not initializing two very imprtant values.
First you did...
float totalDeposits;
float totalWithdrawals;
Then you did...
totalDeposits = totalDeposits + deposits[x];
currentBalance = totalDeposits + initialBalance;
And then...
totalWithdrawals = totalWithdrawals + withdrawals[x];
currentBalance=currentBalance - withdrawals[x];
So those two values had started life with garbage values inside them.
So to fix all your problems, all you need to do is...
float totalDeposits = 0.0;
float totalWithdrawals = 0.0;
Thanks guys, I figured it out I think, you both pointed at the "total..." nonsense. I took those entries out and moved some stuff around a little and it seems to compile and run ok now. I do appreciate your help as always.
Loose the following options:
-ansi -traditional-cpp -pg -lgmon
unless you are really sure that you need them and know what they are for. Note that you have -pg specified twice, probably in the project options and the global compiler options. -traditional-cpp is particularly problematic and almost certainly unnecessary - it is probably not what you think it is, the "cpp" refers to the C pre-processor, and not C++ as you might think.
> C:\ANSI_C\bankbal.c:195: warning: control reaches end of non-void function
> Execution terminated
> Compilation successful
That is very odd. You have a warning and specified -Werror, yet compilation was successful. Moreover you are indeed not getting the uninitialised variable warning. Neither should happen.; what version of Dev-C++ is this you are using?
> I have no clue why it doesn't calculate the balance correctly.
I told you twice, and then Ron told you again! I could have posted the fix as code, but you said you only wanted a push in the right direction, you seem to be perversely resisting the nudge!
Clifford
I follow you now (I think)...I removed the total... stuff but I still have a calculation problem that I don't quite see yet. Here's what I have so far...DEV-C++ Version 4.9.9.2
Compiler: Default compiler
Executing gcc.exe...
gcc.exe "C:\ANSI_C\bankbal.c" -o "C:\ANSI_C\bankbal.exe" -ansi -pg -g3 -I"C:\Dev-Cpp\include" -L"C:\Dev-Cpp\lib" -lgmon -pg -g3
Execution terminated
Compilation successful
include <stdio.h>
int main(void)
{
} / end main /
I removed the typo + sign for currentBalance = + initialBalance + deposits[x]; didn't make a difference. Thanks again for your assistance, it seems to be accumulating wrong.
I moved the currentBalance = initialBalance + deposits[x]; within the for loop but I think I'm missing something after the loop?
This is not a C problem, it is a clarity of thought problem. Don't hack away at it without really understanding. Think about it, print it out and walk through it with simple values.
The line
currentBalance = initialBalance + deposits[x] ;
is obviously wrong outside the loop since x will be equal to numDeposits, so you will have indexed past the end of teh array, and it will have ignored all inputs. Putting it inside the loop is also wrong because you will add the end up with the sum of all the inputs plus numDeposits * initialBalance.
The rather obvious solution is:
currentBalance = initialBalance ; // before the loop
and then
currentBalance += deposit[x] ; // within the loop but only if input was validated (i.e. >= 0 )
This is the same pattern you used for withdrawals, why would you not make deposit the same?
Note your error messages are wrong, since the code allows a deposit/withdrawl equal to zero, but the message says it must be greater than zero. I would suggest that the code is correct, there is no good reason to disallow a zero deposit.
Your for loop is unnecessarily complicated; you have:
> for (x = 0; x <= numDeposits - 1; x++)
which is functionally identical to;
> for (x = 0; x < numDeposits ; x++)
which is more usual and more efficient way of writing a 0 to n-1 loop.
After the withdrawl loop you have:
balance = currentBalance - withdrawals[x] + deposits[x];
but currentBalance is already the correct value as you accumulated it as the values were entered. This line creates an incorrect value for 'balance', and moreover only accounts for one value of withdrawl and deposit (an x may not be a valid index for either!). That line should be removed.
What is the line for?;
numWithdrawals = x;
It is unnecessary, numWithdrawals is already correct at that point - it is what determined the value of x!
From a user point of view asking to enter transactions in a different order to asking how many there are is counter intuitive. In fact I would get deposits immediatly after asking for the number, then ask for the number of withdrawals then get those transactions. Asking for both counts up-front is weird.
A better way still is not to get a count at all, and simply have the user enter a sentinel value when done (with a count limit). Why should a user have had to count their transactions before starting when the computer can do that for them?
Stepping this code in a debugger would be a more efficient method of debugging than asking on a forum. If your tutor did not address debugging very early on in the course (like right after writing "hello, world"), then you are doomed to make slow progress. It is the single most useful programming tool after the compiler itself. Unfortunately for you the one in Dev-C++ sucks, which is why I used VC++ on your code - that's free too.
Clifford
> I subsituted return (0); for getchar( );
You should have added it after getchar(). The getchar() was perhaps still useful.
When all else fails, one can also use the "old fashioned" method for debugging - i.e. printing out the values of variables through strategically placed printf's in your code. This can help you understand what is going on with the flow of your program. I still do it from time to time.
Note that you should get in the habit of insuring that you print is done when you want it, i.e.
printf("My code made it here\n");
fflush(stdout);
Wayne
Thank you very much Clifford, I followed your suggestions with success. Excellent advise as always, it is greatly appreciated.
Please do not ignore the idea of putting print statements in your code as you go along to check that things are doing what you think they should.
You can learn a lot from this "in line" debugging process.
And don't miss Clliffords point about logical problem solving. Despite what someone new to programming might think, programming is not mostly about putting magic words in the right order, its about logic.
Wayne
If you must use printf debugging (no substitute for a working debugger IMO), then at least do it like this:
// debug.h - basic debug macros
ifndef DEBUG_H
define DEBUG_H
ifndef _NDEBUG
include <stdio.h>
if defined( GNUC )
define DEBUGPRINTF( format, args... ) printf( "%s(%d):%s: " format "\n", FILE, LINE, FUNCTION, ## args ) ;
else
define DEBUGPRINTF( format, ... ) printf( "%s(%d):%s: " format "\n", FILE, LINE, FUNCTION, ## VA_ARGS )
endif
else
define DEBUGPRINTF()
endif
endif
Note there are no commas between the strings in the printf call; that is intentional, not a bug!
Put that code in a header file debug.h, and include it where necessary. That way you can write code like this:
include "debug.h"
int main()
{
int x = 10 ;
}
Which for debug builds will output:
c:\projects\sandbox\main.cpp(6):main: x = 10
and for release builds will output nothing without any changes to the code. The automatic insertion of the filename, line number and function is useful since it means you can simply write:
DEBUGPRINTF() ;
if you simply want a trace statement. In fact what I do is add:
define HERE() DEBUGPRINTF()
to the debug macros, then rather than DEBUGPRINTF() you can write the perhaps more intuitive HERE(). You don't actually need the parentheses in the definition or usage, but it retains the 'function call' semantics that code-readers might expect. Simply writing HERE in the middle of your code just looks odd.
Clifford
I would submit that if someone is comfortable enough to do something like this - then they are probably comfortable enough to use the debugger.
My suggestion was based on trying to keep things simple and relatively natural for a new-ish programmer.
But we don't have to teach alike, do we? :)
Wayne
I am not asking anyone to understand it or be comfortable with it, merely to copy&paste it and use it (and reap the benefits). That is no more complex that using printf(), which is still complicated, but made simple by the fact that it is done for you, just as this is.
It is simple code re-use, you don't need to understand it to use it. If that were true few would ever use the STL, or even printf()!
As it happens that code was written for compatibility with with GCC 2.95 which used a non-standard form for variadic macros (not standardised until C99). In 3.x and later the following simplification can be used:
// debug.h - basic debug macros
ifndef DEBUG_H
define DEBUG_H
ifndef _NDEBUG
include <stdio.h>
define DEBUGPRINTF( format, ... ) printf( "%s(%d):%s: " format "\n", FILE, LINE, FUNCTION, ## VA_ARGS )
else
define DEBUGPRINTF()
endif
endif
Clifford
Let us agree to disagree.
Wayne
Of course. It is the end users choice.
Despite my advocacy for using a debugger, in real-time systems it is not always possible to stop the code and have it behave correctly in the face of asynchronous events or threads, so debug output is still sometimes necessary. Where there are multiple concurrent threads, the automatic location information is invaluable. In those situations I would also add a timestamp and thread ID to the default output.
Clifford