2016-07-28 5 views
2

Я работаю с программой, которая обновляет введенную дату и обновляет ее. Принимая во внимание дней в месяце и будет ли это високосный год, и т.д.Я правильно использовал указатели в функции updateDate?

Я пытаюсь упражнение в указателях главе «Программирование в C»:

«Учитывая определение date структуры, как определено в этой главе напишите функцию, называемую dateUpdate(), которая принимает указатель на структуру date в качестве аргумента и обновляет структуру на следующий день (см. Программу 8.4). "

Не могли бы вы рассказать мне, если бы я сделал то, что было задано?

Это исходный код:

#include <stdio.h> 
#include <stdbool.h> 

struct date 
{ 
    int month; 
    int day; 
    int year; 
}; 


struct date dateUpdate (struct date today); 
int numberOfDays (struct date d); 
bool isLeapYear(struct date d); 

int main (void) 
{ 
    struct date thisDay, nextDay; 

    printf("Enter today's date (mm dd yyyy) : "); 
    scanf("%i%i%i", &thisDay.month, &thisDay.day, &thisDay.year); 

    nextDay = dateUpdate(thisDay); 

    printf("Tomorrow's date is %i/%i/%.2i.\n", nextDay.month, nextDay.day, nextDay.year % 100); 

    return 0; 
} 


struct date dateUpdate (struct date today) 
{ 
    struct date tomorrow; 
    int numberOfDays (struct date d); 

    if(today.day != numberOfDays (today)) 
    { 
     tomorrow = (struct date) {today.month, today.day + 1, today.year}; 
    } 
    else if(today.month == 12) 
    { 
     tomorrow = (struct date) {1, 1, today.year + 1}; 
    } 
    else 
    { 
     tomorrow = (struct date) {today.month + 1, 1, today.year}; 
    } 

    return tomorrow; 
} 

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

bool isLeapYear(struct date d) 
{ 
    bool leapYearFlag; 

    if ((d.year % 4 == 0 && d.year % d.year % 100 != 0) || d.year % 400 == 0) 
    { 
     leapYearFlag = true; 
    } 
    else 
    { 
     leapYearFlag = false; 
    } 

    return leapYearFlag; 
} 

А вот моя попытка использовать указатели в updateFunction:

#include <stdio.h> 
#include <stdbool.h> 

struct date 
{ 
    int month; 
    int day; 
    int year; 
}; 


struct date dateUpdate (struct date* today); 
int numberOfDays (struct date d); 
bool isLeapYear(struct date d); 

int main (void) 
{ 
    struct date thisDay, nextDay, *datePtr; 

    printf("Enter today's date (mm dd yyyy) : "); 
    scanf("%i%i%i", &thisDay.month, &thisDay.day, &thisDay.year); 

    datePtr = &thisDay; 

    nextDay = dateUpdate(datePtr); 

    printf("Tomorrow's date is %i/%i/%.2i.\n", nextDay.month, nextDay.day, nextDay.year % 100); 

    return 0; 
} 


struct date dateUpdate (struct date* today) 
{ 
    struct date tomorrow; 
    int numberOfDays (struct date d); 

    if(today->day != numberOfDays (*today)) 
    { 
     tomorrow = (struct date) {today->month, today->day + 1, today->year}; 
    } 
    else if(today->month == 12) 
    { 
     tomorrow = (struct date) {1, 1, today->year + 1}; 
    } 
    else 
    { 
     tomorrow = (struct date) {today->month + 1, 1, today->year}; 
    } 

    return tomorrow; 
} 

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

bool isLeapYear(struct date d) 
{ 
    bool leapYearFlag; 

    if ((d.year % 4 == 0 && d.year % d.year % 100 != 0) || d.year % 400 == 0) 
    { 
     leapYearFlag = true; 
    } 
    else 
    { 
     leapYearFlag = false; 
    } 

    return leapYearFlag; 
} 

Сейчас обе программы компиляции и, кажется, для правильной работы.

+0

Я не совсем понимаю ваш вопрос.Но чтобы сделать указатель на структуру, вы будете делать данные структуры * завтра; И везде у вас есть оператор точки, просто введите его в оператор стрелки ->. Пример: вместо завтрашнего дня сделать это завтра-> день; –

+0

Моя вина, позвольте мне переписать этот автокаталог вопроса. – gloopit

+0

Вы пробовали? –

ответ

1

Чтобы расширить комментарий Omid CompSCI: это почти так же просто. Почти.

#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h> 

// ALL TESTS OMMITTED! 

struct date { 
    int month; 
    int day; 
    int year; 
}; 
// add the pointer mark (asterix) 
struct date *dateUpdate(struct date *today); 
int numberOfDays(struct date *d); 
bool isLeapYear(struct date *d); 

int main(void) 
{ 
    // again ,just add the pointer marks 
    struct date *thisDay, *nextDay; 
    // using a pointer means that all you have is a pointer 
    // but you need some memory to store the content 
    thisDay = malloc(sizeof(struct date)); 

    printf("Enter today's date (mm dd yyyy) : "); 
    // use the "->" notation to get to the respective storages 
    scanf("%i%i%i", &thisDay->month, &thisDay->day, &thisDay->year); 

    // dateUpdate() has been changed to accept and return a pointer, 
    // so no change in notations here 
    nextDay = dateUpdate(thisDay); 
    // again: use the "->" notation to get to the respective storages 
    printf("Tomorrow's date is %i/%i/%.2i.\n", nextDay->month, nextDay->day, 
    nextDay->year % 100); 

    // memory allocated by 'alloc() needs to be free'd, too 
    free(nextDay); 
    free(thisDay); 

    return 0; 
} 

