2013-10-27 5 views
2

Я начал изучать C и только столкнулся с проблемой.C: неполное определение ошибки типа 'struct date'

Я создал дату ADT и хотели бы, чтобы проверить это :)

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

после компиляции этих файлов я получил следующие ошибки:

datetest.c:15:45: error: incomplete definition of type 'struct date' 
    printf("Year: %d Month: %d Day: %d", d->year, d->month, d->day); 
             ~^ 
./date.h:4:16: note: forward declaration of 'struct date' 
typedef struct date Date; 

Что я делаю неправильно?

date.c:

#include "date.h" 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

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

/* 
* date_create creates a Date structure from `datestr` 
* `datestr' is expected to be of the form "dd/mm/yyyy" 
* returns pointer to Date structure if successful, 
*   NULL if not (syntax error) 
*/ 
Date *date_create(char *datestr) { 
    Date *d = (Date *)malloc(sizeof(Date)); 
    const char delimiter[2] = "/"; 
    char *token; 

    if (d != NULL) { 
    token = strtok(datestr, delimiter); 
    d->day = atoi(token); 
    token = strtok(NULL, delimiter); 
    d->month = atoi(token); 
    token = strtok(NULL, delimiter); 
    d->year = atoi(token); 
    //printf("Day: %d Month: %d Year: %d\n", d->day, d->month, d->year);  
    //printf("Day: %p Month: %p Year: %p\n", *d->day, *d->month, *d->year); 
    } 
    return d; 
}; 

/* 
* date_duplicate creates a duplicate of `d' 
* returns pointer to new Date structure if successful, 
*   NULL if not (memory allocation failure) 
*/ 
Date *date_duplicate(Date *d) { 
    Date *dd = (Date *)malloc(sizeof(Date)); 
    if (dd != NULL) { 
    dd->day = d->day; 
    dd->month = d->month; 
    dd->year = d->year; 
    } 
    return dd; 
}; 

/* 
* date_compare compares two dates, returning <0, 0, >0 if 
* date1<date2, date1==date2, date1>date2, respectively 
*/ 
int date_compare(Date *date1, Date *date2) { 
    if (date1->year < date2->year) 
    return -1; 
    else if (date1->year > date2->year) 
    return 1; 
    else { 
    if (date1->month < date2->month) 
     return -1; 
    else if (date1->month > date2->month) 
     return 1; 
    else { 
     if (date1->day < date2->day) 
    return -1; 
     else if (date1->day > date2->day) 
    return 1; 
     else 
    return 0; 
    } 
    } 
}; 

/* 
* date_destroy returns any storage associated with `d' to the system 
*/ 
void date_destroy(Date *d) { 
    if (d != NULL) 
    free(d); 
}; 

datetest.c:

#include "date.h" 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

int main() { 
    Date *d; 
    char buf[1024], *s; 

    while (fgets(buf, sizeof(buf), stdin) != NULL) { 
    if (!(d = date_create(buf))) { 
    fprintf(stderr, "Unable to create a date.\n"); 
    return -1; 
    } 
     printf("Year: %d Month: %d Day: %d", d->year, d->month, d->day); 
    } 
} 

date.h:

#ifndef _DATE_H_INCLUDED_ 
#define _DATE_H_INCLUDED_ 

typedef struct date Date; 

/* 
* date_create creates a Date structure from `datestr` 
* `datestr' is expected to be of the form "dd/mm/yyyy" 
* returns pointer to Date structure if successful, 
*   NULL if not (syntax error) 
*/ 
Date *date_create(char *datestr); 

/* 
* date_duplicate creates a duplicate of `d' 
* returns pointer to new Date structure if successful, 
*   NULL if not (memory allocation failure) 
*/ 
Date *date_duplicate(Date *d); 

/* 
* date_compare compares two dates, returning <0, 0, >0 if 
* date1<date2, date1==date2, date1>date2, respectively 
*/ 
int date_compare(Date *date1, Date *date2); 

/* 
* date_destroy returns any storage associated with `d' to the system 
*/ 
void date_destroy(Date *d); 

#endif /* _DATE_H_INCLUDED_ */ 

ответ

7

Вы определения struct date в date.c, datetest.c понятия не имеет, что это такое. Вместо этого объявите его в date.h. В настоящее время это непрозрачный тип - все, что включает date.h, может сделать указатель на него, но не может получить доступ к членам.

+0

Пример кода, пожалуйста? :) – chuckfinley

+0

Переместить дату 'struct { int day; int month; int year; }; 'часть в файл заголовка. – Kevin

+0

В определении задачи говорится, что я не должен редактировать файл date.h, просто date.c. Есть ли способ обойти это? – chuckfinley

2
datetest.c:15:45: error: incomplete definition of type 'struct date' 
    printf("Year: %d Month: %d Day: %d", d->year, d->month, d->day); 
             ~^ 
./date.h:4:16: note: forward declaration of 'struct date' 
typedef struct date Date; 

Когда компилятор обрабатывает date.h, он обнаруживает, что date.h оленья кожа имеет struct date но он использует date. Поэтому он бросает эту ноту note: forward declaration of 'struct date'

В datetest.c вы включили date.h, но не фактическое определение, которое находится в date.c и компилятор не может определить тип. Вот почему он бросает ошибку

error: incomplete definition of type 'struct date' 

Чтобы это исправить,

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

Переместить это date.h файл.

+0

В задаче, которую я даю, я должен работать только на date.c и datetest.c. Есть ли способ обойти это? – chuckfinley

+0

@martynas Nope: (Возможно, вам придется определять 'date' и' typedef' во всех файлах 'c', которые ему нужны. Простым способом является перенос определения' date' в 'date.h' – thefourtheye

+0

Я получаю ошибка: ./datetest.o: Malformed Mach-o file – chuckfinley

0

Ваша программа объявляет struct date в файле .c, что означает, что вы имеете доступ только к вещам, указанным в файле .h.

Причина, по которой вы можете объявить date, состоит в том, что вы делаете ее pointer, а компилятор знает размер всех указателей. Тем не менее, он ничего не знает о членах date и, следовательно, вы не можете вызвать таких пользователей, как d->year, d->month, d->day и т. Д. Вызов этих членов дает вам вашу ошибку.

Один из вариантов, чтобы сделать некоторые функции интерфейса, которые возвращают year, month и т.д.

Так как вы, вероятно, в классе структур данных, и файл заголовка предоставляется для вас и было дано указание не менять Это. Я бы просто вызывал функции в заголовочном файле ТОЛЬКО и печатал такие вещи, как "passed", когда они работают, как ожидалось, и показывают, что программа не подверглась сегментации, и оставьте ее без необходимости звонить , month и т. Д.

Смежные вопросы