Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C: C90: Sama data kahdella eri nimellä

Puhveli [13.03.2016 17:40:15]

#

Nyt pitäisi valita monesta pahasta mieleisin, mutta C90:n puitteissa on pysyttävä.

Käytössä on kokoelma funktioita, jotka operoivat 2-ulotteislla vektoreilla:

/* 2-ulotteisen vektorin määrittely yleistettynä: */
typedef struct
{
    float x, y;
} Vektori;

/* Vektoreita tai vektoripointtereita käytetään tietotyyppien määrittelyissä, esim: */
typedef struct
{
    Vektori *p[2];
} PointteriJana;

Kuvaan vektoreilla mm. sijaintia 2-ulotteisessa koordinaatistossa. Sovellusalueessa on kuitenkin huomattavasti mielekkäämpää ilmoittaa sijainti X- ja Z-koordinaatein (haluan täsmentää, mitä useampiulottuvuuksisen koordinaatiston akseleita tarkoitan).

Kuinkahan tämän solmun saisi auki?

1. Voin uudelleennimetä "matikkakirjaston" vektorimäärittelyn X-Z-muotoiseksi, mutta tämä taas sotii yleisemmän ja todennäköisemmän käyttötarkoituksen kanssa (jossa X-Y-vektorit ovat järkevämpiä).

2. Voin kuvata vektorin mukavan kantaaottamattomalla yksiulotteisella taulukolla, mutta alkuperäinen ongelma, koordinaattiakselien yksilöinti, ei siitä mihinkään poistuisi.

3. Voin määritellä uuden X-Z-muotoisen vektorin ja tehdä sille kopiot alkuperäisistä funktioista, mutta tämä on hölmöä monesta syystä (funktioita on pirusti, binääri tulisi olemaan kummallekin versiolle täysin sama, huollettavuus...)

4. Voin laittaa kaiken maailman funktiot ja PointteriJanat syömään voidia vektoripointtereiden sijasta ja hyvinkin castailla "matikkakirjaston" sisällä, piilossa tuomitsevilta katseilta, mutta esim. pointterityyppien kanssa tulee myös varsinaisen loppusovellukseen rumaa ja lukemista hankaloittavaa castailua.

5. Voin käyttää unionia, mutta koska nimettömiä unioneita ei C90:ssä vielä tueta (C11 ei ole vaihtoehto), syntyy tästä ruohonjuuritason tietotyypille sopimatonta ketjutusta:

PointteriJana jana;
jana.xy_koordinaatit.p[0]->y == jana.xz_koordinaatit.p[0]->z;

/* etenkin kun päästään yhtään pidemmälle: */
PointteriPolygoni polygoni;
polygoni.xz_janat.jana[0]->xz_koordinaatit.p[0]...

Tämä YouTube-video havainnollistanee esittämääni kvintilemmaa.

Mitä kommentteja tai tapoja jengille tulee mieleen? Itse en osannut vaihtoehdoista selvää voittajaa löytää. Ujosti kutittelisi toi kolmosvaihtoehdon funktioiden kopiointi, vaikka koko ajatukselle jokainen itseäänkunnioittava enterprise-insinööri varmaan tykkää oksentaa.

tl;dr: Mikä on fiksuin / luettavin / vähiten hirveä tapa käpistellä samaa dataa usealla eri nimellä C90:ssä.

Grez [13.03.2016 18:38:24]

#

Mun mielestä vaan nimeät sen sun Z-akselin Y-akseliksi ja sillä hyvä. Omaan korvaan kuulostaa melkein yhtä turhalta ongelmalta, kuin jos mulla olisi merkkijonomuuttujat a ja c ja harmittelisin kun compare ottaa parametreiksi a ja b :D

Sovelluksen käyttöliittymässä voit toki laittaa X ja Z vaikka ohjelman sisäisesti ne olisivatkin X ja Y.

Puhveli kirjoitti:

Sovellusalueessa on kuitenkin huomattavasti mielekkäämpää ilmoittaa sijainti X- ja Z-koordinaatein (haluan täsmentää, mitä useampiulottuvuuksisen koordinaatiston akseleita tarkoitan).

Eikös noi eri katselukulmasta ole kuitenkin X ja Y-koordinaatit.

Metabolix [13.03.2016 18:50:25]

#

Jos yhdessä ohjelmassa käytetään vain xy- tai xz-koordinaatistoa, ongelma ratkeaa melko helposti vain otsikkotiedostolla, jossa on y:n sijaan z. Funktiot voivat olla edelleen samat, ja jos sattuu olemaan y jossain funktion nimessä, voi ohjata z-version siihen #definellä.

/* kirjasto_xz.h */

/* jäsenille uudet nimet: */
typedef struct {
  float x, z;
} Vektori;

/* samat funktiot käyvät: */
extern void skaalaa(Vektori* v, float kerroin);

/* y-funktioille #define tai staattinen tynkä: */
extern void skaalaa_y(Vektori* v, float kerroin);
#if 0
  #define skaalaa_z skaalaa_y
#else
  static void skaalaa_z(Vektori* v, float kerroin) {
    skaalaa_y(v, kerroin);
  }
