Segmentation fault - Core dumped in the code - c

This code is used to get n dates and sort them in the ascending order. I think the getdates function is not working properly.
main function implementation:
#include <stdio.h>
#define max 30
int leapyear(int year);/*to check whether it's leap year or not*/
int dater(int x);/*to find the date from a month begin with the beginning of the year */
void getdates(int f);/*get the date in put*/
int *caldays(int p);
int n, i, q;
int t, d, leap;
int day[30];
int month[30];
int year[30];
char ca[30];
char cb[30];
int dd[30];
int da[30];
int j, a, x;
char c1, c2;
int dayn, monthn, yearn;
int main()
{
printf("Please enter the number of dates and Press ENTER to finish\n");
/*get the numbers of dates*/
scanf("%i", &n);
printf("You have entered %i \n", n);
getdates(n);
printf("end");
for (i = 0; i <= n-1; i++)
{
printf("end");
while (day[i] < 1 || day[i] > 31 || month[i] < 1 ||
month[i] > 12 || year[i] < 1 || year[i] > 10000)
{
fprintf( stderr, "The date entered is not right, please enter again\n");
printf("Please enter the number of dates and Press ENTER to finish\n");
/*get the numbers of dates*/
scanf("%i", &n);
printf("You have entered %i \n", n);
getdates(n);
}
while (month[i] == 2 && day[i] > 29)
{
fprintf( stderr, "The date entered is not right, please enter again\n");
printf("Please enter the number of dates and Press ENTER to finish\n");
/*get the numbers of dates*/
scanf("%i", &n);
printf("You have entered %i \n", n);
getdates(n);
}
while ((month[i] == 4 ||month[i] == 6 ||
month[i] == 9 ||month[i] == 11) && day[i] > 30)
{
fprintf( stderr, "The date entered is not right, please enter again\n");
printf("Please enter the number of dates and Press ENTER to finish\n");
/*get the numbers of dates*/
scanf("%i", &n);
printf("You have entered %i \n", n);
getdates(n);
}
}
/*3 while loops are used to give msg and re-enter again when get an error input*/
caldays(n);
for (i = 0; x < n; ++i)
{
for (j = i + 1; j < n; ++j)
{
if (dd[i] > dd[j])
{
a = dd[i];
dd[i] = dd[j];
dd[j] = a;
}
/*sort the days in asending order in days array*/
}
}
printf("The %i dates in ascending order are\n", n);
for (i = 0; i < n; ++i)
printf("%d%c%d%c%d\n", day[i], ca[i], month[i], cb[i], year[i]);
/*print all the date in ascending order*/
}
/*find out wheter it's leap year or not*/
int leapyear(int year)
{
if (year % 4000 == 0)
{
return 1;
}
else if (year % 400 == 0)
{
return 1;
}
else if (year % 40 == 0)
{
return 1;
}
else if (year % 4 == 0)
{
return 1;
}
else
{
return 0;
}
}
/*find out the days for the month input*/
int dater(x)
{
int y=0;
switch(x)
{
case 1: y=0; break;
case 2: y=31; break;
case 3: y=59; break;
case 4: y=90; break;
case 5: y=120; break;
case 6: y=151; break;
case 7: y=181; break;
case 8: y=212; break;
case 9: y=243; break;
case 10:y=273; break;
case 11:y=304; break;
case 12:y=334; break;
default: fprintf( stderr, "the value entered is not right\n");
}
return y;
}
void getdates(int f)
{
for(i=0;i<f;i++)
{
q = i+1;
printf("Please Enter %i dates (DD/MM/YYYY or DD-MM-YYYY) and
Press ENTER to finish each one\n", n);
scanf("%d%c%d%c%d", &dayn, &c1, &monthn, &c2, &yearn);
printf("You have entered %i date %i%c%i%c%i\n", q, dayn, c1, monthn, c2, yearn);
day[i] = dayn;
month[i] = monthn;
year[i] = yearn;
ca[i] = c1;
cb[i] = c2;
}
return;
}
int *caldays(int p)
{
for (i=0; i < p-1; i++)
{
leap = leapyear(year[i]);
t = 0;
if(leap == 1)
{
t++;
}
/*if there is a leap add one day */
/*find for the days for month entered*/
d = dater(month[i]);
/* find out the total days from the date entered begin with 0 days*/
d = d + dayn + t + (yearn * 365);
dd[i] = d;/*put all the days in an array*/
}
return dd;
}

The mistake is instead of
caldays(n);
for (i = 0; x < n; ++i)
in main function, it should be
caldays(n);
for (i = 0; i < n; ++i)
In getdates() and wherever required, use "%d %c %d %c %d" instead of %d%c%d%c%d.
As soon as you get the program working,I suggest you to post it for review on https://codereview.stackexchange.com/. The experienced people there will help you tear apart your code and make your life easier for better understanding of readability of code.
I recommend you to read Difference between format specifiers %i and %d in printf.
While posting question do follow MCVE from next time if possible.

Related

Program (in C) doesn't start function, and it just simply ends

After running the next code, in the function get_data(), everything runs normally until I get to the end of the For, when program should call the function continue_function() but in somehow, ignores it, and the program just ends.
Am I calling it in a wrong way?
I'm just start learning programming in C and this is one of the last exam's exercises.
#include <stdio.h>
#define MAX 100
#define YES 1
#define NO 0
struct record
{
char fname[15+1];
char lname[20+1];
char phone[9+1];
long income;
int month;
int day;
int year;
};
struct record list[MAX];
int last_entry = 0;
void get_data(void);
void display_report(void);
int continue_function(void);
void clear_kb(void);
main()
{
int cont = YES;
int ch;
while(cont == YES)
{
printf("\n");
printf("\n MENU");
printf("\n =========\n");
printf("\n1. Enter Names");
printf("\n2. Print Report");
printf("\n3. Quit");
printf("\n\nEnter Selection ==> ");
scanf("%d", &ch);
clear_kb();
system("cls");
switch(ch)
{
case 1: get_data();
break;
case 2: display_report();
break;
case 3: printf("\n\nThank You for using this Program!");
cont = NO;
break;
default: printf("\n\nInvalid Choice, Please Select 1 to 3!");
break;
}
}
}
void get_data(void)
{
int cont;
int ctr;
for(cont = YES; last_entry < MAX && cont == YES; last_entry++)
{
printf("\n\nEnter information for Person %d.", last_entry+1);
printf("\n\nEnter first name: ");
gets(list[last_entry].fname);
printf("Enter last name: ");
gets(list[last_entry].lname);
printf("Enter phone in 123-4567 format: ");
gets(list[last_entry].phone);
printf("Enter Yearly Income: ");
scanf("%ld", &list[last_entry].income);
printf("Enter Birthday: ");
do
{
printf("\n\tMonth (0 - 12): ");
scanf("%d", &list[last_entry].month);
}
while (list[last_entry].month < 0 || list[last_entry].month > 12);
do
{
printf("\tDay (0 - 31): ");
scanf("%d", &list[last_entry].day);
}
while (list[last_entry].day < 0 || list[last_entry].day > 31);
do
{
printf("\tYear (1800 - 2025): ");
scanf("%d", list[last_entry].year);
}
while (list[last_entry].year < 1800 || list[last_entry].year > 2025);
cont = continue_function();
}
if(last_entry == MAX)
{
printf("\n\nMaximum Number of Names has been entered!\n");
}
}
void display_report(void)
{
long month_total = 0, grand_total = 0;
int x, y;
fprintf(stdout, "\n\n");
fprintf(stdout, "\n REPORT");
fprintf(stdout, "\n ========");
for(x = 0; x <= 12; x++)
{
month_total = 0;
for(y = 0; y < last_entry; y++)
{
if(list[y].month == x)
{
fprintf(stdout, "\n\t%s %s %s %ld", list[y].fname, list[y].lname, list[y].phone, list[y].income);
month_total += list[y].income;
}
}
fprintf(stdout, "\nTotal for month %d is %ld:", x, month_total);
grand_total += month_total;
}
fprintf(stdout, "\n\nReport Totals:");
fprintf(stdout, "\nTotal Income is %ld", grand_total);
fprintf(stdout, "\nAverage Income is %ld", grand_total/last_entry);
fprintf(stdout, "\n\n* * * End of Report * * *");
}
int continue_function(void)
{
char ch;
printf("\n\nDo you wish to continue? (Y)es/(N)o: ");
getc(ch);
while(ch != 'n' && ch != 'N' && ch != 'y' && ch != 'Y')
{
printf("\n%c is invalid!", ch);
printf("\n\nPlease enter \'N\' to Quit or \'Y\' to Continue: ");
getc(ch);
}
clear_kb();
if(ch == 'n' || ch == 'N')
{
system("cls");
return(NO);
}
else
{
system("cls");
return(YES);
}
}
void clear_kb(void)
{
char junk[80];
gets(junk);
}
You're not using your get functions properly:
https://www.tutorialspoint.com/c_standard_library/c_function_getc.htm
int getc(FILE *); for instance requires a FILE* as argument and returns the character, but you are passing the character as argument, it should look like ch = getc(stdin);.
On another note, notice that when you use scanf you pass &c? This is because for a value to be modified, you need to pass the address where it's stored (&) and not the value itself. So even if getc took a char, it would have to be getc(&ch).
You should follow a quick tutorial on pointers and types, if you come from a higher level language or if you're new that could be a good idea.

for loop repeats until value is less than three

I dont know why my for loop is not working. I have been trying for so long. It just runs for the do / while and gives return. Everything in the do / while loop. I have declared a macro outside the main function and I am using it as loop condition. I can't add more details, all I have is code.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define MIN_YEAR 2012
#define MAX_YEAR 2022
#define LOG_DAYS 3
int main(void)
{
const int JAN = 1;
const int DEC = 12;
int year = 0;
int month = 0;
char day1 = 01;
char day2 = 02;
char day3 = 03;
float ratingMorning = 0;
float ratingEvening = 0;
printf("General Well-being Log\n"
"======================\n");
do
{
printf("Set the year and month for the well-being log (YYYY MM): ");
scanf(" %d %d", &year, &month);
if ((MIN_YEAR > year || year > MAX_YEAR))
{
printf(" ERROR: The year must be between 2012 and 2022 inclusive\n");
}
if ((JAN > month || month > DEC))
{
printf(" ERROR: Jan.(1) - Dec.(12)\n");
}
if ((JAN <= month && month <= DEC) && (MIN_YEAR <= year && year <= MAX_YEAR))
{
printf("\n*** Log date set! ***\n\n");
break;
}
} while ((MIN_YEAR <= year || year <= MAX_YEAR) && (JAN <= month || month <= DEC));
for (int i = 0; i < LOG_DAYS; i++)
{
printf(" %d", year);
printf("-");
printf(" %d", month);
printf("-");
printf(" %d",day1);
printf(" Morning rating (0.0-5.0): ");
scanf(" %d", &ratingMorning);
if (ratingMorning < 0 || ratingMorning > 5)
{
printf(" ERROR: Rating must be between 0.0 and 5.0 inclusive!");
}
printf(" Evening rating (0.0-5.0): ");
scanf(" %d", &ratingEvening);
if (ratingEvening < 0 || ratingEvening > 5)
{
printf(" ERROR: Rating must be between 0.0 and 5.0 inclusive!");
}
}
return 0;
}
The test in the while part of the do / while loop is incorrect. It is much simpler to use a for(;;) loop and break when the input is correct, avoiding redundant and sometime inconsistent tests.
The scanf() conversion specifier for float is %f, not %d.
Here is a modified version:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define MIN_YEAR 2012
#define MAX_YEAR 2022
#define LOG_DAYS 3
int main(void) {
const int JAN = 1;
const int DEC = 12;
int year = 0;
int month = 0;
char day1 = 1;
char day2 = 2;
char day3 = 3;
float ratingMorning = 0;
float ratingEvening = 0;
printf("General Well-being Log\n"
"======================\n");
for (;;) {
printf("Set the year and month for the well-being log (YYYY MM): ");
if (scanf(" %d %d", &year, &month) != 2) {
printf("invalid input\n");
return 1;
}
if (year < MIN_YEAR || year > MAX_YEAR) {
printf(" ERROR: The year must be between 2012 and 2022 inclusive\n");
} else
if (month < JAN || month > DEC)) {
printf(" ERROR: Jan.(1) - Dec.(12)\n");
} else {
printf("\n*** Log date set! ***\n\n");
break;
}
}
for (int i = 0; i < LOG_DAYS; i++) {
printf(" %d- %d- %d", year, month, day1);
printf(" Morning rating (0.0-5.0): ");
if (scanf("%f", &ratingMorning) != 1) {
printf("invalid input\n");
return 1;
}
if (ratingMorning < 0 || ratingMorning > 5) {
printf(" ERROR: Rating must be between 0.0 and 5.0 inclusive!");
continue;
}
printf(" Evening rating (0.0-5.0): ");
if (scanf("%f", &ratingEvening) != 1) {
printf("invalid input\n");
return 1;
}
if (ratingEvening < 0 || ratingEvening > 5) {
printf(" ERROR: Rating must be between 0.0 and 5.0 inclusive!");
continue;
}
// ... handle the ratings and report success
}
return 0;
}
If the problem is that:
if (ratingMorning < 0 || ratingMorning > 5) is not working
i.e. the error line ERROR: Rating must be between 0.0 and 5.0 inclusive!" is never printed, then when you change the %d to %f in the scanf(" %d", &ratingMorning); lines, the errors are printed because now ratingMorning and ratingEvening contain valid values, whereas when they were input as integers, the values were invalid.

