سؤال

I have an assignment from college, in which I have to use C to pack three unsigned integers representing a date (the year must be between 1970 and 2097) and compress it into an unsigned short, then unpack it again and show it in command line.

Can someone help me please?

Below I leave the code I have so far (declared variables outside functions and function signatures cannot be changed)

Edit: I have a second problem, which is the getchar function not return anything, setting the three date fields to 0...

#include <stdio.h>

typedef unsigned short pkdate_t;
typedef struct date3 {
    unsigned year;
    unsigned month;
    unsigned day;
} date3_t;

int ror (int val, unsigned n) {
    return (val >> n)|(n << (32 - n));
}

int pack_date (pkdate_t * dst, date3_t * src) {
    if ((*src).year < 1097 || (*src).year > 2097 || (*src).month < 1 || (*src).month > 12 || (*src).day < 1 ||
    ((*src).month == 2 && (((*src).year / 4 == 0 && (*src).day > 29) || ((*src).year / 4 != 0 && (*src).day > 28))) ||
    (((*src).month == 2 || (*src).month == 4 || (*src).month == 6 || (*src).month == 9 || (*src).month == 11) && (*src).day == 31)) return -1;

    //(*dst) = (*src).year * 10 + (*src).month + (*src).day; "wrong code"

    return 0;
}

int unpack_date (date3_t * dst, pkdate_t date) {
    (*dst).year = date % 10000;
    date = date / 10000;
    (*dst).month = date % 100;
    date = date / 100;
    (*dst).day = date % 100;

    if ((*dst).year < 1097 || (*dst).year > 2097 || (*dst).month < 1 || (*dst).month > 12 || (*dst).day < 1 ||
    ((*dst).month == 2 && (((*dst).year / 4 == 0 && (*dst).day > 29) || ((*dst).year / 4 != 0 && (*dst).day > 28))) ||
    (((*dst).month == 2 || (*dst).month == 4 || (*dst).month == 6 || (*dst).month == 9 || (*dst).month == 11) && (*dst).day == 31)) return -1;
    else return 0;
}

int main () {
    int k = ror(30, 2);
    printf("%s\n", "exercicio 1:");
    printf("%d turned into %d\n", 30, k);

    pkdate_t date = 0;
    date3_t newDate;
    newDate.year = 2000;
    newDate.month = 04;
    newDate.day = 02;
    printf("%s\n", "exercicio 2:");
    //printf("%s\n", "insira uma data (yyyymmdd) e de seguida pressione enter:");

    //int i = 1000;

    //while (i > 0) {
        //newDate.year += getchar() * i;
        //i = i / 10;
    //}

    //i = 10;

    //while (i > 0) {
        //newDate.month += getchar() * i;
        //i = i / 10;
    //}

    //i = 10;

    //while (i > 0) {
        //newDate.day += getchar() * i;
        //i = i / 10;
    //}

    //"the commented part above does not get any values from command line, still figuring that part out :)"

    pack_date(&date, &newDate);

    printf("packed date: %hu\n", date);

    unpack_date(&newDate, date);

    printf("unpacked date: %u/%u/%u\n", newDate.year, newDate.month, newDate.day);

    //newDate.year = 2000;
    //newDate.month = 12;
    //newDate.day = 14;
    //pack_date(&date, &newDate);
    //printf("%s\n", "exercicio 3:");
    //printf("date is %hu\n", date);

    // "ignore"

    return 0;
}
هل كانت مفيدة؟

المحلول

In C, there aren't so much use cases that qualify for bitfields, but this one is a perfect fit IMHO since it saves you a lot of headaches from bit shifting:

struct date_struct
{
    unsigned short year:7;
    unsigned short month:4;
    unsigned short day:5;
};

union date
{
   struct date_struct bits;
   short date;
}

نصائح أخرى

First, you should think about how the date should be presented inside this unsigned short.

End even firster, you should be aware that the length of a(n unsigned) short is not defined exactly, only its minimum, which is 16 bits.

So let's try to pack such a date into 16 bits.

As already was commented as I write this answer, you can shrink the years into a range of y-1970 = 0..127, which makes you need 7 bits. The months need 4 bits and the days 5, in total 16 bits.

Now think about how you determine the single parts and how you shift them so that they fit.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top