// just added pointer markings 
struct date *dateUpdate(struct date *today) 
{ 
    struct date *tomorrow; 
    // again, we need to allocated some memory 
    // not only to get storage but also to be able to return it 
    tomorrow = malloc(sizeof(struct date)); 
    // again: use the "->" notation to get to the respective storages 
    if (today->day != numberOfDays(today)) { 
    // the notation of the cast does not change, the target does 
    *tomorrow = (struct date) { 
    today->month, today->day + 1, today->year}; 
    } else if (today->month == 12) { 
    *tomorrow = (struct date) { 
    1, 1, today->year + 1}; 
    } else { 
    *tomorrow = (struct date) { 
    today->month + 1, 1, today->year}; 
    } 
    return tomorrow; 
} 

int numberOfDays(struct date *d) 
{ 
    int days; 
    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; 
} 

bool isLeapYear(struct date * d) 
{ 
    bool leapYearFlag; 
    // you have one "d.year %" too much in your code 
    if ((d->year % 4 == 0 && d->year % 100 != 0) || d->year % 400 == 0) { 
    leapYearFlag = true; 
    } else { 
    leapYearFlag = false; 
    } 

    return leapYearFlag; 
} 

Надеюсь, это немного улучшится.

+0

большое спасибо! Если сначала объявить структуры, отличные от указателей, вместе с их размером, а затем назначить указатель, я могу избежать использования malloc, не так ли? – gloopit

+0

Malloc - это не то, что я еще не нарисовал, и дальше в книге, которую я изучаю. – gloopit

+0

Если вы видите мою попытку выше, я не использовал синтаксис указателя для других функций, таких как 'isLeapYear' или' numberOfDays'. Есть ли какие-либо преимущества, чтобы изменить его на указатели? Видя, что единственное, что было изменено, было добавление '*' и переключение '.' для' -> ' Я признаю, что мне нравится ваша однородность, хотя :) – gloopit

0

Этот код может быть легко преобразован для использования указателей. Указатели полезны, поскольку они предоставляют альтернативу копированию данных ваших структур каждый раз, когда вызывается функция. Вы все равно можете использовать обычную механику передачи по значению в другом месте. Переписывание кода очень просто и требует нескольких изменений. Например, ваша функция struct date dateUpdate(); может быть переназначена для приема указателей путем добавления символа * после типа, например. int - int *. Определение вашей функции struct date dateUpdate будет изменено на struct date *dateUpdate (struct date *today);, что означает, что передается указатель или адрес памяти даты struct. Ваш код также должен быть изменен в декларации. Например, в bool isLeapYear() строка кода if ((d.year % 4 == 0 && d.year % d.year % 100 != 0) || d.year % 400 == 0) необходимо будет заменить на if ((d->year % 4 == 0 && d->year % d->year % 100 != 0) || d->year % 400 == 0). Оператор -> является сокращением для (*pointer).variable, так как компилятору должно быть предложено получить член структуры по адресу адрес, а не фактическое местоположение указателя. Теперь, когда переданный тип изменился, вызов также отличается. Вызов bool isLeapYear() теперь не bool isLeapYear (d);, но bool isLeapYear (&d);, так как оператор & получает адрес struct. Используя эту информацию, введите преобразованную версию вашей программы: link. Большая проблема заключается в том, что большая часть вашего кода не работает, но это выходит за рамки вашего вопроса. EDIT: Этот ответ был сделан до вашего редактирования вопроса, но по-прежнему полезен.

+0

Все исправлено сейчас, большое вам спасибо! – gloopit

0

Вот мое упражнение, которое, я думаю, предназначено для использования указателя на обновление единой структуры даты со следующей датой.

/* Exercise 10.11 

    Given the definition of a date structure as defined in this chapter, write 
    a function called dateUpdate() that takes a pointer to a date structure as 
    its argument and that updates the structure to the following day. 
*/ 

#include <stdio.h> 
#include <stdbool.h> 

struct date 
{ 
    int month; 
    int day; 
    int year; 
}; 

void dateUpdate (struct date *ptr) 
{ 
    int numberOfDays (struct date d); 

    if (ptr->day != numberOfDays (*ptr)) 
     ++ptr->day; 
    else if (ptr->month == 12) {     // end of year 
     ptr->day = 1; 
     ptr->month = 1; 
     ++ptr->year; 
    } 
    else {           // end of month 
     ptr->day = 1; 
     ++ptr->month; 
    } 
} 

int numberOfDays (struct date d) 
{ 
    bool isLeapYear (struct date d); 

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

bool isLeapYear (struct date d) 
{ 
    bool leapYearFlag; 

    if ((d.year % 4 == 0 && d.year % 100 != 0) || d.year % 400 == 0) 
     leapYearFlag = true;      // leap year 
    else 
     leapYearFlag = false;      // not a leap year 

    return leapYearFlag;   
} 

int main (void) 
{ 
    void dateUpdate (struct date *ptr); 

    struct date calendar; 

    printf ("Enter a day's date (mm dd yyyy): "); 
    scanf ("%i%i%i", &calendar.month, &calendar.day, &calendar.year); 

    dateUpdate (&calendar); 

    printf ("The next day's date is %i/%i/%.2i.\n", calendar.month, 
      calendar.day, calendar.year % 100); 

    return 0; 
} 
Смежные вопросы