Function to check if entered number is a prime is broken though nothing seems to be wrong with the code

I was learning how to use 'switch' and was writing a program to do various functions and everything else is working except the function that checks if the entered program in a prime.
I really can't seem to find the problem with the code here, is there something I'm doing wrong?
#include <stdio.h>
int main(){
int x, c = 1, a, l;
printf("1. Factorial\n2. Prime or not\n3. Even or Odd\n4. Exit\nWhat would you like to do? ");
while (c != 4)
{
scanf_s("%d", &c);
switch (c)
{
case 1:
a = 1;
scanf_s("%d", &x);
for (l = 1; l <= x; l++)
a = a * l;
printf("Factorial of %d = %d\n", x, a);
break;
case 2:
scanf_s("%d", &x);
for (l = 1; l <= x; l++)
{
if (x % l == 0 && l != x)
{
printf("The number entered is not a prime.\n");
break;
}
else if (l == x)
{
printf("The number entered is a prime.\n");
break;
}
}
break;
case 3:
scanf_s("%d", &x);
if (x % 2 == 0)
printf("The number entered is even.\n");
else
printf("The number entered is odd.\n");
break;
case 4:
exit();
}
printf("\n1. Factorial\n2. Prime or not\n3. Even or Odd\n4. Exit\nWhat would you like to do? ");
}
}

