Return pointer to a structure - c

I have this program, where you enter two dates into two structures (same type), and then I want a function to find which date I entered is the later date. It compares only year and month. Once the later date is found, I want the function to return a pointer to the structure with the later date. I then want to print out the later date.
This is what I have so far, but I get errors and I'm not sure about the pointer syntax.
Code:
#include <stdio.h>
struct date{
int year;
int month;
int day;
};
main()
{
struct date dates[2];
int i = 0, res = 0;
for ( i = 0 ; i < 2 ; i++){
printf("Enter a year!");
scanf("%d", &dates[i].year);
printf("Enter a month!");
scanf("%d", &dates[i].month);
printf("Enter a day!");
scanf("%d", &dates[i].day);
}
res = later(&dates[1], &dates[2]);
}
struct date *later(struct date *one, struct date *two)
{
if (one->year > two->year){
return *one;
}
else if (one->year == two->year){
if(one->month > two->month){
return *one;
}
else
return *two;
}
else {
return *two;
}
}
Error messages:
q4.c:28:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("%d", &res);
^
q4.c: At top level:
q4.c:32:14: error: conflicting types for ‘later’
struct date *later(struct date *one, struct date *two){
^
q4.c:26:9: note: previous implicit declaration of ‘later’ was here
res = later(&dates[1], &dates[2]);
^
q4.c:55:1: error: expected identifier or ‘(’ before ‘}’ token
}

There are multiple problem with your program:
There is no prototype for your function later() Solution: Add date *later(date *one, date *two); after ending declaration of struct date or move the whole function above main().
Change return type of you function to date* as you are returning a pointer to date object.
Change data type of res to date* as you want to store a pointer to date object.
Then print the object res is pointing to by printing each of its components individually as printf is not designed to print your custom data type.
This is only a suggestion but i recommend you moving declaration of int i to for(int i = 0; i < 2; i++); it is just considered better and saves memory.
If you want res to be an int you will have to return a object instead of a pointer and then typecast it to int. Guide on typecasting: http://www.cplusplus.com/doc/tutorial/typecasting/

There are a number of ways to handle the return as have been pointed out in the comments. You can either declare your later function as int (as you have), and use the return similar to the return from strcmp (0 - dates are equal, -1 first is earlier than last, 1 first is later than last).
You can also declare later as struct date * and return a pointer to the later date (which leaves you in a pickle as to what to return if the dates are equivalent).
Your return is more meaningful, if you return a int value similar to strcmp. An implementation that compares your struct date and returns -1, 0 or 1 based on the first being earlier, equivalent, or later could be:
int later (struct date *one, struct date *two)
{ /* the ternary operator is your friend */
if (one->year != two->year) /* years differ */
return one->year > two->year ? 1 : -1;
if (one->month != two->month) /* months differ */
return one->month > two->month ? 1 : -1;
if (one->day != two->day) /* days differ */
return one->day > two->day ? 1 : -1;
return 0; /* dates are equivalent */
}
(note: the use of the ternary operator (e.g. test ? if true : if false) to simply comparing each date component)
Also, note, in this case your are free to pass struct date instead of struct date * as the function will work fine operating on a copy of each date struct. It is up to you how you want to do it.
A small sample program testing the function (and noting a few code improvements) could be:
#include <stdio.h>
struct date {
int year;
int month;
int day;
};
int later (struct date *one, struct date *two);
void prn_result (struct date a, struct date b, char op);
/* main is a function of type 'int' and returns a value */
int main (void) {
struct date dates[2] = {{0}}; /* initialize variables */
int i = 0, res = 0;
for (i = 0; i < 2; i++) { /* user input of dates */
printf ("Enter a year: ");
scanf ("%d", &dates[i].year);
printf ("Enter a month :");
scanf ("%d", &dates[i].month);
printf ("Enter a day: ");
scanf ("%d", &dates[i].day);
putchar ('\n');
}
res = later (&dates[0], &dates[1]); /* comparison */
if (res == 0)
prn_result (dates[0], dates[1], '=');
else if (res > 0)
prn_result (dates[0], dates[1], '>');
else
prn_result (dates[0], dates[1], '<');
return 0;
}
int later (struct date *one, struct date *two)
{ /* the ternary operator is your friend */
if (one->year != two->year) /* years differ */
return one->year > two->year ? 1 : -1;
if (one->month != two->month) /* months differ */
return one->month > two->month ? 1 : -1;
if (one->day != two->day) /* days differ */
return one->day > two->day ? 1 : -1;
return 0; /* dates are equivalent */
}
void prn_result (struct date a, struct date b, char op)
{
printf ("%d/%d/%d %c %d/%d/%d\n",
a.month, a.day, a.year, op,
b.month, b.day, b.year);
}
Example Use/Output
$ ./bin/cmpyear
Enter a year: 1993
Enter a month :3
Enter a day: 13
Enter a year: 1993
Enter a month :3
Enter a day: 12
3/13/1993 > 3/12/1993
$ ./bin/cmpyear
Enter a year: 1993
Enter a month :3
Enter a day: 12
Enter a year: 1993
Enter a month :3
Enter a day: 12
3/12/1993 = 3/12/1993
$ ./bin/cmpyear
Enter a year: 1993
Enter a month :3
Enter a day: 12
Enter a year: 1993
Enter a month :3
Enter a day: 13
3/12/1993 < 3/13/1993
Look it over and let me know if you have an further questions.

