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

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

Related

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.

C MongoDB driver DateTime update

Ok this is the scenario. I am reading txt file and inserting/updating (with bulk operations ) data to mongodb.
Inserting part works fine since I am creating bson document in a loop and doing mongoc_bulk_operation_insert.
My date comes in a format of 11:37:17.253 SAST JUN 05 2015
so I run it trough the function that removes .253 and SAST
and feed it to the convert_to_date function that you see down in the text.
This is how I create timestamp and append the date to the document:
int convert_to_date(char *dateString)
{
struct tm *parsedTime;
time_t rawTime;
time_t newTime;
int hour, minutes, seconds, millis, year, month, day;
if (sscanf(dateString, "%d:%d:%d %d %d %d",
&hour, &minutes, &seconds, &month, &day, &year) != EOF) {
time(&rawTime);
parsedTime = localtime(&rawTime);
parsedTime->tm_year = year - 1900;
parsedTime->tm_mon = month - 1;
parsedTime->tm_mday = day;
parsedTime->tm_hour = hour;
parsedTime->tm_min = minutes;
parsedTime->tm_sec = seconds;
newTime = mktime(parsedTime);
return newTime;
}
return 0;
}
/* this is somewhere in a loop */
time_t t = convert_to_date(s1);
bson_append_time_t(doc, field_map[y], strlen(field_map[y]), t);
// and after all if insert is supposed to happen i call
// mongoc_bulk_operation_insert(bulk, doc);
// and mongoc_bulk_operation_execute(bulk, &reply, &error);
That part is just fine when I look at the database I get
ISODate("2015-06-05T09:37:17.000Z")
So ther problem is when I try to update existing record.
When i do update i need to do a $set on all of the fields I want to update(upsert actually and I didnt find a way to update complete document at once)
it looks like this:
//update document with sessionid
query = BCON_NEW("SessionId", BCON_UTF8(sid));
update = BCON_NEW("$set", "{", "SomeDateTimeField",
BCON_DATE_TIME(ystack[y]), "}");
mongoc_bulk_operation_update(bulk, query, update, true);
The value of ystack[y] is 1433497048 which is valid timestamp but
i get in the db ISODate("1970-01-17T14:11:37.037Z")
I also found an example online for inserting the whole bson object as date like this:
int64_t currentTime = time(NULL) * 1000;
bson_t *date = BCON_NEW("$date", BCON_DATE_TIME(currentTime));
bson_t *update = BCON_NEW("$set", "{", "last_sync_time", date, "}");
But this produces \u0001 in the DB instead of valid date. I cant tell what is causing this, so much frustration for something that should be straight forward. This is the libbson api for the reference
https://api.mongodb.org/libbson/current/index.html
and c driver api
http://api.mongodb.org/c/1.1.8/
Ok I found the solution myself, should have read the api more carefully :)
The BCON_DATE_TIME accepts milliseconds instead of seconds which I passed to it.
I actually tried to multiply by 1000 before but since my var was int it could not store the correct value.
I had to declare it as
unsigned long long
Here is the changed code just for reference
long convert_to_long(char *dateString)
{
struct tm *parsedTime;
time_t rawTime;
time_t newTime;
int hour, minutes, seconds, millis, year, month, day;
if (sscanf(dateString, "%d:%d:%d %d %d %d",
&hour, &minutes, &seconds, &month, &day, &year) != EOF) {
time(&rawTime);
parsedTime = localtime(&rawTime);
parsedTime->tm_year = year - 1900;
parsedTime->tm_mon = month - 1;
parsedTime->tm_mday = day;
parsedTime->tm_hour = hour;
parsedTime->tm_min = minutes;
parsedTime->tm_sec = seconds;
newTime = mktime(parsedTime);
unsigned long long millis = newTime * 1000;
return millis;
}
return 0;
}

Time convert from a file and compare to the current time

