• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Język C- zdefiniować strukturę DAY zawierającą informację o dacie

VPS Starter Arubacloud
0 głosów
791 wizyt
pytanie zadane 22 listopada 2018 w C i C++ przez Jennesse Nowicjusz (220 p.)

Witam. Mam zdefiniować strukturę DAY zawierającą informację o dacie, a nastepnie dwuargumentową funkcję days zwracającą liczbę dni pomiędzy dwoma przekazanymi datami. Uwzględnić lata przystępne i zmianę kalendarza. 

struct DAY;
int days (struct DAY, struct DAY);

Pomoże ktoś? Nie mam pojęcia, jak to zacząć

2 odpowiedzi

+1 głos
odpowiedź 22 listopada 2018 przez Eryk Andrzejewski Mędrzec (164,260 p.)

Trzeba zacząć od zdefiniowania struktury. Zajrzyj w pierwszy-lepszy kurs C, jeżeli nie wiesz jak to się robi. Według mnie możesz zdefiniować trzy pola: dzień, miesiąc i rok - oczywiście przechowuj je w postaci liczb całkowitych.

Aby wyznaczyć ilość dni pomiędzy dwoma datami, proponuję zrobić coś takiego, że najpierw dla każdej z tych dat wyznaczasz ile dni upłynęło np. od 1 stycznia roku 1 n.e, albo np. od 1 stycznia roku 1900 - jak Ci jest wygodniej i zależnie od zastosowania projektu, jeżeli daty mogą dotyczyć jakichś dawnych wydarzeń historycznych to proponowałbym to pierwsze rozwiązanie. Jak to zrobić? A no trzeba wyznaczyć ile pełnych lat upłynęło od danego okresu (jeżeli zaczynamy odliczanie od 1 stycznia to to będzie proste), w tym ile było lat "zwykłych", a ile przestępnych - i dla każdego roku przestępnego dodajesz do całkowitego wyniku 366, a w pozostałych przypadkach dodajesz 365. Następnie musisz sprawdzić, który jest aktualnie dzień w roku (oczywiście uwzględniasz, czy aktualny rok jest rokiem przestępnym) - dla każdego miesiąca, który już całkowicie upłynął dodajesz do całkowitego wyniku liczbę dni tego miesiąca (zazwyczaj jest stała, wyjątkiem jest luty, jeżeli mamy rok przestępny). Następnie dodajesz liczbę dni, która pozostała. Trochę to zagmatwane, ale pomyśl nieco i zrozumiesz o co chodzi.

Kiedy już będziesz miał wyznaczoną liczbę dni od danego punktu orientacyjnego (czyli np. tego 1 stycznia roku 1 n.e) no to możesz po prostu odjąć od siebie te dwie liczby dla dwóch dat. Jeżeli potrzebujesz wyniku nieujemnego, wystarczy zastosować funkcję abs() z biblioteki math.h.

O, teraz doczytałem, że masz uwzględnić też aktualizację kalendarza - to po prostu przeczytaj o zasadach kalendarza juliańskiego i kiedy został wyparty przez kalendarz gregoriański - a wszystko inne chyba według podobnych reguł. wink

komentarz 22 listopada 2018 przez Jennesse Nowicjusz (220 p.)

Dziękuję za odpowiedź. Aczkolwiek totalnie nie rozumiem tego "w tym ile było lat "zwykłych", a ile przestępnych - i dla każdego roku przestępnego dodajesz do całkowitego wyniku 366, a w pozostałych przypadkach dodajesz 365." 

#include<stdio.h>

int main(){
int dni1,dni2,wszystkie_dni;
nt ile_lat[2];
struct data {
int dzien;
int miesiac;
int rok;
}
data pierwsza,druga;
printf("Podaj pierwszą datę:");
scanf("%d%d%d",pierwsza.dzien,pierwsza.miesiac,pierwsza.rok);
printf("Podaj drugą datę:");
scanf("%d%d%d",pierwsza.druga,druga.miesiac,druga.rok);
ile_lat[1]=pierwsza.rok-1;
ile_lat[2]=druga.rok-1;
for(i=1;i<=ile_lat[1];i++){
if(i%4==0 && i%100!=0 || i%400==0){
dni1+=366
}
else{
dni2+=365
}
wszystkie_dni=dni1+dni2;
}
return 0;
}