Related

adding a int from a struct pointer

I'm trying to increase the day of a date struct in C. I keep getting a return where the memory seems to be adding [not the actual int day in the struct].
For example, if I INPUT:
2018 10 2
I should get
OUTPUT:
10/03/2018
INSTEAD, I GET:
32594/10/-352487872
I believe I'm not using pointers correctly in the method: advanceDay(struct date d)
#include <stdio.h>
struct date {
int year;
int month;
int day;
};
/* function prototypes */
void printDate(struct date);
void readDate(struct date *);
struct date advanceDay(struct date);
int main(void) {
struct date today, tomorrow;
readDate(&today);
printDate(today);
tomorrow = advanceDay(today);
printDate(tomorrow);
return 0;
}
/* add your function definitions here */
void printDate(struct date d) {
printf("%02d/%02d/%04d\n", d.month, d.day, d.year);
}
void readDate(struct date *d){
scanf("%d %d %d", &(d->year), &(d->month), &(d->day));
}
struct date advanceDay(struct date d) {
d.day = d.day+1;
}
I've tried to change
d.day = d.day+1;
to
d.day = (*d.day)+1;
But I get an error. I've tried the -> and also moving around the *
Note that advanceDay doesn't explicitly return anything, resulting in undefined behavior (and probably reading uninitialized memory - the compiler should have warned you about it).
Instead, you could pass a struct date* to the function, and update it in place:
void advanceDay(struct date * d) {
d->day = d->day + 1;
}
Note that your main also needs to change accordingly:
int main(void) {
struct date today;
readDate(&today);
printDate(today);
advanceDay(&today); /* no retrun value here */
printDate(today); /* today was updated in-place */
return 0;
}
You declare advanceDay to return a value, but you don't return anything. You invoke undefined behavior by failing to return a value from this function and then subsequently attempting to use the return value.
Create a copy of the passed in struct date, perform the operation on the copy, and return it.
struct date advanceDay(struct date d) {
struct date nextDay;
nextDay.day = nextDay.day+1;
return nextDay;
}

Using malloc to create a pointer to multiple struct items

