This is literally the first thing I've ever written in C, so please feel free to point out all it's flaws. :) My issue, however is this: if I write the program the way I feel is cleanest, I get a broken program:
#include <sys/queue.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* Removed prototypes and non related code for brevity */
int
main()
{
char *cmd = NULL;
unsigned int acct = 0;
int amount = 0;
int done = 0;
while (done==0) {
scanf ("%s %u %i", cmd, &acct, &amount);
if (strcmp (cmd, "exit") == 0)
done = 1;
else if ((strcmp (cmd, "dep") == 0) || (strcmp (cmd, "deb") == 0))
debit (acct, amount);
else if ((strcmp (cmd, "wd") == 0) || (strcmp (cmd, "cred") == 0))
credit (acct, amount);
else if (strcmp (cmd, "fee") == 0)
service_fee(acct, amount);
else
printf("Invalid input!\n");
}
return(0);
}
void
credit(unsigned int acct, int amount)
{
}
void
debit(unsigned int acct, int amount)
{
}
void
service_fee(unsigned int acct, int amount)
{
}
As it stands, the above generates no errors at compile, but gives me a segfault when ran. I can fix this by changing the program to pass cmd by reference when calling scanf and strcmp. The segfault goes away and is replaced by warnings for each use of strcmp at compile time. Despite the warnings, the affected code works.
warning: passing arg 1 of 'strcmp' from incompatible pointer type
As an added bonus, modifying the scanf and strcmp calls allows the program to progress far enough to execute return(0), at which point the thing crashes with an Abort trap. If I swap out return(0) for exit(0) then everything works as expected.
This leaves me with two questions: why was the original program wrong? How can I fix it better than I have?
The bit about needing to use exit instead of return has me especially baffled.
This is happening because of the scanf statement.
Look how cmd is pointing to NULL. When scanf is run, it writes to the address of cmd, which is NULL, thus generating a segfault.
The solution is to create a buffer for cmd, such as:
char cmd[20];
Now, your buffer can hold 20 characters. However, you now need to worry about buffer overflows if a user enters more than 20 characters.
Welcome to C.
EDIT: Also, note that your credit, debit, and service fee functions won't work as expected as you have them written. This is because the parameters are passed by value, not by reference. This means that after the method returns, any changes will be discarded. If you want them to modify the arguments you give, try changing the methods to:
void credit(unsigned int *acct, int *amount)
And then call them like:
credit(&acct, &amt);
Doing that will pass the parameters by reference, meaning that any changes you make inside the credit function will affect the parameters, even after the function returns.
You aren't allocating memory for cmd, so it's NULL
.
Try declaring it with some space:
char cmd[1000];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With