Why is this scanf statement causing Segmentation Faults? - c

I've been banging my head against this wall for an hour and I'm losing my mind... I have a piece of code (yes, it is homework) that throws a segmentation fault unless I comment out one of my scanf statements. I've tried to debug the problem using gdb, but I haven't really learned anything about that up until today.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * creditCard(char * ccNumber){
char * lastFour;
lastFour = (ccNumber + strlen(ccNumber) - 4);
return lastFour;
}
void zipCode(int zip){
printf("The zip code entered is: %d\n", zip);
}
int fuelGrade(int grade){
}
int main(void){
char * ccNumber = NULL;
int zip = 0;
int gasGrade = 0;
printf("Please Enter Credit Card Number: ");
scanf("%s", ccNumber);
printf("Please Enter Your Billing Zip Code: ");
scanf("%d", &zip);
printf("Select your Fuel Grade.\n Unleaded(1) Plus(2) Premium(3): ");
scanf("%d", &gasGrade);
ccNumber = creditCard(ccNumber);
printf("****-****-****-%s\n", ccNumber);
zipCode(zip);
return 0;
}
When I compile and run as is I get the following:
Please Enter Credit Card Number: 123413515
Please Enter Your Billing Zip Code: Select your Fuel Grade.
Unleaded(1) Plus(2) Premium(3): 1
Segmentation fault
Entering the zip code is skipped and I get a segfault right after entering anything in fuel grade. However, if I comment out the scanf("%d", &gasGrade); line the code runs fine.
Originally I did not have the variables initialized and I had the code organized a little differently, but I can't seem to find the right solution to this problem. What am I doing wrong here?
Thanks for your help!

Because by doing scanf("%s", ccNumber); with ccNumber = NULL you are dereferencing a NULL pointer.
The "%s" specifier of scanf() expects a pointer to valid memory where it can write the scanned data, you are passing a NULL pointer, it does not check if the pointer is NULL, and hence it's dereferencing the NULL pointer.
You need valid memory, so you can use the stack in this case, like this
char buffer[100];
char *ccNumber;
if (scanf("%99s", buffer) != 1)
problemScanning_buffer_DoNotUse_buffer_In_TheFollowingCode();
ccNumber = creaditCard(buffer);
Note the 99 above, it prevents overflowing buffer, and you MUST always check the return value of scanf() to prevent Undefined Behavior.

You either have to allocate memory for ccNumber using malloc or define it as an array char ccNumber[17] (16 digits + \0 character). Right now it is a pointer to a single char that you initialize to NULL.

You do not allocate memory for cc Number (ccNumber is NULL)
When reading a number you have to clear the line break character, but to read another value with scanf, automatically read the '\ n' that is in the input buffer (stdin).
printf("Please Enter Your Billing Zip Code: ");
scanf("%d", &zip);
Change:
scanf("%d", &zip);
To:
scanf("%d%*c", &zip);

Related

C program not printing the string that is given as input