For a c programming class, I have been told to create the following structs with typedefs, in that order:
//STRUCTS
struct time {
unsigned int hour;
unsigned int minute;
unsigned int second;
};//end struct time
struct date {
unsigned int month;
unsigned int day;
unsigned int year;
};//end struct Date
struct event {
char name[20];
struct time* time;
struct date* date;
};//end struct event
//TYPEDEFS
typedef struct time Time;
typedef struct date Date;
typedef struct event Event;
From there I'm supposed to ask for the max number of events to create, then allocate a pointer with enough memory for that many Events. Part of my work is:
Event *events;
//Ask for max number of events and allocate memory
printf("Number of events to add: ");
scanf("%d", &numEvents);
events = (Event*) malloc(sizeof(Event) * numEvents);
However, from there I'm unsure of what to do to traverse the pointer to view a specific event. I know it isn't just an array, so events[i] won't work. but beyond that, I'm lost. My (broken)function for getting an event is:
void getEvent(Event *events, int index){
//variables
char title[20];
unsigned int day, month, year, hour, minute, second;
Event tempEvent;
//Ask for input
printf("Input title, date, and time.\n");
if(index == 0)
printf("example -> title: dd/mm/yy hh:mm:ss\n");
//Take input
scanf("%20[^:]: %u/%u/%u %u:%u:%u", title, &day, &month, &year, &hour, &minute, &second);
tempEvent = (Event) {*title, { hour, minute, second }, { month, day, year } };
events[index] = tempEvent;
}
I know that it isn't right, and I got a segmentation fault on testing.
When I compile, I get these warnings (and some repeats about similar things):
Lab4.c: In function ‘getEvent’: Lab4.c:82:2: warning: braces around scalar initializer
tempEvent = (Event) {*title, { hour, minute, second }, { month, day, year } };
^ Lab4.c:82:2: note: (near initialization for ‘(anonymous).name[1]’)
Lab4.c:82:39: warning: excess elements in scalar initializer
tempEvent = (Event) {*title, { hour, minute, second }, { month, day, year } }
The compiler is telling you that line 82 is a mess.
tempEvent = (Event) {*title, { hour, minute, second }, { month, day, year } };
In particular, the first member of the event structure is an array char name[20], but you attempt to initialize it with a single character *title. But the bigger problem is that time and date (in the event structure) are pointers, and you haven't allocated any memory for those pointers.
One solution is to allocate memory, and then have scanf fill in the values, like this:
void getEvent( Event *events, int n )
{
// allocate memory
events[n].time = malloc(sizeof(Time));
events[n].date = malloc(sizeof(Date));
if ( events[n].time == NULL || events[n].date == NULL )
{ /* TODO: handle the error */ }
//Ask for input
printf("Input title, date, and time.\n");
if ( n == 0 )
printf("example -> title: dd/mm/yy hh:mm:ss\n");
//Take input
int count = scanf( "%20[^:]:%u/%u/%u%u:%u:%u", events[n].name,
&events[n].date->day, &events[n].date->month, &events[n].date->year,
&events[n].time->hour, &events[n].time->minute, &events[n].time->second );
if ( count != 7 )
{ /* TODO: handle the error */ }
}

Sscanf and fgets proper usage in C - NOTE: edited