#endif

Myös Grezin ehdotus on yleensä hyvä.

Puhveli [13.03.2016 18:56:57]

#

Heti alkuun haluaisin ilmaista vastalauseeni ohjelmointiputkassa vallitsevaan tiukkaan moderointiin. Tarkasti mietitty ja näkyvyyden maksimoimiseksi optimoitu threadiotsikko on omavaltaisesti muutettu laimeaksi ja työturvalliseksi.

Mut joo, Grezin uudelleennimeäminen on jotenkin karvas vaihtoehto. Tuntuu jotenkin kerettiläiseltä kirjotella tasogeometrialaskelmia nimenomaan XZ-tasolle, vaikkei se tarkasti ottaen missään kiellettyä ole.

Tuntuu että yleisin ratkasu tähän (vaikka joku Vec2f) on tarjota koko romu []-operaattorilla käsiteltäväksi niin kuin mikä tahansa sunnuntaitaulukko.

Grez kirjoitti:

Eikös noi eri katselukulmasta ole kuitenkin X ja Y-koordinaatit

EDIT: Tässä tapauksessa vähän huono, kun noi 2-ulotteiset vektorit oikeastaan määrittelee äärettömän korkeita tasoja, joten se Z-koordinaatti on ihan merkityksellinen.

Vaan tuo Metabolixin headeriajatus sopii tähän loistavasti. Kiitos, eipä tullut itselle edes mieleen. Törmäyksiäkään ei tule; hakee vain sen headerin ensin, kummasta mallista sattuu milläkin hetkellä enemmän kiksejä saamaan. Tuskin samassa kooditiedostossa molempia tulee tarvittua.

Btw, näköjään osaa putka päivittää threadia lennossa; ilmestyvät uudet viestit hienosti kesken oman romaanin nakuttelun, ja vielä eeppisen fade in -efektin kanssa. Tää on nyt sitä tulevaisuutta!

EDIT: Tähän hätään löytyi hyvä ratkaisu, mutta aihe kiinnostaa yhä. Antakaa vaan tulla jos lisää ehdotuksia plopsahtaa mieleen. Esimerkiksi 3-ulotteinen vektori on usein hyvä X-Y-Z:na, mutta U-V-W on myös oikein muikea ja tarpeellinen esitys esimerkiksi tekstuurikoordinaateille.

Grez [13.03.2016 19:54:38]

#

Puhveli kirjoitti:

Heti alkuun haluaisin ilmaista vastalauseeni ohjelmointiputkassa vallitsevaan tiukkaan moderointiin. Tarkasti mietitty ja näkyvyyden maksimoimiseksi optimoitu threadiotsikko on omavaltaisesti muutettu laimeaksi ja työturvalliseksi.

Tossa näkyvyyden maksimoimisessa oot yksinkertaisesti vaan väärässä. Alkuperäinen "Koordinaati Ongelma ??? apua" on kyllä siinäkin suhteessa huono.

Oikeastaan ainoa hyvä puoli tuossa otsikossa olisi ollut, että jos viestin olisi sattunut siitä huolimatta avaamaan, olisi yllättynyt positiivisesti :D

Puhveli [13.03.2016 22:02:11]

#

Kiitos, se oli kauniisti sanottu :')

Vastaan Terry A. Davisiä lainaten:

lainaus:

Anyway, uh...

Meinasin nimittäin unohtaa, että valmis toimiva ratkaisu on hyvän tavan mukaista ihan rautalangasta vääntäen pasteta samaan ketjuun jälkipolvia varten, etenkin kun se on toteutettavissa yllättävän vähällä ylimääräisellä koodilla. Sillä vaikka kuljet sa härmän mies polkusi määrään, sua seuravi toiset, taas toiset jäljissään. Ah elon kaaren jatkuvuutta!

vektori.h

#ifndef _VEKTORI_H
#define _VEKTORI_H

/* Määrittele oletus, jos sitä ei ole jo muualla määritelty: */
#ifndef _VEKTORI_XZ_H
typedef struct
{
    float x, y;
} Vektori;
#endif

/* Varsinainen headeri, jossa kaikki
   funktioiden ja muiden tyyppien esittelyt: */
void normalisoi_vektori(Vektori *v);
jne...

#endif

vektori_xz.h

#ifndef _VEKTORI_H
#define _VEKTORI_XZ_H

/* Poikkeava esitys: */
typedef struct
{
   float x, z;
} Vektori;

/* Muut esittelyt käyvät sellaisenaan, niitä ei
   suotta tarvitse edes externinä uusiksi luetella: */
#include "vektori.h"

#endif

Näistä siis jompi kumpi #includella mukaan riippuen siitä, kumpaa "sanamuotoa" siitä jälkimmäisestä muuttujasta halutaan käyttää. Samat funktiot käyvät.

#include "vektori.h"

Vektori v; /* { X, Y } */
v.y = 4.2f;

normalisoi_vektori(&v);
#include "vektori_xz.h"

Vektori v; /* { X, Z } */
v.z = 4.2f;

normalisoi_vektori(&v);

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta