c - 跨多个文件的冲突类型的函数
问题描述
我的代码中的每个函数都出现错误,内容如下:
database.c:21:5: error: conflicting types for ‘p_register’
21 | int p_register (struct unPaciente *tabla, int *numero) {
| ^~~~~~~~~~
In file included from database.c:11:
database.h:20:5: note: previous declaration of ‘p_register’ was here
20 | int p_register (struct unPaciente *tabla, int *numero);
我有一个名为 database.c 的文件,它需要从名为 database.h 和 inout.h 的其他文件中获取其他函数的原型。每个文件的代码如下:
数据库.c
//DEFINICIONES DE LAS FUNCIONES
//Generacion de un ejecutable a partir de dos codigos fuentes -> gcc -Wall divoc.c inout.c -o divoc
//Generacion del codigo objeto de inout -> gcc -Wall -c inout.c
//Generacion de un ejecutable a partir de un codigo fuente y un codigo objeto -> gcc -Wall divoc.c inout.o -o divoc
#include "database.h"
#include "inout.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//DEFINICION DE FUNCIONES del menú
int p_register (struct unPaciente *tabla, int *numero) {
int i;
int verificacion;
int tos, fiebre;
i = *numero;
int *ptos, *pfiebre;
char sintomas;
char *p;
p = &tabla[i]; //puntero que apunta a la direccion de losPacientes
fprintf (stdout ,"Register \n");
get_string ("Name (1-24)",1, 25, tabla[i].nombre); //Pide un nombre con get_string y lo guarda en tabla[numero].nombre
do {
get_string ("DNI (9-9)", 9, 9, tabla[i].dni); //pedir dni con get_string y guardarlo en tabla[numero].dni
verificacion = verify_dni(tabla[i].dni);
if (verificacion == 0) {
fprintf (stdout ,"Invalid DNI \n");
}
} while (verificacion == 0);
get_integer ("Date [1900-2020]", 0,120); //pedir edad con get_integer y guardarlo en tabla[numero].edad
tos = yes_or_no("Cough (y/n): "); //preguntar si tienes tos con yes_or_no y guardarlo en tabla[numero].tos
(*p).tos = tos;
fiebre = yes_or_no("Fever (y/n): "); //preguntar si tiene fiebre con yes_or_no y guardarlo en tabla[numero].fiebre
(*p).fiebre = fiebre;
sintomas = get_caracter("Sypmtom", "FSTMN");
(*p).sintomas = sintomas;
fprintf (stdout ,"New patient: %s %s %d %d %d %c \n",tabla[i].nombre, tabla[i].dni, tabla[i].edad, tabla[i].tos, tabla[i].fiebre, tabla[i].sintomas);
numero += 1;
return numero;
}
int p_discharge (struct unPaciente *tabla, int *numero) { //Funcion p_discharge.
fprintf (stdout ,"Discharge \n");
int n;
char *dni;
int longitud;
int i;
char *a, *aaux;
char *b, *baux;
char *c, *caux;
char *d, *daux;
char *e, *eaux;
char *f, *faux;
aaux = &tabla[i].nombre;
baux = &tabla[i].dni;
caux = &tabla[i].edad;
daux = &tabla[i].tos;
eaux = &tabla[i].fiebre;
faux = &tabla[i].sintomas;
*aaux = (char*)malloc(25 * sizeof(char));
*baux = (char*) malloc (10 * sizeof(char));
if (numero == 0) { //Comprueba si hay pacientes registrados que poder eliminar
fprintf (stdout ,"No patients yet \n");
return 0;
}
do {
get_string("DNI (9-9): ",9 ,9 ,dni);
longitud = strlen(dni);
} while (longitud != 9);
for (i=0; i <= *numero; i++) { //Recorre la tabla en busca de un paciente con un dni igual al introducido por el usuario
if ((dni == tabla[i].dni) && (i != numero)) { //SI SE QUIERE ELIMINAR UN PACIENTE DE EL MEDIO DE LA LISTA
for (i = i; i < *numero; i++) {
*aaux = tabla[i+1].nombre;
*baux = tabla[i+1].dni;
*caux = tabla[i+1].edad;
*daux = tabla[i+1].tos;
*eaux = tabla[i+1].fiebre;
*faux = tabla[i+1].sintomas;
//Por si es necesario borrar la memoria del ultimo elemento(ahora vacio despues de sobreescribir)
//free(aaux);
//free(baux);
//free(caux);
//free(daux);
//free(eaux);
//free(faux);
}
}
if ((dni == tabla[i].dni) && (i == *numero)) { //SI SE QUIERE ELIMINAR EL ULTIMO PACIENTE DE LA LISTA
a = &tabla[i].nombre;
b = &tabla[i].dni;
c = &tabla[i].edad;
d = &tabla[i].tos;
e = &tabla[i].fiebre;
f = &tabla[i].sintomas; /////ARREGLAR ESTA PARTE
free(a);
free(b);
free(c);
free(d);
free(e);
free(f);
fprintf (stdout, "Discharged patient \n");
numero -= 1;
return numero;
}
else {
fprintf (stdout ,"Unknown patient \n");
return numero;
}
}
}
int p_list(struct unPaciente *tabla, int numero) {
int i;
int edad;
fprintf (stdout ,"List \n");
edad = get_integer("Date [1900-2020]",0, 120); //Pide al usuario hasta que edad quiere que busque pacientes
fprintf (stdout ,"Patients born before %d", edad);
for (i = 0; i < numero; i++) { //Recorre la tabla, desde el 0, hasta el numero de pacientes
if (tabla[i].edad <= edad) {
display_patient(tabla, i); //Comprueba si algun paciente de la tabla tiene una fecha de nacimiento menor o igual que la dada por el usuario, y si es el caso, imprime su info
}
return 1;
}
}
int p_search (struct unPaciente *tabla, int numero) { //Funcion p_search.
int i;
char dni[10];
fprintf (stdout ,"Search \n");
get_string("DNI:",9 ,9 ,dni); //Pide al usuario un DNI con la funcion get_string
for (i = 0; i <= numero; i++) {
if (dni == tabla[i].dni) //Recorre la tabla en busca de una coincidencia con el dni introducido, si la hay, imprime su info
display_patient(tabla, i);
else {
fprintf (stdout ,"No matches \n"); //Informa al usuario que no hay ningun paciente que coincida con el dni introducido
}
return 0;
}
}
void p_mark (struct unPaciente *tabla, int numero) { //Funcion p_mark
int i;
fprintf (stdout ,"Mark positive \n"); //Indica al usuario que ha entrado en la funcion mark positive
if (numero == 0) { //Comprueba si el numero de pacientes es igual a 0
fprintf (stdout, "No patients yet \n");
return;
}
for (i=0; i <= numero; i++) { //Recorre la tabla en busca de un paciente que padezca de algun sintoma o enfermedad, y si lo encuentra, imprime sus datos
if ((tabla[i].tos == 1) || (tabla[i].fiebre == 1) || (tabla[i].sintomas == 'F') || (tabla[i].sintomas == 'S') || (tabla[i].sintomas == 'T')|| (tabla[i].sintomas == 'M')|| (tabla[i].sintomas == 'N')) {
fprintf (stdout ,"%s %s %d %d %d %c \n",tabla[i].nombre, tabla[i].dni, tabla[i].edad, tabla[i].tos, tabla[i].fiebre, tabla[i].sintomas);
return;
}
else {
fprintf (stdout ,"No sick patients yet \n"); //Si no hay un paciente que cumpla alguna de las condiciones anteriores, informa al usuario que no hay pacientes enfermos
return;
}
}
}
//int p_init (struct unPaciente *tabla, int numero) {
// int edad;
// numero = 0;
// edad = get_integer ("Date");
// while (edad > 1) {
// tabla[numero].edad = edad;
// get_string ("Name", 9, 9, tabla[numero].nombre);
// numero =+ 1;
// edad = get_integer ("Date");
// }
// return 0;
// }
void save_patients (struct unPaciente *tabla, int numero, FILE *fp) {
int i;
while ((i = fgetc(fp)) != EOF)
fputc(i, fp);
return;
}
int p_exit () {
int valor_salida;
fprintf (stdout ,"Exit \n");
valor_salida = yes_or_no("Are you sure you want to exit"); //El valor sacado de la funcion yes_or_no (1 o 0) sera atribuído a valor_salida y será el valor devuelto por la función
return valor_salida;
}
数据库.h
#ifndef DATABASE_H
#define DATABASE_H
//DECLARACIONES DE LAS FUNCIONES (PROTOTIPOS) del menú
void init_patients (struct unPaciente *tabla, int numero);
void save_patients (struct unPaciente *tabla, int numero, FILE *fp);
//int p_init (struct unPaciente *tabla, int numero);
int p_discharge (struct unPaciente *tabla, int *numero);
int p_list(struct unPaciente *tabla, int numero);
int p_search (struct unPaciente *tabla, int numero);
int p_register (struct unPaciente *tabla, int *numero);
void p_mark (struct unPaciente *tabla, int numero);
int p_exit();
#endif
inout.c(其中包含 database.c 中使用的某些函数的代码)
//Generacion de un ejecutable a partir de dos codigos fuentes -> gcc -Wall divoc.c inout.c -o divoc
//Generacion del codigo objeto de inout -> gcc -Wall -c inout.c
//Generacion de un ejecutable a partir de un codigo fuente y un codigo objeto -> gcc -Wall divoc.c inout.o -o divoc
#include "inout.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//DEFINICION DE FUNCIONES fuera del menú
void headline (char * APLICACION ,char caracterhl, int numchar) { // Funcion headline. Imprime una cadena centrada, entre 2 caracteres dados por el usuario.
int numblanks;
int j;
strlen(APLICACION);
numblanks = ((numchar - 2) - strlen(APLICACION)) /2;
fprintf (stdout ,"%c", caracterhl);
for (j=0; j<numblanks; j++) {
fprintf (stdout ," ");
}
fprintf (stdout ,"%s", APLICACION);
for (j=0; j<numblanks; j++) {
fprintf (stdout ," ");
} //si es impar numblanks, se hace un if else. El if imprime un (espacio) (+) y (cambio de linea) si es impar, y en el else, imprime un (+) y (cambio de linea)
if (numblanks%2 != 0) {
fprintf (stdout ,"%c" ,caracterhl);
fprintf (stdout ,"\n");
}
else {
fprintf (stdout ," ");
fprintf (stdout ,"%c" ,caracterhl);
fprintf (stdout ,"\n");
}
}
void stripe (char caracter, int numchar) { //funcion stripe modificada
int i;
for (i=0; i<numchar; i++) {
fprintf (stdout ,"%c" ,caracter);
}
if (i == numchar) {
fprintf (stdout ,"\n");
}
return;
}
//funcion yes_or_no
int yes_or_no (char *mensaje) { //YES_OR_NO (CONFIRMACION DE SALIDA) añadir sscanf
char opcion2;
fprintf (stdout ,"%s", mensaje);
fscanf (stdin ," %c", &opcion2);
if ((opcion2 == 'y') || (opcion2 == 'Y'))
{
fprintf (stdout ,"Ha seleccionado \"Si\".\n");
return 1;
}
if ((opcion2 == 'n') || (opcion2 == 'N'))
{
fprintf (stdout ,"Ha seleccionado \"No\".\n");
return 0;
}
else
{
fprintf (stdout ,"No ha seleccionado una opcion valida\n");
return 0;
}
}
//get_string
void get_string(char *mensaje ,int min ,int max ,char *la_cadena) {
char *linea;
char extra[256];
int valores;
int longitud, longitud2;
char *otra_cadena;
linea = (char *)malloc(max*sizeof(char));
do {
fprintf (stdout ,"%s" ,mensaje);
fgets (linea, sizeof(linea), stdin);
valores = sscanf (linea ,"%s%s" ,otra_cadena ,extra);
if (valores != 1) {
fprintf (stdout, "Formato incorrecto\n");
longitud = 0;
}
else {
longitud = strlen(otra_cadena);
}
} while ((longitud < max) && (longitud > min));
longitud2 = strlen(linea);
linea[longitud2 + 1] = '/0';
strcpy (la_cadena, otra_cadena);
return;
}
//funcion get_integer
int get_integer (char *mensaje, int min, int max) { //Funcion get_integer. Recibe una cadena como parametro, lee un numero, y devuelve ese numero si esta dentro del rango [1,24]
int numero;
char extra[256]; //cadena extra para comprobar si se introducen algo más que el número
int valores;
mensaje = (char *) malloc (256*sizeof(char));
do {
fprintf (stdout, "%s" ,mensaje);
fscanf (stdin, "%d" ,&numero);
if ((numero >= max) || (numero <= min))
{
fprintf (stdout ,"Valor incorrecto\n");
}
}
while ((numero >= max) || (numero <= min));
valores = sscanf (numero ,"%d%s" ,&numero ,extra);
if (valores == 2)
{
fprintf (stdout, "Formato incorrecto");
return 0;
}
else {
return numero;
}
}
char get_character (char *mensaje, char *comprobacion) {
int valores;
char letra;
char extra[256]; //cadena extra para comprobar si se introducen algo más que el número
mensaje = (char *) malloc (256*sizeof(char));
do {
fprintf (stdout, "%s" ,mensaje); //Se lee el mensaje de invitacion al usuario
fprintf (stdout ,"%s" ,comprobacion);
fscanf (stdin, "%c" ,&letra); //Se escanea el resultado
valores = sscanf (letra ,"%c %s" ,&letra ,extra); //Se le asigna a valores un numero en funcion del numero de elementos introducidos, si es distinto de 1, dará error
if (valores != 1)
{
fprintf (stdout, "Formato incorrecto");
break; //Si el formato es incorrecto pasará a la siguiente repeticion del bucle, saltándose los dos switch
}
if ((letra != 'F') || (letra != 'f') || (letra != 'S') || (letra != 's') || (letra != 'T') || (letra != 't') || (letra != 'M') || (letra != 'm') || (letra != 'N') || (letra != 'n') || (letra != 'R') || (letra != 'r') || (letra != 'S') || (letra != 's') || (letra != 'D') || (letra != 'd') || (letra != 'P') || (letra != 'p') || (letra != 'L') || (letra != 'l') || (letra != 'X') || (letra != 'x')) {
fprintf (stdout ,"Invalid option \n"); //Se comprueba que la letra es distinta a cualquiera de las letras pertenecientes al menu o a los sintomas
}
if ((letra == 'F') || (letra == 'f') || (letra == 'S') || (letra == 's') || (letra == 'T') || (letra == 't') || (letra == 'M') || (letra == 'm') || (letra == 'N') || (letra == 'n')) {
//Para el caso de que se quiera obtener una letra para los síntomas
switch (letra) {
case 'F':
case 'f':
letra = 'F';
return letra;
case 'S':
case 's':
letra = 'S';
return letra;
case 'T':
case 't':
letra = 'T';
return letra;
case 'M':
case 'm':
letra = 'M';
return letra;
case 'N':
case 'n':
letra = 'L';
return letra;
default:
fprintf (stdout ,"Invalid option \n");
break;
}
}
if ((letra == 'R') || (letra == 'r') || (letra == 'S') || (letra == 's') || (letra == 'D') || (letra == 'd') || (letra == 'P') || (letra == 'p') || (letra == 'L') || (letra == 'l') || (letra == 'X') || (letra == 'x')) {
//Para el caso de que se quiera obtener una letra para el menú
switch (letra) {
case 'R':
case 'r':
letra = 'R';
return letra;
case 'S':
case 's':
letra = 'S';
return letra;
case 'D':
case 'd':
letra = 'T';
return letra;
case 'P':
case 'p':
letra = 'P';
return letra;
case 'L':
case 'l':
letra = 'L';
return letra;
default:
fprintf (stdout ,"Invalid option \n");
break;
}
}
} while (valores !=1); //El bucle se va a repetir siempre y cuando se introduzcan varios elementos (!= 1) o cuando no se introduzca ninguna de las letras deseadas, siendo ese el caso en el que la funcion entrara en el "else", llegando a un break y volviendo a pedir una letra, mostrando nuevamente el mensaje de invitacion
return letra;
}
int verify_dni (char *cadena) { //FUNCION VERIFY
int longitud;
int i;
longitud = strlen(cadena);
if (longitud == 9) { //COMPRUEBA SI LA LONGITUD DEL DNI ES 9
return 1;
}
else {
return 0;
}
for (i = 0; i <= 7; i++) {
if (cadena[i] >= '0' && cadena[i] <= '9') { //COMPRUEBA SI LOS 8 PRIMEROS CARÁCTERES SON NUMEROS
return 1;
}
else {
return 0;
}
for (i = 8; i < 9; i++) {
if (cadena[i] >= 'A' && cadena[i] <= 'Z') { //COMPRUEBA SI EL ÚLTIMO CARÁCTER ES UNA LETRA
return 1;
}
else {
return 0;
}
}
}
}
void display_patient (struct unPaciente *tabla ,int numero) { //el numero pasado a la funcion va a indicar la informacion de que paciente se desea mostrar (indice)
fprintf (stdout, "> %s ; %s ; %d ; %d ; %d ; %c \n" ,tabla[numero].nombre ,tabla[numero].dni ,tabla[numero].edad ,tabla[numero].tos ,tabla[numero].fiebre ,tabla[numero].sintomas);
return;
}
get_caracter (char mensaje, char *comprobacion) {
char letra;
char extra[256]; //cadena extra para comprobar si se introducen algo más que el número
char i;
int longitud, valores;
mensaje = (char *) malloc (256*sizeof(char));
do {
fprintf (stdout, "%s" ,mensaje); //Se imprime el mensaje de invitacion al usuario recibida como parametro
fprintf (stdout ,"%s" ,comprobacion); //Se imprime la cadena de comprobacion recibida como parametro
fscanf (stdin, "%c" ,&letra); //Se escanea el input del usuario
valores = sscanf (letra ,"%c %s" ,&letra ,extra); //Se le asigna a valores un numero en funcion del numero de elementos introducidos, si es distinto de 1, dará error
} while (valores != 1);
longitud = strlen(comprobacion);
comprobacion = (char *) malloc (longitud*sizeof(char));
for (i = 0; i <= longitud; i++) {
if (letra = comprobacion[i]) { //Se revisan todos los elementos de la cadena de comprobacion, si hay un elemento que coincida, se devuelve esa letra
return letra;
}
else {
fprintf (stdout ,"%s" ,comprobacion);
continue;
}
}
}
和 inout.h,以及 inout.c 中函数的原型
#ifndef INOUT_H
#define INOUT_H
//DECLARACIONES DE LAS FUNCIONES fuera del menú
struct unPaciente {
char nombre[25];
char dni[10];
unsigned short edad;
int fiebre;
int tos;
char sintomas;
}losPacientes[100];
void stripe (char caracter, int numchar);
void headline (char * APLICACION ,char caracterhl, int numchar); // Funcion headline. Imprime una cadena centrada, entre 2 caracteres dados por el usuario.
int yes_or_no ();
void get_string(char *mensaje,int min, int max, char*la_cadena);
int get_integer (char *mensaje, int min, int max);
char get_character (char *mensaje, char *comprobacion);
void display_patient (struct unPaciente *tabla,int numero);
#endif
每个.h 都以#ifndef 和#endif 开头和结尾,database.c 正在读取这些文件,我假设它们的原型与database.c 中的原型冲突,但我不知道为什么。有人告诉我,删除每个标题中的“struct unPaciente”的多个副本可以解决问题,但我仍然得到相同的结果。
解决方案
这个看似自相矛盾的错误信息......
database.c:21:5: error: conflicting types for ‘p_register’ 21 | int p_register (struct unPaciente *tabla, int *numero) { | ^~~~~~~~~~ In file included from database.c:11: database.h:20:5: note: previous declaration of ‘p_register’ was here 20 | int p_register (struct unPaciente *tabla, int *numero);
...试图告诉您struct unPaciente
其中一个声明中的类型与另一个声明中的类型不同。
为什么?因为database.h
本身不是结构定义所在的#include
header ,并且因为包含before ,所以前者也看不到后者的结构声明。在这种情况下,函数原型内部的声明提供了一个作为不完整结构类型的隐式声明,并且该隐式声明的作用域为原型,因此它与后来从 引入的文件范围声明分离。inout.h
database.c
database.h
inout.h
struct unPaciente *tabla
struct unPaciente
inout.h
最好的办法是database.h
包含inout.h
它自己。更一般地说,每个源文件,包括头文件,都应该包括提供数据类型和引用的函数所需的所有头文件。通过在每个标头中正确使用包含保护,正如您所看到的那样,生成相同标头的多个包含没有问题,并且它使您的标头包含的顺序无关。
推荐阅读
- yii2 - Yii2 ActiveRecord 在急切加载后获得新关系
- fiware - FIWARE Cygnus 无法在 HDFSink 中持续存在
- ios - Swift:CMAuthorizationStatus 更改的侦听器
- android - InputField 中的长字符串在存储时被剪切
- powershell - PowerShell 压缩消息字符串输出
- java - 将 JTextPane 字符串添加到 JComboBox
- animation - 是否可以在 .jpg 中“隐藏”一个 .gif?
- c++ - Q 矩阵单元之间的最短路径
- sql - 选择列表中带有函数调用的 ORDER BY 子句的性能问题
- python - OpenCV - 检测颜色范围并在控制台上显示