Tengo una estructura de datos como esta:
struct foo { int id; int route; int backup_route; int current_route; }
y una función llamada update () que se usa para solicitar cambios en ella.
actualizar (42, dont_care, dont_care, nueva_ruta);
esto es realmente largo y si agrego algo a la estructura, tengo que agregar un 'dont_care' a CADA llamada para actualizar (...).
Estoy pensando en pasarle una estructura en su lugar, pero completar la estructura con 'dont_care' de antemano es aún más tedioso que simplemente deletrearlo en la llamada a la función. ¿Puedo crear la estructura en algún lugar con valores predeterminados de no me importa y simplemente establecer los campos que me importan después de declararlo como una variable local?
struct foo bar = {.id = 42, .ruta_actual = nueva_ruta}; actualizar (& bar);
¿Cuál es la forma más elegante de pasar solo la información que deseo expresar a la función de actualización?
y quiero que todo lo demás esté predeterminado en -1 (el código secreto para 'no me importa')
fuente
PTHREAD_MUTEX_INITIALIZER
usa esto también.Puede cambiar su valor especial secreto a 0 y aprovechar la semántica de miembros de estructura predeterminada de C
luego pasará 0 como miembros de la barra no especificada en el inicializador.
O puede crear una macro que hará la inicialización predeterminada por usted:
fuente
<stdarg.h>
le permite definir funciones variadas (que aceptan un número indefinido de argumentos, comoprintf()
). Definiría una función que toma un número arbitrario de pares de argumentos, uno que especifica la propiedad que se actualizará y otro que especifica el valor. Utilice unaenum
cadena o una para especificar el nombre de la propiedad.fuente
enum
variables alstruct
campo? ¿Codificarlo? Entonces esta función solo será aplicable a específicosstruct
.Quizás considere usar una definición de macro de preprocesador en su lugar:
Si su instancia de (struct foo) es global, entonces no necesita el parámetro para eso, por supuesto. Pero supongo que probablemente tengas más de una instancia. Usar el bloque ({...}) es un GNU-ismo que se aplica a GCC; es una forma agradable (segura) de mantener las líneas juntas como un bloque. Si más adelante necesita agregar más a las macros, como la verificación de validación de rango, no tendrá que preocuparse por romper cosas como declaraciones if / else, etc.
Esto es lo que haría, de acuerdo con los requisitos que indicó. Situaciones como esta son una de las razones por las que comencé a usar mucho Python; el manejo de los parámetros predeterminados se vuelve mucho más simple que nunca con C. (supongo que es un complemento de Python, lo siento ;-)
fuente
Un patrón que usa gobject es una función variable y valores enumerados para cada propiedad. La interfaz se parece a:
Escribir una función varargs es fácil; consulte http://www.eskimo.com/~scs/cclass/int/sx11b.html . Simplemente haga coincidir los pares clave -> valor y establezca los atributos de estructura apropiados.
fuente
Como parece que solo necesita esta estructura para la
update()
función, no use una estructura para esto en absoluto, solo ofuscará su intención detrás de esa construcción. Quizás debería reconsiderar por qué está cambiando y actualizando esos campos y definir funciones o macros separadas para estos "pequeños" cambios.p.ej
O incluso mejor, escriba una función para cada caso de cambio. Como ya notó, no cambia todas las propiedades al mismo tiempo, por lo tanto, haga posible cambiar solo una propiedad a la vez. Esto no solo mejora la legibilidad, sino que también lo ayuda a manejar los diferentes casos, por ejemplo, no tiene que verificar todos los "dont_care" porque sabe que solo se cambia la ruta actual.
fuente
¿Qué tal algo como:
con:
y:
y en consecuencia:
En C ++, un patrón similar tiene un nombre que no recuerdo en este momento.
EDITAR : Se llama el idioma de parámetro con nombre .
fuente
Estoy oxidado con las estructuras, por lo que probablemente me falten algunas palabras clave aquí. Pero, ¿por qué no comenzar con una estructura global con los valores predeterminados inicializados, copiarla en su variable local y luego modificarla?
Un inicializador como:
Luego, cuando quieras usarlo:
fuente
Podría abordar el problema con una X-Macro
Cambiaría la definición de su estructura en:
Y luego podrá definir fácilmente una función flexible que establezca todos los campos en
dont_care
.Siguiendo la discusión aquí , también se podría definir un valor predeterminado de esta manera:
Que se traduce en:
Y utilícelo como en hlovdal answer , con la ventaja de que aquí el mantenimiento es más fácil, es decir, cambiar el número de miembros de la estructura se actualizará automáticamente
foo_DONT_CARE
. Tenga en cuenta que la última coma "falsa" es aceptable .Aprendí por primera vez el concepto de X-Macros cuando tuve que abordar este problema .
Es extremadamente flexible para agregar nuevos campos a la estructura. Si tiene diferentes tipos de datos, puede definir diferentes
dont_care
valores según el tipo de datos: desde aquí , puede inspirarse en la función utilizada para imprimir los valores en el segundo ejemplo.Si está de acuerdo con una
int
estructura all , entonces puede omitir el tipo de datos deLIST_OF_foo_MEMBERS
y simplemente cambiar la función X de la definición de la estructura a#define X(name) int name;
fuente
X
y, por lo general, los agrego_ENTRY
al nombre de la lista, por ejemplo#define LIST_SOMETHING LIST_SOMETHING_ENTRY(a1, a2, aN) \ LIST_SOMETHING_ENTRY(b1, b2, bN) ...
.La forma más elegante sería actualizar los campos de estructura directamente, sin tener que usar la
update()
función, pero tal vez haya buenas razones para usarla que no aparecen en la pregunta.O puede, como sugirió Pukku, crear funciones de acceso independientes para cada campo de la estructura.
De lo contrario, la mejor solución en la que puedo pensar es tratar un valor de '0' en un campo de estructura como un indicador de 'no actualizar', por lo que solo crea una función para devolver una estructura cero y luego usa esto para actualizar.
Sin embargo, esto podría no ser muy factible si 0 es un valor válido para los campos en la estructura.
fuente