I'm writing a function whose purpose is to change the value of struct variables. I'm getting error messages that say the expressions toward the end of my first function are not assignable. How, then, do I have the function change the values of the daate structure?
Here's my code:
#include <stdio.h>
#include <stdbool.h>
struct date
{
int month;
int day;
int year;
};
struct date dateUpdate (struct date *dait) {
struct date tomorrow;
int numberOfDays (struct date d);
if (dait->day != numberOfDays (*dait) ) {
tomorrow.day = dait->day + 1;
tomorrow.month = dait->month;
tomorrow.year = dait->year;
}
else if ( dait->month == 12 ) { //end of year
tomorrow.day = 1;
tomorrow.month = 1;
tomorrow.year = dait->year + 1;
}
else { //end of month
tomorrow.day = 1;
tomorrow.month = dait->month + 1;
tomorrow.year = dait->year;
}
&dait->day = tomorrow.day;
&dait->month = tomorrow.month;
&dait->year = tomorrow.year;
return *dait;
}
//Function to find the number of days in a month;
int numberOfDays (struct date d)
{
int days;
bool isLeapYear (struct date d);
const int daysPerMonth[12] =
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if ( isLeapYear (d) && d.month == 2 )
days = 29;
else
days = daysPerMonth[d.month - 1];
return days;
}
}
int main (void) {
struct date daate;
daate.day = 21;
daate.month = 6;
daate.year = 2013;
dateUpdate(&daate);
printf("%d", daate.day);
}
The correct syntax (which you already used in the function) is the following
dait->day = tomorrow.day;
dait->month = tomorrow.month;
dait->year = tomorrow.year;
Take into account that instead of these three statements you could write simply
*dait = tomorrow;
dait is already a pointer, so &dait is a pointer to a pointer, and thus it has no fields to de-reference.
Solution: lose the & before dait.
Related
I have a problem regarding index out of bound error in arrays.
I want to create a method that takes month and day as parameter and returns day of the year.If any of the parameters are incorrect, the method should return 0.
for example if the method receives 2 and 3, meaning the third of February it must return 34. If it receives 12 and 31, it must return 365.
but I am getting this problem of index out of bound and can't solv it any tips.
this is my code.
public class CalendarMethods {
public static int dayInYear(int month, int day){
int[] daysInMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int yearCalculation = 0;
int monthCalculation = 0;
for (int j = 0; j < month-1; j++) {
monthCalculation = monthCalculation + daysInMonth[j];
}
yearCalculation = monthCalculation + day;
if (month <= 0 ) {
yearCalculation = 0;
}
if (month >= 13){
yearCalculation = 0;
}
return yearCalculation;
}
}
You should do the boundary checks on month before the loop. A fix for that would be:
public class CalendarMethods {
public static int dayInYear(int month, int day){
int[] daysInMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int yearCalculation = 0;
int monthCalculation = 0;
if (month > 0 && month < 13) {
if (day > 0 && day <= daysInMonth[month - 1]) { // extra: check if entered day makes sense
for (int j = 0; j < month-1; j++) {
monthCalculation = monthCalculation + daysInMonth[j];
}
yearCalculation = monthCalculation + day;
}
}
return yearCalculation;
}
}
For functions, always do sanity checks first to ensure the inputs you are getting align with your expections, in this this case we expect months to be values between 1 and 12 so same implementation as you had but check inputs before processing the rest of the code. This saves you from exceptions from unexpected/bad inputs.
public static int dayInYear(int month, int day){
if (month <= 0||month >= 13 ) {
return 0;
}
int[] daysInMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int yearCalculation = 0;
int monthCalculation = 0;
for (int j = 0; j < month-1; j++) {
monthCalculation = monthCalculation + daysInMonth[j];
}
yearCalculation = monthCalculation + day;
return yearCalculation;
}
So I wrote a program where I have to realloc an array of structs whenever I want to add something to it.
But when I try to free the array, I free every element individually but I get a munmap_chunk(): invalid pointer at some point.
Here is the full code :
#include <stdlib.h>
#include <string.h>
struct Date {
int day;
int month;
int year;
};
struct Person {
char *name;
char *surname;
struct Date birth;
};
struct Directory {
int size;
struct Person *array;
};
struct Date create_date() {
struct Date date = {
.day = 0,
.month = 0,
.year = 0
};
return date;
}
struct Directory create_directory() {
struct Directory directory = {
.size = 0,
.array = NULL
};
return directory;
}
struct Person *create_person() {
struct Person *person_ptr = (struct Person *) malloc(sizeof(struct Person));
person_ptr->name = NULL;
person_ptr->surname = NULL;
return person_ptr;
}
void copy_date(struct Date *dest, struct Date *src) {
dest->day = src->day;
dest->month = src->month;
dest->year = src->year;
}
void initialize_person(struct Person *person_ptr, char *name, char *surname, struct Date *birth) {
if (name != NULL && surname != NULL && birth != NULL) {
person_ptr->name = realloc((*person_ptr).name, (strlen(name) * sizeof(char)) + 1);
strcpy(person_ptr->name, name);
person_ptr->surname = realloc((*person_ptr).surname, (strlen(surname) * sizeof(char)) + 1);
strcpy(person_ptr->surname, surname);
copy_date(&person_ptr->birth, birth);
}
}
void copy_person(struct Person *dest, struct Person *src) {
dest->name = realloc((*dest).name, (strlen(src->name) * sizeof(char)) + 1);
dest->surname = realloc((*dest).surname, (strlen(src->surname) * sizeof(char)) + 1);
struct Date date = create_date();
dest->birth = date;
strcpy(dest->name, src->name);
strcpy(dest->surname, src->surname);
copy_date(&dest->birth, &src->birth);
}
int add_person(struct Directory *directory_ptr, const struct Person *new_person_ptr) {
int return_code = 0;
directory_ptr->size++;
directory_ptr->array = realloc(directory_ptr->array, (directory_ptr->size * sizeof(struct Person)));
if (directory_ptr->array) {
copy_person(&directory_ptr->array[directory_ptr->size - 1], (struct Person *) new_person_ptr);
} else {
return_code = 1;
}
return return_code;
}
int add_multiple_persons(struct Directory *directory_ptr, const struct Person **persons_ptr, int nb_persons) {
for (int i = 0; i < nb_persons; i++) {
add_person(directory_ptr, (persons_ptr[i]));
}
return 0;
}
void destroy_person(struct Person *person_ptr) {
free(person_ptr->name);
person_ptr->name = NULL;
free(person_ptr->surname);
person_ptr->surname = NULL;
free(person_ptr);
person_ptr = NULL;
}
void destroy_directory(struct Directory *directory_ptr) {
if (directory_ptr->array) {
for (int i = 0; i < directory_ptr->size; i++) {
destroy_person(&directory_ptr->array[i]);
}
directory_ptr->array = NULL;
directory_ptr->size = 0;
}
}
int main(void) {
struct Directory directory = create_directory();
struct Person *person1 = create_person();
struct Person *person2 = create_person();
struct Person *person3 = create_person();
struct Date date = {
.day = 17,
.month = 04,
.year = 1999};
initialize_person(person1, "Marcel", "Juan", &date);
initialize_person(person2, "Albin", "Michel", &date);
initialize_person(person3, "Suzerain", "Bernard", &date);
const struct Person *array[] = {
person1,
person2,
person3
};
add_multiple_persons(&directory, array, 3);
destroy_person(person1);
destroy_person(person2);
destroy_person(person3);
destroy_directory(&directory);
return 0;
}
I've been on this error for more than a week, and it keeps bugging me.
How can I fix this ?
In the destroy_directory function, you freed the persons contained by the array. But in this array you didn't put pointers to structures but the structures themselves. Therefore you must free the space you allocated for the array and nothing else :
void destroy_directory(struct Directory *directory_ptr) {
if (directory_ptr->array) {
free(directory_ptr->array); //<==== Here
directory_ptr->array = NULL;
directory_ptr->size = 0;
}
}
person_ptr is a part of the memory allocated at directory_ptr->array. You need to remove this line.
As a rule of gold, memory responsible is the same while allocation and while freeing. In your code, the person holder is the array inside directory_ptr, which is allocated by add_person. Despite its name, it is a directory manager, so freeing its memory should be done only on directory destroyer.
I'm doing a school project where I need to ask for a year and a month to be printed like a calendar. The problem is that when I debug it shows the whole year and not just the chosen month.
What changes do I have to do? Hope you can help me!
This is my code:
int SetFirstDay(int year)
{
int d;
int d1, d2, d3;
d1 = (year - 1.) / 4.0;
d2 = (year - 1.) / 100.;
d3 = (year - 1.) / 400.;
d = (year + d1 - d2 + d3) % 7;
return d;
}
int main()
{
int day, month, year, ndays, DayWeek = 0, FirstDay;
do
{
printf("\nEnter the desired year [2000 - 2099]\n");
scanf_s(" %d", &year);
} while (year < 2000 || year > 2100);
do
{
printf("\nEnter the desired month [1 - 12]\n");
scanf_s(" %d", &month);
} while (month < 1 || month > 12);
char *months[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
int DayMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
DayMonth[1] = 29;
FirstDay = SetFirstDay(year);
for (month = 0; month < 12; month++)
{
ndays = DayMonth[month];
printf("\n\n--------------%s-----------------\n", months[month]);
printf("\n Sun Mon Tue Wed Thu Fri Sat\n");
for (DayWeek = 0; DayWeek < FirstDay; DayWeek++)
{
printf(" ");
}
for (day = 1; day <= ndays; day++)
{
printf("%5d", day);
if (++DayWeek > 6)
{
printf("\n");
DayWeek = 0;
}
FirstDay = DayWeek;
}
}
printf("\n\n\n");
system("pause");
return 0;
}
Save the month value which comes from user input to an additional variable:
int monthTmp = month;
Then prefix all printf invokations with the following statement withing the "month" for loop:
for (month = 0; month < 12; month++)
{
// ...
if (monthTmp==month) printf(.........
It is not an optimized solution, but it is very straightforward.
I just started learning C and I'm still new to it.
In this program I'm working with an array of structs. The structs are:
typedef struct {
int day;
int month;
int year;
} Date;
typedef struct {
int serial_num;
char full_name[15];
Date *pDate;
} Person;
The array is Person *people.
Now I have two arrays of people and birth dates of those people (same indexes):
const char* names[MAX] = { "Sasson_Sassoni", "Pooh", "James_Bond", "Elvis_is_Alive", "Shilgiya", "Cleopatra", "Sissoo_VeSimmhoo" };
const int dates[MAX][COLS] = {
{ 10, 1, 1988 },
{ 12, 12, 1948 },
{ 4, 12, 1970 },
{ 11, 11, 1890 },
{ 11, 11, 1948 },
{ 1, 10, 1213 },
{ 12, 11, 1948 }
};
By using switch case, every time the user types 1 a person from the lists (Name and birthday) is added to the list people. Then if the user types 3, the list people should be sorted by date (oldest to youngest). So I wrote the following two functions:
void sortList(Person **people, int index) {
qsort(*people, index, sizeof(Person), intcmp);
}
int intcmp(const void *a, const void *b) {
Person *one = (Person *)a;
Person *two = (Person *)b;
int year1 = one->pDate->year;
int year2 = two->pDate->year;
int month1 = one->pDate->month;
int month2 = two->pDate->month;
int day1 = one->pDate->day;
int day2 = two->pDate->day;
if (year1 > year2)
return -1;
else if (year2 > year1)
return 1;
if (month1 > month2)
return -1;
else if (month2 > month1)
return 1;
if (day1 > day2)
return -1;
else if (day2 > day1)
return 1;
return 0;
}
But every time I get an error saying:
Exception thrown: read access violation.
one->pDate was nullptr.
Any help?
Thanks!
EDIT:
Further explanation: In order to insert the people to the array one by one, I made a variable called index and every time a person is added the index grows by one. So When calling the function qsort(), index is the number of people in the array. Also MAX=7, COLS=3, LEN=10. The function that adds people to the array is:
void addToList(Person **people, int *index, const char *names[MAX], const int dates[][COLS]) {
people[*index] = (Person *)malloc(sizeof(Person));
people[*index]->serial_num = *index + 1;
strcpy(people[*index]->full_name, names[*index]);
Date *temp = (Date *)malloc(sizeof(Date));
temp->day = dates[*index][0];
temp->month = dates[*index][1];
temp->year = dates[*index][2];
people[*index]->pDate = temp;
printf("%d %s %d/%d/%d \n", people[*index]->serial_num, people[*index]->full_name, people[*index]->pDate->day, people[*index]->pDate->month, people[*index]->pDate->year);
*index = *index + 1;
}
Your mcve is not complete but I think it's because you confuse pointer and struct:
void sortList(Person **people, int index) {
qsort(people, index, sizeof(Person *), intcmp);
// or qsort(people, index, sizeof *people, intcmp);
}
int intcmp(const void *a, const void *b) {
const Person *one = *(const Person **)a;
const Person *two = *(const Person **)b;
If using an enum for which you cannot alter the contents, e.g.,
typedef enum {
sun=0,
mon=1,
tue=2,
wed=3,
thu=4,
fri=5,
sat=6,
} days;
Is there any way to safely have some code that looks like:
days day;
day = /*what goes here*/;
if (somecondition)
{
day = sun;
}
else if (othercondition)
{
day = mon;
}
if (day != /*what goes here*/)
{
use(day);
}
Besides creating another sentinel that shows that day was set and without relying on knowing the contents of the days enum?
In similar coding, I try to reserve the first enum (0) as the "NULL" value:
typedef enum {
nullday = 0,
sun=1,
mon=2,
tue=3,
wed=4,
thu=5,
fri=6,
sat=7,
} days;
That allows for a 'non-day' day:
days day;
day = nullday;
if (somecondition)
{
day = sun;
}
else if (othercondition)
{
day = mon;
}
if (day != nullday)
{
use(day);
}
Another version of the code:
typedef enum {nullday=0, sun, mon,tue,wed,thu,fri,sat} days;
...
days day = nullday;
if (somecondition)
{
day = sun;
}
else if (othercondition)
{
day = mon;
}
if (day)
{
use(day);
}