Error in "if not true" - C - c

I'm kinda new in C so I don't know if im allowed do to the following "if" in C, my error happens in the if line but the error is a segmentation fault, that should be a uninitialized variable but i give her a value from a file...well, there is the code:
char t1, ch;
if((fscanf(f,"P%d", &t1)) == 1){
if(!((strcmp(t1,"P2")==0) || (strcmp(t1,"P5")==0))){ // error here
fprintf(stderr, "\nTipo de imagem invalido.\n");
fclose(f);
return NULL;
}
If anyone can help me i will appreciate...
Thank you in advance!

Edit: I have rewritten answer to be complete and correct.
You are expecting to put an integer %d into a of char, which are most likely of different sizes. int is at least same size, and often bigger, so probably this is 1st place that should have blown up.
You can look at table here to figure out what format string specifier to use to match size of the variable you are reading. For a char it should be %hhd.
Also please note you use a string comparison function strcmp for a single character. Not sure why compiler did not point out type miss-match between char* and char.
You could force it to work with &t1 but it could end up with memory access faults, as strcmp expects the input to be a null-terminated string, which for single character is valid only for an empty string '\0'.
Also. If you write a format string like "P%s" the P symbol will not appear in the output.
What you can do.
Sticking to the string is tricky.
You could read whole string, like P3, and compare strings as you do, however you need to remember that they are null terminated. So to hold P3 you need something like char t1[3]. char t1; will certainly not hold "P3".
Also, unless your input is well formed and you are sure of, it is dangerous to read string from scanf with plain %s. You never know how long the input will be and it might end up overflowing your buffer...
You should specify the length of the string to read e.g. %2s.
#include <stdio.h>
#include <stdlib.h>
#define TYPE_SIZE 2
char ch;
int size;
char t1[TYPE_SIZE+1];
int main(){
if( (scanf("%2s", &t1) == 1)){
printf("t1=%s", t1);
if(!((strcmp(t1,"P2")==0) || (strcmp(t1,"P5")==0))){ // error here
fprintf(stderr, "\nTipo de imagem invalido.\n");
return -1;
}
} else fprintf(stderr, "Wrong input.\n");
return 0;
}
Still with this if you will input P5456456, there will be no error. You would need to consume input after 1st two characters and test it. You also need to keep track of max type length. You could also change TYPE_SIZE to something extra large in advance, but it is something to look for, and buggy prone (more theoretical, but still). Whenever you change TYPE_SIZE you need to update the format string, or construct it dynamically - more code.
Personally I would probably try reading type number into an integer and construct the if vs it.
#include <stdio.h>
#include <stdlib.h>
char ch;
int size;
unsigned char t1;
int main(){
if( (scanf("P%hhu", &t1) == 1)){
printf("t1=%u\n", t1);
if(!((t1 == 2) || (t1 == 5))){ // error here
fprintf(stderr, "\nTipo de imagem invalido.\n");
return -1;
}
} else fprintf(stderr, "Wrong input.\n");
return 0;
}

You should get segmentation fault even in
if((fscanf(f,"P%d", &t1)) == 1){
You should use
int t1;
In strcmp, you are passing t1 which is char not const char *. Here, char value is being typecasted to a pointer and now it tries to access the value at the location of t1. And this results in segmentation fault. So change is
int t1;
if((fscanf(f,"P%d", t1))){
if(!((2 == t1) || (5 == t1))){ // error here
fprintf(stderr, "\nTipo de imagem invalido.\n");
fclose(f);
return NULL;
}

Related

Why am I getting a Segmentation Fault when reading in a text file and storing into an array? [duplicate]

This question already has answers here:
Getting a stack overflow exception when declaring a large array
(8 answers)
Closed 5 years ago.
I need to read in a line of text, store it into an array. When I compile the program, it works but then when I execute it, I receive a segmentation fault. I have read other questions and tried what they have suggested and nothing seems to be working.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main() {
FILE *file;
char text[10000000], *line[10000000];
int i=0;
file = fopen("/home/Documents/xxxxxx_HW01/text.txt", "r");
if(file == NULL) {
printf("cannot open file");
exit(1);
}
while (i< 10000 && fgets(text, sizeof(text), file)!= NULL){
line[i] = strdup(text);
i++;
}
for (i=0; text[i] != '\0'; i++)
printf("%c ", text[i]);
fclose(file);
}
Continuing from my comment,
text[i] = strdup (text);
Is wrong. It attempts to assign a pointer (the result of strdup) to text[i] a signed char value. You need to use a separate array of pointers (or declare a pointer to pointer to char, e.g. char **lines; and then allocate pointers and then for each line).
The most important thing you can do is Listen to what your compiler is telling you. To make sure you are getting the benefit of your compilers help, always compile with warnings enabled and do not accept code until it compiles without warning. For gcc that means adding at minimum -Wall -Wextra to your compile string. For clang, -Weverything will do. For cl.exe (VS) add /Wall. Then read and understand the warnings. The compiler will give you the exact line where any problem occurs.
If you are simply reading lines less than some number, you can avoid allocating pointer and just use an array of pointers, but you must keep track of the index (to avoid writing beyond the last element)
Based on what you are attempting, it looks like you are trying to do something similar to the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 1000
int main (void) {
FILE *file;
char text[MAX] = "",
*lines[MAX] = {NULL};
int i=0, j;
file = fopen ("/home/Documents/xxxxxx_HW01/text.txt", "r");
if(file == NULL) {
printf("cannot open file");
exit(1);
}
while (i < MAX && fgets (text, sizeof(text), file)!= NULL){
size_t len = strlen (text); /* get length */
if (len && text[len-1] == '\n') /* check if last is '\n' */
text[--len] = 0; /* overwrite with '\0' */
else { /* line too long - character remain unread */
fprintf (stderr, "error: line exceeds %d chars.\n", MAX - 2);
exit (EXIT_FAILURE);
}
lines[i] = strdup(text);
i++;
}
for (j = 0; j < i; j++) {
printf ("line[%3d] %s\n", j, lines[j]);
free (lines[j]); /* don't forget to free memory */
}
fclose(file);
return 0; /* main() is type int and therefore returns a value */
}
note: you should also remove the trailing '\n' included at the end of text by fgets -- example given above.
Look things over and let me know if you have further questions.
From what I remember sizeof will give you the size of the object type, and the fgets expects the maximum amount of chars you want to read, so you probably don’t want to use sizeof there.
Also you are increasing the index of your array indefinitely which is most likely going to give you a out of bounds exception.
Summing up I think you should try passing directly the size you set on your array on the fgets, and if you dont need the file to be all stored at the same time, just don’t increase i and handle each chunk in one iteration of the loop. If you do need the file all stored at once, make sure you have an array as big as your file size and perhaps use fread like this

Why is strlen causing a segmentation fault in C?

(Warning) Yes this is a part of an assignment I am working on, but I am completely desperate at this point and NO I am not looking for you guys to solve it for me, but any hint would be much appreciated!(/Warning)
I am pretty much trying to make an interactive menu, the user is meant to input an expression (For example "5 3 +") and the program should detect that it's in postfix notation, unfortunately I have been getting segmentation fault errors and I suspect they have something to do with the use of the strlen function.
EDIT: I was able to make it work, first the char expression[25] = {NULL}; line
becomes char expression[25] = {'\0'};
And when calling the determine_notation function I removed the [25] from the array I am passing like so:
determine_notation(expression, expr_length);
Also the input[length] part I changed to input[length-2] since like mentioned in a previous comment, input[length] == '\0' and input[length--] == '\n'.
All in all thanks for all the help!
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int determine_notation(char input[25], int length);
int main(void)
{
char expression[25] = {NULL}; // Initializing character array to NULL
int notation;
int expr_length;
printf("Please enter your expression to detect and convert it's notation: ");
fgets( expression, 25, stdin );
expr_length = strlen(expression[25]); // Determining size of array input until the NULL terminator
notation = determine_notation( expression[25], expr_length );
printf("%d\n", notation);
}
int determine_notation(char input[25], int length) // Determines notation
{
if(isdigit(input[0]) == 0)
{
printf("This is a prefix expression\n");
return 0;
}
else if(isdigit(input[length]) == 0)
{
printf("This is a postfix expression\n");
return 1;
}
else
{
printf("This is an infix expression\n");
return 2;
}
}
You probably got a warning explaining that you are converting a char to a pointer in this call:
expr_length = strlen(expression[25]);
// ^^^^
This is the problem - your code is referencing a non-existent element past the end of the array (an undefined behavior) and tries to pass it to strlen.
Since strlen takes a pointer to the beginning of the string, the call needs to be
expr_length = strlen(expression); // Determining size of array input until the NULL terminator

lack of understanding about sscanf usage

I would like to parse a specific line. So, I wrote the following piece of code in order to test the logic but I probably understand something wrongly :
typedef struct vers
{
char tu8UVersion[5];
char tu8UCommit[32];
}tst_prg_versions;
int main(int argc, char **argv)
{
tst_prg_versions lstVer;
char buf1[32];
char buf2[32];
char str[] = "BOARD-VERS-v1.0.0-git+9abc12345a";
sscanf(str, "BOARD-VERS-v%5s-git+%s", lstVer.tu8UVersion, lstVer.tu8UCommit);
printf("vers='%s'\n", lstVer.tu8UVersion);
printf("commit='%s'\n", lstVer.tu8UCommit);
sscanf(str, "BOARD-VERS-v%5s-git+%s", buf1, buf2);
printf("vers='%s'\n", buf1);
printf("commit='%s'\n", buf2);
return 0;
}
Once executed it returns :
vers='1.0.09abc12345a'
commit='9abc12345a'
vers='1.0.0'
commit='9abc12345a
Why the first vers is equals to 1.0.09abc12345a and not 1.0.0 ?
The first actually reads 1.0.0! Problem is, however, that tu8UVersion is not null-terminated, thus printf (not sscanf) prints beyound the field (doing so is undefined behaviour, however, as noted by sjsam) - which is immediately followed by tu8UCommit (does not necessarily have to be so, there could still be some fill bytes in between for alignment reasons!).
You need to either print 5 characters at most (%.5s in printf format string) or leave place for terminating the tu8UVersion with 0, as proposed in a comment already.
Something similar could have happened with your buffers, too. You are lucky that they appearently have been initialized to 0 already (probably because of compiled as debug version), which again does not necessarily have to happen. So with bad luck, you could have printed the whole rest of buf1 (having been left at garbage) and even beyond.
Why the first vers is equals to 1.0.09abc12345a and not 1.0.0 ?
Remember that you have
typedef struct vers
{
char tu8UVersion[5];
char tu8UCommit[32];
}tst_prg_versions;
I guess, there is a good chance the memory for tu8UVersion and tu8UCommit is contiguous. Since you have not null-terminated tu8UVersion when you do :
printf("vers='%s'\n", lstVer.tu8UVersion);
it goes on to print tu8UCommit and it stops because tu8UCommit is null terminated.
While sscanf seem the most sensible solution here you could also introduce some formatting :
char tu8UVersion[32];
/* version number can't get too big.
* So the first step is do allocated a
* reasonably - but not too - big size for it.
* So that you can be sure there are few empty bytes at the end.
*/
and then use a function to sanitize a string :
char* sanitized(char* ptr)
{
if(ptr[strlen(ptr)]!='\0') // include string.h for strlen
ptr[strlen(ptr)]='\0';
return ptr;
}
and print it like :
printf("vers='%s'\n", sanitized(lstVer.tu8UVersion));
Your problem has already been identified in the comments: You don't leave space for the terminating null character and the two strings are run together.
If you want to scan a version whose size you don't know beforehand, you can limit the characters to scan to decimal digits and points with %[.-9] or to everything except a hyphen with %[^-]. (The %[...] format is like %s, except that you must provide a list of valid characters in the brackets. A caret as first letter means that the string is made up of characters that are not listed. In other words, %s is short for %[^ \t\n]
When you scan a string, you should test the return value of sscanf to be sure that all items have been scanned correctly and contain valid values.
Here's a variant that scans version numbers of up to 11 letters:
#include <stdlib.h>
#include <stdio.h>
typedef struct vers
{
char tu8UVersion[12];
char tu8UCommit[32];
} tst_prg_versions;
int main(int argc, char **argv)
{
tst_prg_versions lstVer;
char str[] = "BOARD-VERS-v1.0.0-git+9abc12345a";
int n;
n = sscanf(str, "BOARD-VERS-v%11[^-]-git+%s",
lstVer.tu8UVersion, lstVer.tu8UCommit);
if (n == 2) {
printf("vers='%s'\n", lstVer.tu8UVersion);
printf("commit='%s'\n", lstVer.tu8UCommit);
} else {
puts("Parse error.");
}
return 0;
}

Multiple fscanf

I have written the following program that is intended to read a string from a file into variable "title":
#include <stdio.h>
#include <stdlib.h>
int main()
{
int m, b;
char *title;
FILE *fp;
fp = fopen("input2.txt", "r");
if (fp == NULL)
{
printf ("Error: file cannot be found\n");
return 1;
}
fscanf(fp, "<%d>\n<%d>", &m, &b);
printf("%d\n%d", m, b);
fscanf(fp, "<%s>", title);
fclose(fp);
return 0;
}
The above program crashes at the second call to fscanf. Why does this happen?
Your main problem is that you've not allocated space for the string to be read into. You can do this in multiple ways:
char title[256];
or:
char *title = malloc(256);
if (title == NULL)
{
fprintf(stderr, "Out of memory\n");
exit(1);
}
either of which should then be used with:
if (fscanf(fp, " <%255[^>]>", title) != 1)
{
fprintf(stderr, "Oops: format error\n");
exit(1);
}
or, if you have a system with an implementation of fscanf() that's compliant with POSIX 2008, you can use the m modifier to %s (or with %c, or, in this case, a scanset %[...] — more on that below):
char *title = 0;
if (fscanf(fp, " <%m[^>]>", &title) != 1) // Note the crucial &
{
fprintf(stderr, "Oops: format error\n");
exit(1);
}
This way, if the fscanf() succeeds in its entirety, the function will allocate the memory for the title. If it fails, the memory will have been released (or never assigned).
Note that I changed %s to %m[^>]. This is necessary because the original conversions will never match the >. If there is a > in the input, it will be incorporated into the result string because that reads up to white space, and > is not white space. Further, you won't be able to tell whether the trailing context was ever matched — that's the > in the original format, and it's still a problem (or not) in the revised code I'm suggesting.
I also added a space at the start of the string to match optional white space. Without that, the < at the start of the string must be on the same line as the > after the second number, assuming that the > is present at all. You should also check the return from the first fscanf():
if (fscanf(fp, "<%d>\n<%d>", &m, &b) != 2)
{
fprintf(stderr, "Oops: format error\n");
exit(1);
}
Note that the embedded newline simply looks for white space between the > and the < — that's zero or more blanks, tabs or newlines. Also note that you'll never know whether the second > was matched or not.
You could use exit(EXIT_FAILURE); in place of exit(1); — or, since this code is in main(), you could use either return 1; or return(EXIT_FAILURE); where the parentheses are optional in either case but their presence evokes unwarranted ire in some people.
You could also improve the error messages. And you should consider using fgets() or POSIX's getline() followed by sscanf() because it makes it easier (by far) to do good error reporting, plus you can rescan the data easily if the first attempt at converting it fails.
This:
char *title;
is just a pointer to a char. If fscanf writes more than one character to it, you will corrupt whatever happens to be in memory after
You need to do one of two things:
char title[50]; // Holds up to 49 characters, plus termination
Or:
#include <stdlib.h>
// ...
char *title = malloc(50 * sizeof(char)); // Same capacity as above
if (title == NULL) {
// handle out of mem error
}
// ...
free (title);
The first option is obviously much simpler, but requires you to know your array size at compile time.
If you are new to programming, and haven't encountered pointers and dynamic memory allocation yet, stick with the first option for now.

Learning C, would appreciate input on why this solution works

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];
As others have pointed out, you haven't allocated anything for scanf to read into. But you should also test the return value of scanf:
if ( scanf ("%s %u %i", cmd, &acct, &amount) != 3 ) {
// do some error handling
}
The scanf function returns the number of succesful conversions, so if someone types in XXXX when you expect an integer you want to be able to detect and deal with it. But frankly, user interface code that uses scanf() is never really going to be proof against this sort of thing. scanf() was actually intended for reading formatted files, not random input from humans.
This :
char *cmd = NULL;
Should be:
char cmd[100];
Please note:
You should ensure that the string the user will input in cmd has length less than 100 or n
cmd is initialised to a null pointer which never points at any memory. scanf doesn't check that cmd is valid before trying to write to what cmd points to.
A preliminary solution instead creates some space for cmd to point to:
char cmd[30]; /* DANGEROUS! */
but this is a very dangerous move because you may still get segfaults if the input is longer than expected and scanf tries to write to cmd[30] and beyond.
For this reason scanf is considered unsafe and should not be used in production code. Safer alternatives include using fgets to read a line of input and sscanf to process it.
Sadly, C I/O is very difficult to get right without introducing the possibility of buffer overflows into your program. You always need to be thinking about how much memory you have available and whether it will be enough to store the longest possible input you could receive. You also need to check the return values of most I/O functions for errors.
In your example, scanf() is being passed a null pointer.
char *cmd = NULL;
scanf() won't allocate space for the string - you'll need to allocate somewhere for the string to go.
char cmd[80];
...
scanf ("%s",cmd);
Your getting a segmentation fault because scanf() is attempting to write its output to unallocated space.
Others have pointed out the error in your program, but for a better understanding of pointers, since you are just starting to learn C, look at this question at SO.
Your basic problem is that you haven't allocated memory for your string. In C, you are responsible for all memory management. If you declare variables on the stack, this is easy. With pointers, it's a little more difficult. Since you have the line char* str = NULL, when you attempt to scanf into it, you write bytes to NULL, which is illegal. What the %s specifier does is write into what str points to; it can't change str, as parameters are passed by value. This is why you have to pass &acct instead of just acct.
So how do you fix it? You need to provide memory where the read-in string can live. Something like char str[5] = "". This makes str a five-element character array, big enough to hold "exit" and its terminating zero byte. (Arrays decay into pointers at the slightest provocation, so we're fine on that front.) However, this is dangerous. If the user enters the string malicious, you're going to write "malic" into str and the bytes for "icious\0" into whatever comes after that at memory. This is a buffer overflow, and is a classic bug. The simplest way to fix it here is to require the user to enter a command of at most N letters, where N is the longest command you have; in this case, N = 4. Then you can tell scanf to read in at most four characters: scanf("%4s %u %i", cmd, &acct, &amt). The %4s says "read in at most four characters", so you can't screw up other memory. However, note that if the user enters malformed 3 4, you won't be able to find the 3 and the 4, since you'll be looking at ormed.
The reason you could do scanf("%s %u %i", &cmd, &acct, &amount) is that C is not type-safe. When you gave it &cmd, you gave it a char**; however, it was happy to treat it as a char*. Thus, it wrote bytes over cmd, so if you passed in the string exit, cmd might (if it were four bytes wide and had the appropriate endianness) be equal to 0x65786974 (0x65 = e, 0x78 = x, 0x69 = i, 0x74 = t). And then the zero byte, or any other bytes you passed in, you would start to write over random memory. If you change it at strcmp too, however, it will also treat the value of str as a string, and everything will be consistent. As for why return 0; fails but exit(0) works, I'm not sure, but I have a guess: you may have been writing over the return address of main. That's stored on the stack too, and if it happens to come after cmd in the stack layout, then you might be zeroing it or scribbling on it. Now, exit must do its cleanup manually, jumping to the right locations, etc. However, if (as I think is the case, although I'm not sure) main behaves like any other function, its return jumps to the space on the stack stored as the return address (which is probably a cleanup routine of some sort). However, since you've scribbled over that, you get an abort.
Now, there are a couple of other small improvements you could make. First, since you're treating done as a boolean, you ought to loop while (!done) { ... }. Second, the current setup requires you to write exit 1 1 to exit the program, even though the 1 1 bit shouldn't be necessary. Third, you should check to see if you have successfully read all three arguments, so you don't get errors/inconsistencies; for instance, if you don't fix this, then the input
deb 1 2
deb 3 a
Calls debit(1,2) and debit(3,2), while still leaving the a in the input to trip you up. Finally, you should exit cleanly on EOF, rather than looping forever doing the last thing you did. If we put this together, we get the following code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void credit(unsigned int acct, int amount);
void debit(unsigned int acct, int amount);
void service_fee(unsigned int acct, int amount);
int main() {
char cmd[5] = "";
unsigned int acct = 0;
int amount = 0;
int done = 0;
while (!done) {
if (feof(stdin)) {
done = 1;
} else {
if (scanf("%4s", cmd, &acct) != 1) {
fprintf(stderr, "Could not read the command!\n");
scanf(" %*s "); /* Get rid of the rest of the line */
continue;
}
if (strcmp(cmd, "exit") == 0) {
done = 1;
} else {
if (scanf(" %u %i", &acct, &amount) != 2) {
fprintf(stderr, "Could not read the arguments!\n");
scanf(" %*s "); /* Get rid of the rest of the line */
continue;
}
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
fprintf(stderr, "Invalid input!\n");
}
}
/* Cleanup code ... */
}
return 0;
}
/* Dummy function bodies */
void credit(unsigned int acct, int amount) {
printf("credit(%u, %d)\n", acct, amount);
}
void debit(unsigned int acct, int amount) {
printf("debit(%u, %d)\n", acct, amount);
}
void service_fee(unsigned int acct, int amount) {
printf("service_fee(%u, %d)\n", acct, amount);
}
Note that if there is no "cleanup code", you can replace all your uses of done with break and remove the declaration of done, giving the nicer loop
while (1) {
if (feof(stdin)) break;
if (scanf("%4s", cmd, &acct) != 1) {
fprintf(stderr, "Could not read the command!\n");
scanf(" %*s "); /* Get rid of the rest of the line */
continue;
}
if (strcmp(cmd, "exit") == 0) break;
if (scanf(" %u %i", &acct, &amount) != 2) {
fprintf(stderr, "Could not read the arguments!\n");
scanf(" %*s "); /* Get rid of the rest of the line */
continue;
}
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
fprintf(stderr, "Invalid input!\n");
}
In order to fully understand what is going on here you need to understand some basics about C pointers. I suggest you take a look here if you are really that new to C:
http://www.cprogramming.com/tutorial.html#ctutorial
The most common cause of segfaults are detailed here:
http://www.cprogramming.com/debugging/segfaults.html

Resources