Czy do tego momentu coś jest źle? Mam pętlik w głowię.. 

komentarz 22 listopada 2018 przez Eryk Andrzejewski Mędrzec (164,260 p.)

Och panie, polecam zainwestować w tabulatory, bo ciężko cokolwiek odczytać tutaj. smiley

Jak znajdę chwilkę to się przyjrzę.

komentarz 22 listopada 2018 przez Jennesse Nowicjusz (220 p.)
Dziękuję. Niecierpliwie czekam
komentarz 22 listopada 2018 przez Eryk Andrzejewski Mędrzec (164,260 p.)

Zacznę od tego, że masz błędy kompilacji w swoim kodzie. Po pierwsze, jeśli już, to:

nt ile_lat[2];

powinieneś zastąpić:

int ile_lat[2];

Zjadłeś literkę. smiley

Kolejna sprawa - definicję struktury kończymy średnikiem.

I kolejna - albo przed nazwą typu struktury przy deklaracji zmiennych będziesz podawał słowo kluczowe struct - o w taki sposób:

struct data pierwsza, druga;

Albo musisz zmienić nieco definicję struktury z czegoś takiego:

struct data {
    // ... pola struktury
};

na coś takiego:

typedef struct {
    // ... pola struktury
} data;

Wtedy będziesz mógł posługiwać się tymi nazwami normalnie.

Kolejna rzecz - w scanf() kolejne wartości w formacie (czyli te %d) należałoby oddzielić spacjami, a jako argument musisz przekazać adresy zmiennych - ponieważ funkcja przyjmuje te wartości przez wskaźnik, bo musi je zmodyfikować. A więc nazwy zmiennych-argumentów poprzedź ampersandem (&).

W drugim scanf() musisz poprawić pierwsza.druga na druga.dzien.

W pętli for (konkretnie to w jej nagłówku) musisz zadeklarować zmienną i, a ty po prostu przypisujesz wartość do zmiennej i, nigdzie jej wcześniej nie deklarując.

I dodaj średniki na końcu poniższych linii.

dni1+=366

//...


dni2+=365

Twojego kodu jeszcze nie przeanalizowałem, nie ukrywam że niechlujne formatowanie mi to trochę utrudnia. frown

Ja naprawdę Ci dobrze radzę - porób eleganckie wcięcia, niezbyt przyjemnie się czyta taką ścianę tekstu, bez estetycznie wyróżnionej żadnej hierarchii w kodzie - który kod wykonuje się w pętli, który w instrukcji warunkowej. Można oczywiście do tego dojść, jak się chwilę posiedzi, ale chyba nie o to chodzi żeby ślęczeć nad kodem, aby pojąć o co w nim chodzi. W taki sposób bardzo łatwo też o błędy.

Aktualizacja

Kolejne sprawy, które rzucają mi się w oczy:

  • z tego co mi wiadomo, język C wymaga, aby dla funkcji nieprzyjmującej żadnych parametrów (jak u Ciebie main) wpisać wyraźnie void na liście parametrów. Niby działa bez tego, ale chyba jednak warto o to zadbać.
    int main(void)
  • tablice indeksujemy od 0, nie od 1. Jeżeli alokujesz tablicę w taki sposób:
    int ile_lat[2];

    To oznacza, że tablica ta będzie zawierała dwa elementy. Indeksy tych elementów to 0 i 1. Nigdy nie będziesz miał indeksu 2.

komentarz 22 listopada 2018 przez Jennesse Nowicjusz (220 p.)
#include<stdio.h>