I've asked something close to this before, but as it seems, the time I get from the file does not convert to the same type of time you get from localtime() and time().
Exactly what I want is:
I have a txt file with the following information
order.txt
file1.txt;5;15:40
file2.txt;7;15:41
file1.txt;10;16:00
My objective is to get the time in hour:min (15:40) and then, if it's the same as the currentTime, then I show the file1.txt content. Otherwise, if the currentTime is lower than the hour:min time (15:40), it waits untill it's 15:40 and shows the file1.txt content. If the currentTime is higher, then it ignores the first one and goes to the next one.
So for example, if the current time is 15:39, it will wait 1 minute and then show the file1.txt content.
If the current Time is 15:40, it shows the file1.txt content without waiting.
If the current Time is 15:41, it just goes to the next one (file2.txt) and checks again.
Used variables
FILE* orderFile;
FILE* contentFile;
FILE* defaultFile; (This will be used when this code works)
char fileName[50];
char textContent[5000];
int seconds;
int hour, min;
int diff_time;
char timeValue[50];
time_t current;
Includes
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
So for that I've tried the following code:
orderFile = fopen("order.txt","r");
defaultFile = fopen("default.txt","r");
while(fscanf(orderFile," %49[^;];%d; %49[^\n]",fileName,&seconds,timeValue)
{
sscanf(timeValue,"%d:%d",&hour,&min);
contentFile = fopen(fileName,"r");
if(contentFile != NULL)
{
fseek (contentFile, 0, SEEK_END);
size = ftell(contentFile);
rewind(contentFile);
if(size == 0)
{
printf("\nEmpty file. (Scanned file: %s)\n", fileName);
fclose(contentFile);
}
else
{
time_t now;
time(&now);
struct tm file_time_tm;
file_time_tm = *localtime(&now);
file_time_tm.tm_hour = hour;
file_time_tm.tm_min = min;
file_time_tm.tm_sec = 0;
file_time_tm.tm_isdst = -1;
time_t fileTime = mktime(&file_time_tm);
double diff_time = difftime(fileTime, now);
if(diff_time == 0)
{
while(fscanf(contentFile,"%[^\t]",textContent) == 1)
{
printf("%s\n", textContent);
}
sleep(seconds);
}
else
{
if(diff_time > 0)
{
while(fscanf(defaultFile,"%[^\t]",defaultContent) == 1)
{
printf("%s\n", defaultContent);
}
sleep(diff_time);
while(fscanf(contentFile,"%[^\t]",textContent) == 1)
{
printf("%s\n", textContent);
}
sleep(seconds);
}
}
fclose(defaultFile);
fclose(contentFile);
}
}
else
{
if(contentFile == NULL)
{
printf("\nFile does not exist. (Scanned file: %s)\n", fileName);
fclose(contentFile);
}
}
}
fclose(orderFile);
printf("\n");
So thanks to chux it is quite working now, yet not fully working.
If I have the following:
Current Time: 15:00
order.txt
file1.txt;5;15:01
file2.txt;6;15:02
file3.txt;3;15:03
When I run the program, the following will occur:
DEFAULT MESSAGE (text inside default.txt)
WAITS DIFF_TIME (CORRECTLY DONE)
SHOWS CONTENT FROM THE file1.txt
WAITS 5 SECONDS
X - SHOWS CONTENT FROM THE file2.txt (This is wrong, it should check again and if the time is 15:02 it will show, not 15:01. Which I assume it's because it is still reading as 15:01 on the timeValue and not 15:02, any idea why?)
WAITS UNTILL IT'S 15:02 (wrong)
SHOWS file3.txt (wrong)
WAITS UNTILL IT'S 15:03
ENDS (wrong as it should not end after waiting, it should end when file3.txt shows and waits for 3 seconds)
Output I need:
DEFAULT MESSAGE
waits diff_time
file1.txt content
waits 5 seconds
DEFAULT MESSAGE
waits diff_time
file2.txt content
waits 7 seconds
DEFAULT MESSAGE
waits diff_time
file3.txt content
waits 3 seconds
ENDS
It also does not work well if I have two files with the same time, such as this:
order.txt
file1.txt;5;15:01
file2.txt;6;15:01
file3.txt;3;15:02
It breaks it aswell.
Any idea of how to do this correctly?
As commented above by #M Oehm, it is apparent the compiler warnings are not fully enabled. Suggest enabling them - it will save you time.
A problem lies in the time compare and subtraction.
// Troublesome code
if(currentTime->tm_hour < hour && currentTime->tm_min < min) {
diff_time = difftime(currentTime,timeValue);
printf("%d - Or this?\n", diff_time);
sleep(diff_time);
}
The comparison is curious. Usually with such a comparison would be in the form
if (h1 < h2 || (h1 == h2 && m1 < m2))
difftime takes 2 time_t paramters, not char timeValue[50] and a struct tm.
The values passed to double difftime(time_t time1, time_t time0) appear backwards. The result it time1 - time0.
Recommend instead
int current_hm = currentTime->tm_hour * 60 + currentTime->tm_min;
int file_hm = hour * 60 + min;
if (current_hm < file_hm) {
unsigned diff_time = (file_hm - current_hm)*60u;
printf("%u - Or this?\n", diff_time);
sleep(diff_time);
}
[Edit]
Simplified approach.
time_t now;
time(&now);
struct tm file_time_tm;
file_time_tm = *localtime(&now);
file_time_tm.tm_hour = hour; // from file
file_time_tm.tm_min = min; // from file
file_time_tm.tm_sec = 0;
file_time_tm.tm_isdst = -1;
time_t filetime = mktime(&file_time_tm);
double diff = difftime(filetime, now); // filetime - now
if (diff > 0) {
sleep((unsigned) diff);
}
Chux's suggestion to do your comparisons with your own integer that represents the minutes after midnight is probably easier in your case, but if you want to use the standard time mechanisms, you can do it.
But first, keep in mind that there are two time representations, time_t, which is a "numerical" time that stores the seconds after the epoch and struct tm, which is the human-readable time that breaks a time down to years, months, days and so on.
With strptime, you can scan a string accoding to a format specification. It is the scanf for struct tm. This function does not initialise fields that are not specified, so that you can assign the current time with localtime and then overwrite only the hour and minute fields.
mktime converts a struct tm to a time_t, which you can pass to difftime.
The following code snipped shows how such a comparison might work:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main()
{
char stamp[] = "12:53";
char *p;
struct tm now;
time_t t = time(NULL);
now = *localtime(&t);
p = strptime(stamp, "%H:%M", &now);
if (p == NULL || *p != '\0') {
printf("Illegal date.\n");
} else {
char buf[20];
double dsec;
int dmin;
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M\n", &now);
puts(buf);
dsec = difftime(t, mktime(&now));
printf("Diff: %g sec\n", dsec);
dmin = (int) dsec / 60;
printf("Diff: %d min\n", dmin);
}
return 0;
}

Having problems replacing data in array

For a project I have to do, I have to list a set of classes, have the user select which class to use, and print out a weekly schedule for them for the semester. (Same program as the first question I asked.) However, I seem to run into a problem when I try to print out a weekly schedule. (The program is pretty lengthy, at least with the experience I have in C.)
struct course
{
int index;
char name[7];
char day[4];
int hours,houre,mins,mine;
char ap[3];
int credit;
};
struct course whcl[]={ {0,"MATH1","MWF",7,8,30,50,"AM",5},
{1,"MATH2","MWF",9,10,00,20,"AM",5},
{2,"CHEM1","MW ",2,6,30,50,"PM",5},
{3,"PHYS4","TTH",4,6,00,45,"PM",4},
{4,"ENGR1","M ",9,10,30,20,"AM",1},
{5,"ENGR2","TTH",10,12,00,15,"PM",3},
{6,"ENGR3","MW ",11,12,00,15,"PM",3}};
int choice[15],i,j,k,num,z,s;
void printout(int z); //(To be put in when I fix the function)
int main(void)
{
char l[8][3]={{"st"},{"nd"},{"rd"},{"th"},{"th"},{"th"},{"th"},{"th"}};
printf(" Fall Schedule\n");
printf("Index Course Day Time Credit\n");
printf("-------------------------------------------\n");
for(i=0;i<7;i++)
{
printf(" %i %s %s %i%i:%i%i-%i%i:%i%i%s %i\n",
whcl[i].index,whcl[i].name,whcl[i].day,
whcl[i].hours/10,whcl[i].hours%10,
whcl[i].mins/10,whcl[i].mins%10,
whcl[i].houre/10,whcl[i].houre%10,
whcl[i].mine/10,whcl[i].mine%10,
whcl[i].ap,whcl[i].credit);
}
printf("How many classes would you like to take?: ");
scanf("%i",&num);
for(i=0;i<num;i++)
{
printf("Select the %i%s class using the index: ",i+1,l[i]);
scanf("%i",&choice[i]);
}
printf("The classes you have selected are:\n");
printf("Index Course Day Time Credit\n");
printf("-------------------------------------------\n");
for(i=0;i<num;i++)
{
s=choice[i];
printf(" %i %s %s %i%i:%i%i-%i%i:%i%i%s %i\n",
whcl[s].index,whcl[s].name,whcl[s].day,
whcl[s].hours/10,whcl[s].hours%10,
whcl[s].mins/10,whcl[s].mins%10,
whcl[s].houre/10,whcl[s].houre%10,
whcl[s].mine/10,whcl[s].mine%10,
whcl[s].ap,whcl[s].credit);
}
printf("Your weekly schedule for Fall is:\n");
printf(" Time Monday Tuesday Wednesday Thursday Friday\n");
printout(z);
return 0;
}
void printout(int z)
{
int start,starti,end,endi,num;
int slot[25][6];
for(i=0;i<24;i++)
for(j=0;j<5;j++)
slot[i][j]=99;
for(i=0;i<num;i++)
{
if ((whcl[choice[i]].day)=="MWF")//I think the problem is here.
{
start=whcl[choice[i]].hours*60+whcl[choice[i]].mins;
end=whcl[choice[i]].houre*60+whcl[choice[i]].mine;
starti=(start-450)/30;
endi=(end-450)/30;
for(j=starti;j<=endi;j++)
slot[j][1]=slot[j][3]=slot[j][6]=whcl[choice[i]].index;
}
}
for(i=0;i<24;i++)
{
printf("%i%i:%i%i-%i%i:%i%i ",
(450+(i-1)*30)/60/10,(450+(i-1)*30)/60%10,
(450+(i-1)*30)%60/10,(450+(i-1)*30)%60%10,
(450+(i-1)*30+30)/60/10,(450+(i-1)*30+30)/60%10,
(450+(i-1)*30+30)%60/10,(450+(i-1)*30+30)%60%10);
for(j=0;j<4;j++)
{
if (slot[i][j]!=99) //Use Note here
printf(" %s ",whcl[choice[i]].name);
else
printf("");
}
printf("\n");
}
return;
}
When I print out the schedule, the only thing that comes up is the time. Everything else is blank. I think it's due to my trying to replace the slot array with something other than 99. If you plan on running this program, please use 2 the amount of classes you want to take, and use 0 and 1 for the index on the class choice. (I don't have any if statements and whatnot to take into account the other classes the user might have chosen.) Here's a photo of what I'm trying to do for my program. http://postimg.org/image/3tlgtwu9h/ I used paint to put in the boxes on the schedule to visually see the different arrays as I was coding.
Note: If you change the if statement to [i][j]==99 You can see the "Class" being printed on the table, however it fills up the entire array slot, which confirms my thought that I messed up on trying to replace data in the array. Also, I filled it up with 99 to make 99 associated with blank spaces.
if ((whcl[choice[i]].day)=="MWF") //I think the problem is here.
Correct, you need to use strcmp to compare strings, not ==
Try:
if (strcmp(whcl[choice[i]].day,"MWF") == 0)
Equality as == will check if pointers are the same so you could have:
char * a = "MTW"; char *b = a and then a == b would be true

Resources