I'm trying to make a big program for making a Gregorian calendar but at the moment, I'm just trying to work with a function that parses an inputted date. A few of the functions (sscanf and fgets) I'm not really sure how to use them with the rest of the program. Here is my attempt:
int main(int arg, char *argv[]) {
/*
* Request a date from the user
* in format DD-MM-YYYY, DD.MM.YYYY or DD/MM/YYYY
*/
date d;
char input_date[20];
fgets(input_date, 20, stdin);
printf("Enter your date of birth in the form DD/MM/YYYY:");
//fgets(d, 100, stdin);
sscanf(input_date,"%d", &d.day, &d.month, &d.year);
if (leapYearFeb(d.year, d.month)) {
d.day = d.day + 1;
}
if (parse_formatted_date(input_date, &d))
printf("date: %s\ndd = %d, mm = %d, yy = %d\n", input_date, d.day, d.month, d.year);
return 1;
return 0;
}
Here is the date.h header file where I'm calling parse_formatted_date from:
#ifndef DATE_H_
#define DATE_H_
// Define the structure date.
typedef struct {
int day;
int month;
int year;
} date;
// Parses a string 'formatted_date' representing a date
// in format DD-MM-YYYY, DD.MM.YYYY or DD/MM/YYYY
// into a structure date 'parsed_date'.
void parse_formatted_date(char * formatted_date, date * parsed_date) {
const int ret = sscanf(formatted_date, "%d-%d-%d",
&parsed_date->day,
&parsed_date->month,
&parsed_date->year);
//printf("Day: %d, Month: %d, Year: %d\n", d.day, d.month, d.year);
//return ret == 3;
}
#endif
At the moment, the errors I'm getting are:
main_Assignment4.c: In function ‘main’:
main_Assignment4.c:22: error: void value not ignored as it ought to be
Not sure what these errors mean or how to fix?
Thank you!
Modified answer
// Parses a string 'formatted_date' representing a date
// in format DD-MM-YYYY, DD.MM.YYYY or DD/MM/YYYY
// into a structure date 'parsed_date'.
void parse_formatted_date(char * formatted_date, date * parsed_date)
{
sprintf(formatted_date, "%d-%d-%d",
parsed_date->day,
parsed_date->month,
parsed_date->year);
}
int main(int arg, char *argv[]) {
/*
* Request a date from the user
* in format DD/MM/YYYY
*/
date d;
char input_date[20];
printf("Enter your date of birth in the form DD/MM/YYYY:");
fgets(input_date, 100, stdin);
sscanf(input_date,"%d/%d/%d", &d.day, &d.month, &d.year);
parse_formatted_date(input_date, &d);
printf("date: %s dd = %d, mm = %d, yy = %d\n", input_date, d.day, d.month, d.year);
return 0;
}

scanf doesn't store proper information in structure

I have a problem with scanf. scanf doesn't store proper information in structure. Part of code is:
if( figure->pro.p_category == 'C' || figure->pro.p_category == 'c' ){
printf("Enter data line> ");
result += scanf("%s %d%c %d %d %d%c", (figure->pro.name), &temp,\
&figure->pro.money, &figure->exp.month, &figure->exp.year,\
&figure->ais.aisle_num, &figure->ais.aisle_side);
if ( figure->pro.money == 'C')
figure->pro.cents = temp;
else if( figure->pro.money == 'D')
figure->pro.dollars = temp;
}
figure->pro.name and figure->exp.month store different values.
My structures are:
typedef struct {
char name[20];
char p_category,
sub_p_category,
money;
int cents,
dollars;
}product_t;
typedef struct {
int aisle_num;
char aisle_side;
}aisle_t;
typedef struct {
int day,
month,
year;
}experiment_t;
typedef struct {
int day,
month,
year;
}packaging_t;
typedef union {
product_t pro;
experiment_t exp;
packaging_t pack;
aisle_t ais;
}figure_t;
For instance;
input> corn 89C 11 2010 11B
This piece of code from output function:
printf("The %s costs %d cents, expires in ",my_figure.pro.name, my_figure.pro.cents);
print_exp_month(my_figure);
printf("of %d, and is displayed in %d%c", my_figure.exp.year, my_figure.ais.aisle_num,\
my_figure.ais.aisle_side);
its output:
The
costs 89 Dollar, expires in of 2000, and is displayed in 12B
The proper output:
The corn costs 89 cents, expires in November of 2000, and is displayed in 12B
If you store your data in a union
typedef union {
product_t pro;
experiment_t exp;
packaging_t pack;
aisle_t ais;
} figure_t;
only one set of data is stored at each time. When you read into, for example, figure->pro.money and figure->exp.month the data will be stored in the same place and overwrite each other.
So when you try to print it, it is not there anymore!

Date comparison to find which is bigger in C