How to Fix the Logic Errors in My "Guess the Movie" Game as a C Program

I have written a Guess the Movie game in the C programming language. My logic seems to be correct but whenever I run the program, it doesn't work as expected.
Here is my code
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ran = 1;
int l, j = 0, i = 0, total = 0, d = 0;
char b;
char a[20];
char s[1000];
int z;
FILE *my;
printf("Enter your name:\n ");
scanf("%s", s);
ran = rand() % 6;
if (ran == 1)
{
my = fopen("my1.txt", "r");
}
else if (ran == 2)
{
my = fopen("my.txt", "r");
}
else if (ran == 3)
{
my = fopen("my2.txt", "r");
}
else if (ran == 4)
{
my = fopen("my3.txt", "r");
}
else if (ran == 5)
{
my = fopen("my4.txt", "r");
}
for (d = 0; d < 20; d++)
fscanf(my, "%c", &a[d]);
fclose(my);
printf("GUESS THE MOVIE GAME\n");
for (j = 0; j < 7; j++)
{
if (a[j] == 'm')
{
printf("M ");
}
else
{
printf("_ ");
}
}
printf("\n");
printf("Let's begin the game\n");
for (i = 0; i < 7;)
{
if (a[i] != 'm')
{
printf("enter character number %d\n",i+1);
scanf("%c", &b);
if (b == a[i])
{
printf("its a right guess\n");
total = total + 4;
i++;
}
else if (b != a[i])
{
printf("Wrong choice\n");
if (total == 1 || total == 0)
{
total=0;
}
else
{
total = total - 2;
}
}
}
}
printf("You have guessd the movie\n");
printf("The movie name is: ");
for (i = 0; i < 7; i++)
{
printf("%c",a[i]);
}
printf("Your score is %d\n",total);
}
This is the program output that I get each time I run the above code:
Enter your name:
raj
GUESS THE MOVIE GAME
_ _ _ _ M _ _
Let's begin the game
Enter character number 1
Wrong choice
Enter character number 1
I
Wrong choice
Enter character number 1
Wrong choice
Enter character number 1
Besides the deficiencies pointed out in comments, there's this major logic error:
for (i = 0; i < 7;)
{
if (a[i] != 'm')
{
…
}
}
If the loop encounters an m, it repeats endlessly. Eliminate the if (a[i] != 'm') or add an else ++i.