int main(void){
int dni1,dni2,wszystkie_dni;
int ile_lat1,ile_lat2;
struct data {
        int dzien;
        int miesiac;
        int rok;
}
struct data pierwsza,druga;
printf("Podaj pierwsza data:");
scanf("%d %d %d",&pierwsza.dzien,&pierwsza.miesiac,&pierwsza.rok);
printf("Podaj druga data:");
scanf("%d %d %d",&pierwsza.druga,&druga.miesiac,&druga.rok);
ile_lat1=pierwsza.rok-1;
ile_lat2=druga.rok-1;
for(int i=1;i<=ile_lat[1];i++){
        if(i%4==0 && i%100!=0 || i%400==0){
                dni1+=366;
}
        else{
                dni2+=365;
}
        wszystkie_dni=dni1+dni2;
}
return 0;
}

 

komentarz 22 listopada 2018 przez Jennesse Nowicjusz (220 p.)
Ktoś ma pomysł jak to dalej pociągnąc? :(
0 głosów
odpowiedź 23 listopada 2018 przez Bondrusiek Maniak (61,370 p.)

Witam,

wydaje mi się że nazwa DAY była by nieprecyzyjna w stosunku do tego problemu. Lepiej by było nazwać to Data(Date), która by reprezentowała dzień/miesiąc/rok. Na przykład:

struct Date
{
    int day, month, year;
    Date(int _day, int _month, int _year) : day(_day), month(_month), year(_year) {}
};

Dzięki takiej strukturze bez problemu można przedstawić dzień.

Następnie należy zdefiniować funkcję, która sprawdza czy dany rok jest przestępny. Za ( https://pl.wikibooks.org/wiki/Kody_%C5%BAr%C3%B3d%C5%82owe/Rok_przest%C4%99pny ).

bool isLeapYear(int _year)
{
    return (_year % 4 == 0 && _year % 100 != 0 || _year % 400 == 0);
}

Kolejną rzeczą, którą należałoby zdefiniować są poszczególne dni w danym miesiącu. Dni tygodnia można przypisać do tablicy dla roku nieprzestępnego. Za( https://pl.wikipedia.org/wiki/Szablon:Miesi%C4%85ce_i_dni_roku)

static int daysOfMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

Mając wszystkie dane można przystąpić do napisania funkcji days, która zwraca różnicę liczb.

int days(Date d1, Date d2)
{
    //rok i miesiąc jest ten sam
    if(d1.year == d2.year && d1.month == d2.month)
    {
        int retVal =d1.day - d2.day;
        return  retVal;
    }
    //rok jest taki sam
    else if(d1.year == d2.year)
    {
        if(isLeapYear(d1.year)) daysOfMonth[1] = 29;
        int summary = 0;
        for(int idx = d2.month - 1 ;
            idx < d1.month - 1;
            ++idx)
        {
            summary += daysOfMonth[idx];
        }

        summary += (d1.day - d2.day);
        daysOfMonth[1] = 28;
        return summary;
    }
    //roki są różne
    else
    {
        int summary = 0;
        for(int idxY = d2.year; idxY != (d1.year - 1) ; ++idxY)
        {
            if( isLeapYear(idxY) )
            {
                summary += 366; // rok przestepny
            }
            else
            {
                summary += 365; // normalny rok
            }
        }
        //roki są taki same więc bazujemy na liczbach dni w miesiącach
        if(isLeapYear(d1.year)) daysOfMonth[1] = 29;
        for(int idx = d2.month - 1 ;
            idx < d1.month - 1;
            ++idx)
        {
            summary += daysOfMonth[idx];
        }
        //miesiące są takie same więc bazujemy na liczbach dni
        summary += (d1.day - d2.day);
        daysOfMonth[1] = 28;
        return summary;

    }

}

Ta funkcja ma kilka wad. Np. d1 zawsze musi być większe niż d2. Można również poprawić strukturę dodając nowe funkcje składowe.

Podobne pytania

0 głosów
1 odpowiedź 504 wizyt
pytanie zadane 26 października 2020 w C i C++ przez komboboost0 Użytkownik (570 p.)
0 głosów
2 odpowiedzi 753 wizyt
pytanie zadane 3 czerwca 2017 w C i C++ przez Dorota95 Nowicjusz (210 p.)
0 głosów
0 odpowiedzi 143 wizyt
pytanie zadane 13 stycznia 2020 w C i C++ przez Glitterfrost Nowicjusz (210 p.)

92,452 zapytań

141,262 odpowiedzi

319,079 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...