I want to know how to find which is bigger date using a C program
kindly help me out plz....
You can use the difftime function:
#include <time.h>
#include <stdio.h>
int main(void) {
time_t date1, date2;
// initialize date1 and date2...
double seconds = difftime(date1, date2);
if (seconds > 0) {
printf("Date1 > Date2\n");
}
return 0;
}
If your dates are not of type time_t, you can use the function mktime to convert them.
#include <stdio.h>
struct date
{
int month;
int date;
int year;
};
int main(void)
{
int i=compare_dates (struct date d1, struct date d2);
switch(i)
{
case -1:
printf("%d/%d/%d is earlear date than %d/%d %d", D1.day, D1.month, D1.year, D2.day
case 1:
printf("%d/%d/%d is later date than %d/%d/%d",D1.day,D1.month,D1.year,D2.day…
case 0:
printf("%d/%d/%d is the same date than %d/%d/%d", D1.day, D1.month, D1.year, D2.day
}
return 0;
}
int compare_dates (struct date d1, struct date d2)
{
if (d1.year < d2.year)
return -1;
else if (d1.year > d2.year)
return 1;
if (d1.year == d2.year)
{
if (d1.month<d2.month)
return -1;
else if (d1.month>d2.month)
return 1;
else if (d1.day<d2.day)
return -1;
else if(d1.day>d2.day)
return 1;
else
return 0;
}
}
If you just want to know which is bigger, you don't need go through all this. You can just prioritize the values and compare them. Just add coefficients to month and year that is bigger than highest day possible. For example, say that a month is 100 times more important than the day and a year is 2000 times more important than a day. Just calculate the score of the dates and compare them.
#include <stdio.h>
int main()
{
int day1, day2, month1, month2, year1, year2;
printf("Enter first date (dd/mm/yyyy) => "); scanf("%d/%d/%d", &day1, &month1, &year1);
int prioritedScore1 = day1 + month1*100 + year1*2000;
printf("Enter second date (dd/mm/yyyy) => "); scanf("%d/%d/%d", &day2, &month2, &year2);
int prioritedScore2 = day2 + month2*100 + year2*2000;
if(prioritedScore1 > prioritedScore2){
printf("Bigger date is => %d/%d/%d", day1, month1, year1);
} else if(prioritedScore2 > prioritedScore1){
printf("Bigger date is => %d/%d/%d", day2, month2, year2);
} else{
printf("Dates are same.");
}
return 0;
}
You can always use a long integer in order to get rid of possible bugs when user enters so high numbers like 2147484 as year.
Can you give more information about what you want to achieve ? Because comparing date is really easy. After all, they are just number of seconds (or milli, micro, nano, ...) since a given past date, or a structure containing year, month, day, ... Whatever the format, the comparison should be pretty easy to perform.
Maybe you want to compare two date given by the user as strings (something like "2011-03-12 18:38") ? Then, you can use strptime to convert the string to a struct tm, and then do the comparison.
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int parse_date(char* date, struct tm* tm)
{
char* format;
char* formats[] = {
"%F %I", /* "2011-03-12 06:38:05 AM" */
"%F %T", /* "2011-03-12 18:38:05" */
"%F %R", /* "2011-03-12 18:38" */
NULL,
};
for (format = formats[0]; format; ++ format) {
if (strptime(date, format, &tm)) {
return 1;
}
}
return 0;
}
int main(int argc, char** argv)
{
float diff;
char* date1;
char* date2;
struct tm tm1;
struct tm tm2;
time_t time1;
time_t time2;
if (argc != 3) {
fprintf(stderr, "usage: compare-date date1 date2\n");
exit(1);
}
date1 = argv[1];
date2 = argv[2];
if (!parse_date(date1, &tm1)) {
fprintf(stderr, "unsupported date: %s\n", date1);
exit(1);
}
if (!parse_date(date2, &tm1)) {
fprintf(stderr, "unsupported date: %s\n", date2);
exit(1);
}
time1 = mktime(&tm1);
time2 = mktime(&tm2);
diff = difftime(time1, time2);
printf("%s %c %s\n",
date1,
(diff < 0 ? '<' : (diff > 0 ? '>' : '==')),
date2);
return 0;
}
You didn't say in which format you have the date, so I will name two common examples:
If you are using GNU lib-c (or MinGW) and query the time with:
time_t time (time_t *result)
Then time_t is just a long int, numbers of seconds since epoch and you can subtract one date from the other to find out the number of seconds difference.
If you are using the Windows API and have a filetime-structure:
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME;
you can cast the pointer to a pointer to ULARGE_INTEGER, and subtract that one giving you the number of 100-nanosecond intervals difference.

Resources