using several different functions

For my assignment, my program needs to ask the user which of the five functions he wants to execute. The five functions include:
Summation of a number
Factorial of a number
Fibonacci value of the nth term.
gcd of two numbers
a to the power of b.
The user will be prompted repeatedly until he wishes to exit. All my functions work fine. However, i think i messed up on one of the loops because once i enter which function i want to execute and enter a value, it keeps displaying the answer in an infinite loop.
#include <stdio.h>
#include <math.h>
// function to find summation of a number
int summation(int k) {
int i;
for(i = k; i >= 0; i--) {
k = i + (i-1);
}
return k;
}
// function to find the factorail of a number
int factorial(int num) {
int i;
for(i = num - 1; i > 0; i--) {
num = num * i;
}
return num;
}
// dunxtion to find the fibonacci of the nth term
int fibonacci(int n){
int i, t1 = 0, t2 = 1, nextTerm;
for(i = 1; i <= n; i++) {
if(i == 1) {
printf("%d, ", t1);
continue;
}
if(i == 2) {
printf("%d, ", t2);
continue;
}
nextTerm = t1 + t2;
t1 = t2;
t2 = nextTerm;
printf("%d, ", nextTerm);
}
return nextTerm;
}
// function to find the gcd of two numbers
int gcd(int n, int m) {
int i, gcd;
for(i=1; i <= n && i <= m; i++) {
// Checks if i is a factor of both integers
if(n % i == 0 && m % i == 0)
gcd = i;
}
return gcd;
}
// function to find value of n to the power of m
int power(int n, int m) {
return pow(n, m);
}
int main(void) {;
int option ,n, m;
//Asks user for what they want to find
printf("If you would like to find the summation of a number, enter 1 \n");
printf("If you would like to find the factorial of a number, enter 2 \n");
printf("If you would like to find the fibonacci sequence of a number, enter 3 \n");
printf("If you would like to find the gcd of two numbers, enter 4 \n");
printf("If you would like to find the power of a number a to b, enter 5 \n");
printf("If you would like to exit, enter 0 \n");
scanf("%d", &option);
// Enables the program to prompt the user until they wish to exit
while(option != 0) {
switch(option) { //If user wishes to find the summation
case 1: if(option == 1) {
printf("Enter a number: ");
scanf("%d", &n);
while(n > 0) {
if(n < 1) { //message displayed if an invalid value is entered
printf("invalid value");
}
else {
printf("Summation of %d is %d", n, summation(n));
}
}
}
case 2: if(option == 2) { //if user wishes to find factorial of a number
printf("Enter a number: ");
scanf("%d", &n);
while(n >= 0) {//message displayed if an invalid value is entered
if(n < 0) {
printf("invalid value");
}
else {
printf("factorial of %d is %d", n, factorial(n));
}
}
}
case 3: if(option == 3) { //if user wishes to find the fibonacci value of the nth term
printf("Enter a number: ");
scanf("%d", &n);
while(n >= 0) {//message displayed if an invalid value is entered
if(n < 0) {
printf("invalid value");
}
else {
printf("fibonacci of %d is %d", n, fibonacci(n));
}
}
}
case 4: if(option == 4) {
printf("Enter a number: ");
scanf("%d %d", &n, &m);
while(n >= 0 && m >= 0) {
if(n < 0 || m < 0) {//message displayed if an invalid value is entered
printf("invalid value");
}
else {
printf("GCD of %d and %d is %d", n, m, gcd(n, m));
}
}
}
case 5: if(option == 5) {
printf("Enter a number: ");
scanf("%d %d", &n, &m);
while(n >= 0 && m >= 0) {
if(n <= 0 || m < 0) {
printf("invalid value");
}
else {
printf("%d to the power of %d is %d", n, m, power(n, m));
}
}
}
default: if(option == 0) {
break;
}
}
scanf("%d", &option);
}
}
First of all, C has unstructured switch statement.
You need to add a break; statement after each of your case body to limit the execution for a particular case to the body mentioned under that case.
Otherwise, by default, (with the absence of a break statement) all the case statements works in fall-through manner. You can read more about it here.
That said, regarding the repeated execution of a single function, there's a serious flaw in most (if not all) of the the logic. For example, let's take this
while(n > 0) {
if(n < 1) { //message displayed if an invalid value is entered
printf("invalid value");
}
else {
printf("Summation of %d is %d", n, summation(n));
}
}
here, you're replying on n becoming 0 at some point to break out of the loop, but you did not modify n, at all.
To elaborate, C uses pass-by-value for argument passing, so for the call, summation(n), inside the function, whatever change you make to the parameter receiving the value of n, is not reflected in the caller, and thus, the n in the caller remains unchanged.
You just need a break statement at the end of every case
like:
case 1: if(option == 1) {
printf("Enter a number: ");
scanf("%d", &n);
while(n > 0) {
if(n < 1) { //message displayed if an invalid value is entered
printf("invalid value");
}
else {
printf("Summation of %d is %d", n, summation(n));
}
}
}
break;
As the control will fall down to next case if no break statement is present.

Resources