Sscanf and fgets proper usage in C - NOTE: edited - c

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;
}

Related

How do I manipulate the values to a pointer to a struct

It's a function that makes events based off the time values the user enters, it then converts the value to Unix Epoch using mktime and stores them to a file. I've tested and found that everything else works well until we reach the section where the user enters the values seems like I'm not using the pointer event to the struct tm well, so I need help in doing it right.
int EventCreator(){
FILE *fptr = fopen("Events_Calendar.txt", "a+");
struct tm *event;
printf("Enter the values of the hour minute day month year in digits and this specific format meaning using spaces to seperate them");
printf("\n hr min day mon yr\n>");
scanf("%d %d %d %d %d", event->tm_hour, event->tm_min, event->tm_mday, event->tm_mon, event->tm_year);
time_t NineteenEvent = mktime(event);
printf("%ld", NineteenEvent);
fprintf(fptr, "%ld\n", NineteenEvent);
fclose(fptr);
}
You have declared a pointer to a struct tm but you haven't allocated memory for a struct tm. I suggest that you make event an automatic variable instead.
Example:
void EventCreator() { // make the function `void` since you do not return anything
FILE *fptr = fopen("Events_Calendar.txt", "a+");
if (fptr) { // check that opening the file succeeds
// `event` is now not a pointer and set `tm_isdst` to a negative value
// to make `mktime` guess if DST is in effect:
struct tm event = {.tm_isdst = -1};
printf(
"Enter the values of the hour minute day month year in digits and "
"this specific format meaning using spaces to seperate them\n"
"hr min day mon yr\n>");
// %d requires an `int*` but you've supplied it with `int`.
// (also, check that scanf succeeds)
if (scanf("%d %d %d %d %d", &event.tm_hour, &event.tm_min,
&event.tm_mday, &event.tm_mon, &event.tm_year) == 5) {
event.tm_year -= 1900; // years since 1900
--event.tm_mon; // 0-11
time_t NineteenEvent = mktime(&event); // take its address here
printf("%ld", NineteenEvent);
fprintf(fptr, "%ld\n", NineteenEvent);
fclose(fptr);
}
}
}

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;
}

How to get current day of month properly in Tizen c program

the following program works with c compiler and returns correct date. But on tizen app code it returns 0:
time_t my_time;
struct tm * timeinfo;
time (&my_time);
timeinfo = localtime (&my_time);
int y = timeinfo->tm_year+1900;
int m = timeinfo->tm_mon+1;
int d = timeinfo->tm_mday;
char day[10];
dlog_print(DLOG_DEBUG, "GG", "Current time: %d %d %d", y,m,d);
required screenshot:
it shows 0 only for date(d) but other m and y is printed correctly. Also similar code prints correct date on other c complier program.
How to get current day of the month properly?
You can use Watch Application API on the wearable profile.
You can also find sample code in Tizen Studio sample application(Classic Watch) like as below.
/**
* #brief Called at each second. This callback is not called while the app is paused or the device is in ambient mode.
* #param[in] watch_time The watch time handle. watch_time will not be available after returning this callback. It will be freed by the framework.
* #param[in] user_data The user data to be passed to the callback functions
*/
void app_time_tick(watch_time_h watch_time, void* user_data)
{
int hour = 0;
int min = 0;
int sec = 0;
int year = 0;
int month = 0;
int day = 0;
int day_of_week = 0;
watch_time_get_hour(watch_time, &hour);
watch_time_get_minute(watch_time, &min);
watch_time_get_second(watch_time, &sec);
watch_time_get_day(watch_time, &day);
watch_time_get_month(watch_time, &month);
watch_time_get_year(watch_time, &year);
watch_time_get_day_of_week(watch_time, &day_of_week);
_set_time(hour, min, sec);
_set_date(day, month, day_of_week);
_set_moonphase(day, month, year);
}

Return pointer to a structure

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.

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