I want the output to print the data that we print. but it is not working as expected and the output is not displaying and it is exiting
#include <stdio.h>
int main() {
char name[20], department[3], section[1];
printf("enter the name of the student:");
scanf("%s", name);
printf("enter your department:");
scanf("%s", department);
printf("enter the section");
scanf("%s", section);
printf("Name:%s \n Department:%s \n Section: %s ", name, department, section);
return 0;
}
Your program has undefined behavior because the arrays are too short and scanf() stores the user input beyond the end of the arrays, especially the last one, section that can only contain an empty string which scanf() cannot read anyway.
Make the arrays larger and tell scanf() the maximum number of characters to store before the null terminator, ie: the size of the array minus 1.
Here is a modified version:
#include <stdio.h>
int main() {
char name[50], department[50], section[50];
printf("enter the name of the student:");
if (scanf("%49s", name) != 1)
return 1;
printf("enter your department:");
if (scanf("%49s", department) != 1)
return 1;
printf("enter the section");
if (scanf("%49s", section) != 1)
return 1;
printf("Name:%s\n Department:%s\n Section: %s\n", name, department, section);
return 0;
}
Note that using scanf with a %s conversion requires that each data item be a single word without embedded spaces. If you want name, department and section to accommodate spaces, which is more realistic for anyone besides Superman Krypton A, you would use %[\n] with an initial space to skip pending whitespace and newlines (or fgets() but in another chapter):
#include <stdio.h>
int main() {
char name[50], department[50], section[50];
printf("enter the name of the student:");
if (scanf(" %49[^\n]", name) != 1)
return 1;
printf("enter your department:");
if (scanf(" %49[^\n]", department) != 1)
return 1;
printf("enter the section");
if (scanf(" %49[^\n]", section) != 1)
return 1;
printf("Name:%s\n Department:%s\n Section: %s\n", name, department, section);
return 0;
}
scanf(" %49[^\n]", name) means skip any initial whitespace, including pending newlines from previous input, read and store and bytes read different from newline, up to a maximum of 49 bytes, append a null byte and return 1 for success, 0 for conversion failure or EOF is end of file is reached without storing any byte. For this particular call, conversion failure can happen if there is an encoding error in the currently selected locale.
The problem is that you have not accounted for the null character. It should work with the following.
char name[20] , department[4] , section[2];
The reason this happens is that C requires an extra character for the null character \0 which tells the program when the string ends.
first of all you should respect the size of string ,so you should either convert section to char or increase the size of that string because you have here the problem of '\0' character...so the rule is : the size of string is the size what you need + 1 for '\0' NULL character
and her is two program i tried to Modification you program for two scenarios :
#include <stdio.h>
int main(){
/// any size you like just respect the NULL character
char name[20],department[4],section[23];
printf("enter the name of the student:");
scanf("%s",name);
printf("enter your department:");
scanf("%s",department);
printf("enter the section");
scanf ("%s",section);
printf("Name:%s \n Department:%s \n Section:%s ", name,department,section);
return 0;
}
and case of char :
#include <stdio.h>
int main(){
char name[20],department[4];
char section;
printf("enter the name of the student:");
scanf("%s",name);
printf("enter your department:");
scanf("%s",department);
printf("enter the section");
///don't forget this space before %c it is important
scanf (" %c",&section);
printf("Name:%s \n Department:%s \n Section:%c ", name,department,section);
return 0;
}
I watched for a long time and finally found the problem.
This is problem: char section[1];.
You declared the size is too short.
It looks like this after you declared it: section[0] = '\0';.
If you scanf a, the array data like section[0] = 'a';, and then it automatically add '\0' somewhere, so you got a memory leaking.
So replace char section[1]; to char section[2];.
I will not insist in the reasons of the other answers (that state other problems in your code than the one you are asking for) but I'll limit my answer to the reasons you don't get any output before the first prompt (there's no undefined behaviour before the third call of printf if you have input short enough strings to not overflow the arrays --- the last is impossible as long as you input one char, because to input one char you heed at least space for two)
I want the output to print the data that we print. but it is not working as expected and the output is not displaying and it is exiting
stdio works in linebuffer mode when output is directed to a terminal, which means that output is written to the terminal in the following cases:
The buffer is filled completely. This is not going to happen with a sort set of strings.
There is a \n in the output string (which there isn't, as you want the cursor to remain in the same line for input as the prompt string)
As there is no \n in your prompts, you need to make printf flush the buffer at each call (just before calling the input routines) You have two ways of doing this.
Calling explicitly the function fflush(3), as in the example below:
printf("enter the name of the student:");
fflush(stdout); /* <-- this forces flushing the buffer */
if (scanf(" %49[^\n]", name) != 1)
return 1;
configuring stdout so it doesn't use buffers at all, so every call to printf forces a write to the standard output.
setbuf(stdout, NULL); /* this disables buffering completely on stdout */
/* ... later, when you need to print something */
printf("enter the name of the student:"); /* data will be printed */
if (scanf(" %49[^\n]", name) != 1)
return 1;
But use this facilities only when it is necessary, as the throughput of the program is degraded if you disable the normal buffering of stdio.

C Program not printing the string in a structure

I made a program to take multiple inputs as string, store and print them.
Somehow the "Account Number" that's stored in a[i].acn is not printing. I've tried debugging and the problem seems to be in the loop that adds spaces to a[i].name .
#include <stdio.h>
#include <string.h>
struct Bank
{
char name[10],acn[8];
float bal;
}a[100];
int n,i,flag;
void add()
{
//function to add Rs. 100 to accounts that have balance over 1000
//and print the details.
for(i=0;i<n;i++)
if(a[i].bal>=1000)
a[i].bal+=100;
printf("\nS.No.\tName\t\tAcc. No.\tBalance(in Rs.)");
for(i=0;i<n;i++)
printf("\n[%d]\t%s\t%s\t%.2f",i+1,a[i].name,a[i].acn,a[i].bal);
}
void main()
{
printf("Enter the number of customers: ");
scanf("%d",&n);
printf("Enter the details of %d customers:\n",n);
for(i=0;i<n;i++)
{
printf("\nCustomer-%d",i+1);
printf("\nFirst Name: ");
fflush(stdin);
gets(a[i].name);
printf("Account Number: ");
fflush(stdin);
gets(a[i].acn);
printf("Account Balance: ");
scanf("%f",&a[i].bal);
}
for(i=0;i<n;i++)//The problem seems to be in this loop
while(strlen(a[i].name)<10)
strcat(a[i].name," ");
add();
}
Input:
Enter the number of customers: 2
Enter the details of 2 customers:
Customer-1
First Name: Aarav
Account Number: ASDF1234
Account Balance: 1200
Customer-2
First Name: Asd
Account Number: abcd1122
Account Balance: 999.9
Output:
S.No. Name Acc. No. Balance(in Rs.)
[1] Aarav 1300.00
[2] Asd 999.90
scanf() then gets() is bad
scanf("%d",&n); reads the integer, yet leaves the following '\n' in stdin that gets() reads as an empty string "".
I recommend to use fgets() to read all the line into a sizable buffer and then parse using sscanf(), strtol() etc.
Code overfills buffer
a[i].nam only has enough room for 9 characters and then the null character. Appending a space until it has a length more the 9 overfills .name[10].
struct Bank {
char name[10],acn[8];
float bal;
} a[100];
while(strlen(a[i].name)<10)
strcat(a[i].name," ");
Use while(strlen(a[i].name)<9) to pad with spaces, but not too many.
Money needs special considerations. For now, consider a long of lowest denominational (cents). Read in a double and then long balance = lround(input*100.0);
Other weaknesses exist.
There are few things to correct in your program.
Use fgets instead of gets because in gets there is no boundary check and there is a danger of reading beyond the allocated size.
When using fgets , scanf and even gets they all read the left over \n characters from the standard buffer , so using fgets we can avoid it if we properly use it.(scanf also avoids space characters but it cannot be used to read multiword strings)
remove fflush(stdin), its not required you can see reason here
And last, but certainly not least use int main() instead of void main()
You have this:
struct Bank
{
char name[10],acn[8];
float bal;
}a[100];
since C strings must end with a NUL character (aka '\0') the name can be at maximum 9 chars long.
But here
while(strlen(a[i].name)<10)
strcat(a[i].name," ");
you keep adding spaces until it's 10 characters long. In other word - you write outside the array.
Change name to be name[11]
Besides that gets and fflush(stdin) should be avoided.

Scanf won't continue after I seized an input text

so, I am basically building an array of students with their evaluation.
I made a basic struct :
struct Eleve{
char Nom[100];
int Note;
};
struct Eleve *array;
Then asking for how many children I want to input into my array, then loop and asking information for each child. But, when I enter an input into scanf("%s\n", array[i].Nom); the code stop.
int nbEleves;
float total = 0;
printf("Nombre?!\n");
scanf("%d", &nbEleves);
array = malloc(nbEleves * sizeof(struct Eleve));
int i = 0;
while (i < nbEleves) {
printf("Nom? ");
scanf("%s\n", array[i].Nom);
printf("La note? ");
scanf("%d\n", &array[i].Note);
total = total + array[i].Note;
i++;
}
It doesn't even go on the next printf. I don't understand why, because I don't get any build error or execution errors on this line. Eventually I would have looked at the format if by any chance I'd get an error there, but nothing. No errors, just not getting to the next step of the program.
I think my scanf looks right, and I've got no warnings on it. So, what can prevent the code to go further?
The data I entered in Nom is test.
You should not use scanf! This is an age old discussion that use of scanf requires care and is dangerous. Disadvantages of scanf.
Instead use fgets().
Check this answer How to read from stdin with fgets()? or this
Not able to input a string with spaces in a loop in C
But if you still insist on using scanf(), this may be useful:
while(i<nbEleves){
printf("Nom? ");
scanf(" %[^\n]",array[i].Nom);// remove the \n and notice the space before %[^\n]
printf("La note? ");
scanf("%d", &array[i].Note);
total = total + array[i].Note;
i++;
}
Also I suggest that you must free the memory you allocated using free() in order to prevent memory leaks.
free(array);
Remove the \n from scanf("%s\n", array[i].Nom); and scanf("%d\n", &array[i].Note); or press CTRL + D after you inserted the value.

strcmp call keeps crashing my program

I'm creating a "phonebook" program for school. Basically I have to get a user to input the names and phone numbers of their contacts into two different arrays. I got that part down, but after I have to give the user an option to search the contacts either via name or phone number and I'm running into some issues.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
int main()
{
int arraysize;
printf("How many phone numbers will you be entering: ");
scanf("%d", &arraysize);
int * phoneNumbers = malloc(arraysize);
char * names = malloc(arraysize);
for (int i = 0; i < arraysize; ++i)
{
printf("Please enter the name of person %d: ", i + 1);
scanf("%s", &names[i]);
printf("Please enter %s's phone number: ", &names[i]);
scanf("%d", &phoneNumbers[i]);
}
char * searchOption;
printf("Would you like to seach via name or phone number? ");
scanf("%s", &searchOption);
if (strcmp(searchOption, "name") == 0)
{
char * searchName;
int element;
bool stop = false;
while (stop = false)
{
searchName = NULL;
printf("\nPlease enter the name you wish to search for: ");
scanf("%s", &searchName);
for (int i = 0; i < arraysize; ++i)
{
if (strcmp(searchName, names[i]) == 0)
{
element = i;
stop = true;
break;
}
}
if (stop = false)
{
printf("\nname not found, please search again!");
}
}
}
I'm pretty sure it's crashing at the strcmp() call but I have no idea why
The problem is, in
scanf("%s", &searchOption);
you're doing it wrong.
You need to
First allocate memory to searchOption pointer (or make it an array).
pass searchOption, not &searchOption to scanf().
Same issue appears for char * searchName; also later in the code.
The crash is not directly caused by the strcmp() call.
This line is at fault:
scanf("%s", &searchOption);
First of all, there is a type mismatch. For %s you have to pass an argument of type char*, not char** as you did. To fix this, remove the take-address (&) operator.
Additionally, you need to allocate memory to scan into. The scanf function doesn't do that for you. As a quick and dirty fix, you can simply make searchOption an array. Replace its declaration with
char searchOption[100];
or such to fix this. You also want to limit the number of characters scanf() attempts to read:
scanf("%100s", searchOption);
so there can't be a buffer overflow.
An even better approach is to use fgets() instead of scanf(). The fgets() function is suited better for what you want to do. Read the manual for how to use fgets().
As Alter Mann said, the same problem occurs a second time further down. You need to repair that, too.
Also i think in strcmp you have used "name" whereas you declared it as names before.If you correct this maybe program works

Why am I getting a Segmentation error?

#include<stdio.h>
#include<string.h>
void main()
{
int entry,i;
printf("\nPlease indicate the number of records you want to enter :\n");
scanf("%d",entry);
char ent[entry][100000];
printf("\nPlease input records of students (enter a new line after each record), with following format first name last name score \n");
for(i=0;i<entry;i++)
{
gets(ent[i]);
printf("%s",ent[i]);
}
}
The following is a code to accept data of student , first name last name and then score.
main should return int, not void.
int main(void) {
/* ... */
}
scanf("%d",entry);
scanf expects the argument corresponding to the "%d" format specifier to be an int *. Your argument, however, is an int. Perhaps you meant this:
scanf("%d",&entry);
On that note, you should really check the return value of scanf. For all you know, the user didn't enter anything numeric.
if (scanf("%d", &entry) != 1) {
exit(0);
}
In fact, this still allows the user to enter a negative number. Have you ever seen an array of a negative number of items? Seems strange to me, too... I think size_t would be a more appropriate type than int (and as a result, you'll need to use the %zu format specifier)...
Last but not least, gets is deprecated because it makes it impossible to prevent the user from overflowing buffers, which could cause segfaults.
#include <stdio.h>
#include <string.h>
int main(void)
{
size_t entry;
printf("\nPlease indicate the number of records you want to enter :\n");
if (scanf("%zu",&entry) != 1)
{
exit(0);
}
char ent[entry][100000];
printf("\nPlease input records of students (enter a new line after each record), with following format first name last name score \n");
for(size_t i=0; i<entry; i++)
{
fgets(ent[i], sizeof ent[i], stdin);
printf("%s",ent[i]);
}
}
you should use int main()instead of void main
when you use you should scanf("%d",&entry) instead of scanf("%d",entry),what scanf need is an address.
you shouldn't use gets(),it's dangerous,try fgets()
scanf("%d",entry); //scanf("%d",&entry)
char ent[entry][100000]; //error
you should use malloc to get an array when you can not know the length of an array in compiling time
The error is in scanf use scanf("%d",&entry) instead of scanf("%d",entry);
Suggestion: use int as return type for main

Resources