Structures

BasicC

Erfahrenes Mitglied
Hey Leute,
bin wieder zurück :)
Also hab mir echt mühe gegeben, komme nicht mehr weiter.
Es ist diesmal etwas aufwendig durch zuschauen Ihr habt gesagt ihr wollt erstmal was sehen :)

vector.c-Datei (main)
C:
#include <stdlib.h>

#include <stdio.h>



#include "vec_funcs.h"

#include "vec_testers.h"



int main() {



   enum { MAXV  = 30 };    /* Maximalzahl array-Elemente/Test-Vektoren */



   vector_t vectors[MAXV]; /* array der eingelesen Testvektoren */

   int nv;                 /* Anzahl eingelesener Vektoren */

   char infilename [] = "/Users/************/Desktop/INF 1/INF 1/Übg 6/A6_Rumpf/testvectors.dat";



   printf("\n3D-Vektorrechnung\n");

   printf("=================\n\n");



   /* Test-Vektoren einlesen und speichern */

   nv = vec_read(infilename, vectors, MAXV);

   if (nv <= 0) return 1;



   /* b) Kontroll-Ausgabe der Test-Vektoren */

   test_vec_out(vectors, nv);



   /*************************************************************

    * 1) Verwendung aller definierten Vektor-Funktionen

    *************************************************************/



   printf("=== Funktionsaufrufe mit Test-Vektoren ===\n\n");



   /* c) Betrag/Norm */

   test_vec_norm(vectors, nv);



   /* d) Vektoraddition */

   test_vec_add(vectors, nv);



   /* e) Mult. mit Skalar */

   test_vec_smul(vectors, nv);



   /* f) Vergleich */

   test_vec_equal(vectors, nv);



   /* g) Skalarprodukt */

   test_vec_dotp(vectors, nv);



   /* h) Kreuzprodukt */

   test_vec_crossp(vectors, nv);



   /* i) Winkel */

   test_vec_angle(vectors, nv);



   printf("\n");

   return 0;

}

vec_funcs.c - Funktionsdatei
C:
#include "vec_funcs.h"



/***********************************************************************/



int vec_read(char *infilename, vector_t vectors[], const int MAXV) {

   /* liest Vektoren von Datei in struct-array vectors ein,

    * gibt Anzahl gelesener Vektoren zurück */



   FILE *infile;

   double c1, c2, c3;

   int nv = 0;



   /* Eingabedatei oeffnen und pruefen */

   if ((infile = fopen(infilename, "r")) == NULL) {

      fprintf(stderr, " *** Fehler: Kann '%s' nicht zum Lesen oeffnen!\n",

              infilename);

      return 0;

   }



   /* Schleife ueber alle Test-Vektoren(je 3 doubles), speichern */

   while (fscanf(infile, "%lf %lf %lf", &c1, &c2, &c3) == 3) {

      if (nv >= MAXV) {    /* Feldgroesse absichern */

        fprintf(stderr,

                " *** Hinweis: Mehr als %d Testvektoren auf der Datei!\n", MAXV);

        break;

      }

      vectors[nv] = vec_gen(c1, c2, c3);

      nv++;

   }



   /* Eingabedatei schliessen und Kontrollmeldung */

   fclose(infile);

   printf("Es wurden %d Testvektoren eingelesen.\n\n", nv);



   return nv;

}



/***********************************************************************/



vector_t vec_gen(const double xcoord,

                const double ycoord,

                const double zcoord) {

   /* erzeugt einen Ortsvektor aus drei kartesischen Koordinaten */



   vector_t vec;

    vec.x=xcoord;

    vec.y=ycoord;

    vec.z=zcoord;



   return vec;

}



/***********************************************************************/



void vec_out(const vector_t a) {

   /* gibt einen Ortsvektor formatiert nach stdout aus */

    printf(" %4.3lf %4.3lf %4.3lf\n",a.x,a.y,a.z);



}



/***********************************************************************/



void vec_out_idx(vector_t vectors[], const int idx) {

   /* gibt ein Element des Vektor-Feldes mit

    * Index formatiert nach stdout aus */



   printf("%3d:", idx);

   vec_out(vectors[idx]);

}



/***********************************************************************/



double vec_norm(const vector_t a) {

   /* Betrag/Norm eines Vektors */



   double norm = 0.;

    norm = sqrt(a.x*a.x + a.y*a.y + a.z*a.z);





   return norm;

}



/***********************************************************************/



vector_t vec_add(const vector_t a, const vector_t b) {

   /* Addiert zwei Ortsvektoren */

  

   vector_t vsum;

    vsum.x = a.x + b.x;

    vsum.y = a.y + b.y;

    vsum.z = a.z + b.z;

  



   return vsum;

}



/***********************************************************************/



vector_t vec_smul(const vector_t a, double f) {

    /* Multiplikation zweier Vektoren */

  

    vector_t vsmul;

    vsmul.x = a.x*f;

    vsmul.y = a.y*f;

    vsmul.z = a.z*f;

  

    return vsmul;



}



/***********************************************************************/

vector_t vec_equal(const vector_t a);



 /***********************************************************************/



vector_t vec_dotp(const vector_t a, const vector_t b) {

    double vskal2;

    vector_t vskal;

  

    vskal.x = a.x * b.x;

    vskal.y = a.y * b.y;

    vskal.z = a.z * b.z;

  

    vskal2 =vskal.x+vskal.y+vskal.z;

    return vskal;

}

vec_funcs.h - Datei
C:
#ifndef VEC_FUNCS_H

#define VEC_FUNCS_H
#include <stdlib.h>

#include <stdio.h>

#include <math.h>



/* Struktur zur Definition eines 3D-Punktes/Ortsvektors */

typedef struct {

    double x,y,z;

  



} vector_t;



int vec_read(char *infilename, vector_t vectors[], const int MAXV);

/* liest Vektoren von Datei in struct-array vectors ein,

 * gibt Anzahl gelesener Vektoren zurück */



vector_t vec_gen(const double x, const double y, const double z);

/* erzeugt einen Ortsvektor aus drei kartesischen Koordinaten */



void vec_out(const vector_t a);

/* gibt einen Ortsvektor formatiert nach stdout aus */



void vec_out_idx(vector_t vectors[], const int idx);

/* gibt ein Element des Vektor-Feldes mit Index formatiert nach stdout aus */



double vec_norm(const vector_t a);

/* Betrag/Norm eines Vektors */



vector_t vec_add(const vector_t a, const vector_t b);

/* Addiert zwei Ortsvektoren */



vector_t vec_smul(const vector_t a, double f);

/* Multiplikation eines Vektors */











#endif

vec_testers.c - Datei
C:
#include "vec_testers.h"



/***********************************************************************/



void test_vec_out(vector_t vectors[], const int nv) {

   /* c) Test-Ausgabe Vektoren */



   int i;



   printf("=== Kontroll-Ausgabe eingelesener Test-Vektoren ===\n\n");

   for (i = 0; i < nv; i++) {

      vec_out_idx(vectors, i);

      printf("\n");

   }

   printf("\n");

}



/***********************************************************************/



void test_vec_norm(vector_t vectors[], const int nv) {

   /* c) Test-Ausgabe Betrag/Norm eines Vektors */



   int i;



   printf("Betrag:\n");

   printf("-------\n");

   for (i = 0; i < nv; i++) {

      vec_out_idx(vectors, i);

      printf(" ==> %3.3f\n", vec_norm(vectors[i]));

   }

   printf("\n");

}



/***********************************************************************/



void test_vec_add(vector_t vectors[], const int nv) {

   /* d) Test-Ausgabe Betrag/Norm eines Vektors */



   int i;



   printf("Vektoraddition:\n");

   printf("---------------\n");

   for (i = 0; i < nv - 1; i++) {

      vec_out_idx(vectors, i);

      printf(" +\n");

      vec_out_idx(vectors, i + 1);

      printf(" ==> ");

      vec_out(vec_add(vectors[i], vectors[i + 1]));

      printf("\n");

   }

   printf("\n");

}



/***********************************************************************/



void test_vec_smul(vector_t vectors[], const int nv) {

   /* e) Test-Ausgabe Skalar mult. mit Vektor */

   int i;

   printf("Skalar(eigener Betrag) * Vektor:\n");

   printf("--------------------------------\n");

   for (i = 0; i < nv - 1; i++) {

        vec_out_idx(vectors, i);

        printf(" ==> ");

        vec_out(vec_smul(vectors[i]),double 3));

        printf("\n");

    }

}



/***********************************************************************/



void test_vec_equal(vector_t vectors[], const int nv) {

   /* f) Test-Ausgabe Vergleich zweier Vektoren */



   printf("Vergleichen:\n");

   printf("------------\n");

  

  



 



   printf("\n");

}



/***********************************************************************/



void test_vec_dotp(vector_t vectors[], const int nv) {

   /* g) Test-Ausgabe Skalarprodukt */



   printf("Skalarprodukt:\n");

   printf("--------------\n");

    for (i = 0; i < nv - 1; i++) {

        vec_out_idx(vectors, i);

        printf(" ==> ");

        vec_out(vec_smul(vectors[i]),double 3);

        printf("\n");

   printf("\n");

}



/***********************************************************************/



void test_vec_crossp(vector_t vectors[], const int nv) {

   /* h) Test-Ausgabe Kreuzprodukt */



   printf("Kreuzprodukt:\n");

   printf("-------------\n");



  



   printf("\n");

}



/***********************************************************************/



void test_vec_angle(vector_t vectors[], const int nv) {

   /* i) Test-Ausgabe eingeschlossener Winkel */



   printf("eingeschlossener Winkel:\n");

   printf("------------------------\n");



  



   printf("\n");

}



/***********************************************************************/

vec_testers.h
C:
#ifndef VEC_TESTERS_H

#define VEC_TESTERS_H
#include <stdlib.h>

#include <stdio.h>

#include <math.h>



#include "vec_funcs.h"



void test_vec_out(vector_t vectors[], const int nv);

/* b) Test-Ausgabe Vektoren */



void test_vec_norm(vector_t vectors[], const int nv);

/* c) Test-Ausgabe Betrag/Norm eines Vektors */



void test_vec_add(vector_t vectors[], const int nv);

/* d) Test-Ausgabe Betrag/Norm eines Vektors */



void test_vec_smul(vector_t vectors[], const int nv);

/* e) Test-Ausgabe Skalar mult. mit Vektor */



void test_vec_equal(vector_t vectors[], const int nv);

/* f) Test-Ausgabe Vergleich zweier Vektoren */



void test_vec_dotp(vector_t vectors[], const int nv);

/* g) Test-Ausgabe Skalarprodukt */



void test_vec_crossp(vector_t vectors[], const int nv);

/* h) Test-Ausgabe Kreuzprodukt */



void test_vec_angle(vector_t vectors[], const int nv);

/* i) Test-Ausgabe eingeschlossener Winkel */



#endif

So ich hoffe ihr könnt mir einzelne Stichpunkte geben, wie ich weiter arbeiten könnte.

Aufgabenstellung :

1. Schreiben Sie ein Hauptprogramm, das Triplets von doubles von der Eingabedatei testvectors.dat bis EOF liest, daraus je einen vector_t [siehe a)] erzeugt, diese in ei- nem array von Strukturen speichert und dann testweise alle u. g. Funktionen verwendet. Für jede neu geschriebene Funktion sollte im Hauptprogramm ein Block zur Kontrollaus- gabe implementiert werden, der für alle Vektoren im array den/die Eingabevektor(en) mit dem Ergebnis des jeweiligen Funktionsaufrufes zeigt. Addieren Sie z.B. für den Test der Funktion aus d) in einer Schleife über alle Vektoren den jeweils i-ten mit dem i+1-ten Vektor.
[Beachten Sie, dass die Eingabewerte insbesondere auch die Grenzfälle (z. B. zwei Vek- toren in einer Ebene, zwei senkrecht aufeinander stehende Vektoren, zwei parallele Vek- toren, Null-Vektor) abdecken, siehe auch i).]

  1. a) Definieren Sie einen geeigneten struct-Datentyp vector_t, der ein 3D-Koordina- tentripel aufnimmt und damit auch als Ortsvektor aufgefasst werden kann.

  2. b) Definieren Sie Funktionen zum Erzeugen (aus drei skalaren doubles) und zur forma- tierten Ausgabe eines vector_t.

  3. c) Definieren Sie eine Funktion für die Berechnung des Betrages (euklidische Länge) ei- nes Ortsvektors.

  4. d) Definieren Sie eine Funktion für die Addition zweier Vektoren.

  5. e) Definieren Sie eine Funktion für die Multiplikation eines Vektors mit einem Skalar (Streckung, d.h. Skalierung der Vektorlänge).

  6. f) Definieren Sie eine Funktion, mit der zwei Ortsvektoren auf Gleichheit überprüft werden können.

  7. g) Definieren Sie Funktionen für das Skalarprodukt (inneres oder Punkt-Produkt, liefert als Ergebnis ein Skalar) und

  8. h) das Kreuzprodukt (äußeres oder Vektor-Produkt, liefert wieder einen Vektor) zweier V ektoren.

  9. i) Definieren Sie eine Funktion zur Ermittlung des eingeschlossenen Winkels zwischen zwei Vektoren unter Verwendung der o. g. Funktionen für den Betrag und das Skalar- produkt (beachten Sie die numerischen Probleme mit der Division und dem Argument des acos()).
 
Zuletzt bearbeitet von einem Moderator:

cwriter

Erfahrenes Mitglied
So ich hoffe ihr könnt mir einzelne Stichpunkte geben, wie ich weiter arbeiten könnte.
Indem du die Funktionen fertig implementierst.

Die Aufgabe scheint eher mit Vektoren als mit C zu tun zu haben. Ist etwas mit den Vektoren unklar? Im Prinzip musst du ja nur Formeln zu Code umwandeln.

Gruss
cwriter
 

BasicC

Erfahrenes Mitglied
Naja zum Beispiel bei dem wo ich Vektoren Vergleichen soll die Formel + die Funktion krieg ich nicht heraus
 

ComFreek

Mod | @comfreek
Moderator
Die Funktion dazu heißt bei dir "test_vec_equal", das sollte recht naheliegend sein, wenn du dir alle Funktionsnamen zusammen ansiehst. Kannst du die Gleichheit zweier Ortsvektoren händisch bestimmen? Wenn ja, hast du deinen Algorithmus; du könntest auch zur Übung einen Algorithmus zur Gleichheit zweier Richtungsvektoren bestimmen.

PS: Bitte [code=c] als Code-Tag nutzen, sonst hast du kein Syntax Highlighting.
 

BasicC

Erfahrenes Mitglied
C:
void test_vec_smul(vector_t vectors[], const int nv) {

   /* e) Test-Ausgabe Skalar mult. mit Vektor */

    int i;

   

   printf("Skalar(eigener Betrag) * Vektor:\n");

   printf("--------------------------------\n");

   for (i = 0; i < nv - 1; i++) {

        vec_out_idx(vectors, i);

        printf(" ==> ");

        vec_out(vec_smul(vectors [i]), double 3));

        printf("\n");

    }

}
[/code=c]

da bei vec_out........ steht als Fehler Too= few arguments to function call, expected 2, have 1
                                                                 Expected expression
 

BasicC

Erfahrenes Mitglied
C:
vector_t vec_angle(const vector_t a, const vector_t b){

    double vector_a;

    double vector_b;

    double angle = vec_dotp(vector_a,vector_b)/(vec_norm(vector_a)*vec_norm(vector_b));

    if (angle <-1.0){

        angle = -1.0;

    }

    if (angle > +1.0){

        angle = +1.0;

    }

    return acos(angle);

Ich weiß ehrlich nicht was daran falsch ist. Was mache ich falsch ?
 
Zuletzt bearbeitet:

cwriter

Erfahrenes Mitglied
Warum normalisiert du den Betrag des Winkels auf 1.0?
Warum definierst du "vector_X" als double? Double ist ein Skalar.
Dazu verwendest du die Uninitialisierten Werte. Würdest du wenigstens auf den Compiler hören? Der wird dir bei diesem Code ja mehrere Warnungen geben.

Gruss
cwriter
 

Technipion

Erfahrenes Mitglied
Hallo Tikorz,
hier ist dein Code mit einigen Anmerkungen.
C++:
// Der Winkel zwischen zwei Vektoren ist ein Skalar...
// Also warum gibst du hier einen Vektor zurück?
vector_t vec_angle(const vector_t a, const vector_t b){

    double vector_a; // vector_a ist eine Gleitkommazahl?? Außerdem: Wofür brauchst du das?
    // Warum so viele Leerzeilen?
    double vector_b; // vector_b ist eine Gleitkommazahl?? Außerdem: Wofür brauchst du das?
  
    double angle = vec_dotp(vector_a,vector_b)/(vec_norm(vector_a)*vec_norm(vector_b));
    /* Du bildest hier das Punktprodukt aus zwei Zahlen!!
    Dann normalisierst du zwei Zahlen?! Das macht keinen Sinn! */

    /* Die Formel ist cos(alpha) = A*B / (|A| * |B|)
    Also liegt der Wert von angle definitiv zwischen -1 und 1 */
    // Korrektur (s.u.): Der Wert kann durch Ungenauigkeiten beim Rechnen auch außerhalb von [-1, 1] liegen.

    if (angle <-1.0){ // Das hier ist also unnötig
                      // Korrektur: Lass es drin. Manchmal kommt es bei der Gleitkomma-Arithmetik zu numerischen Abweichungen.
        angle = -1.0;

    }

    if (angle > +1.0){ // Das hier auch
                       // Korrektur: Lass es drin. Manchmal kommt es bei der Gleitkomma-Arithmetik zu numerischen Abweichungen.
        angle = +1.0;

    }

    return acos(angle); // So gibst du den Winkel in Radians zurück. Willst du vielleicht noch zu Grad konvertieren?

// Wo ist die Funktion zu Ende? Hier fehlt ein }

// Wolltest du nicht einfach a und b benutzen, statt vector_a und vector_b?
Ich sage es dir wie es ist: Dir fehlen Grundlagen! Hol den Stoff bezüglich Typen, Gültigkeitsbereichen (Scopes) und Funktionen nach! Sonst legst du dich in der Klausur hin :(

Gruß Technipion
 
Zuletzt bearbeitet:

ComFreek

Mod | @comfreek
Moderator
@Technipion Das Beschränken der Werte auf [-1, 1] kann numerisch gesehen durchaus sinnvoll sein. "man 3 acos" sagt auf meinem System:
If x is outside the range [-1, 1], a domain error occurs, and a NaN is returned.
Domain error: x is outside the range [-1, 1]: errno is set to EDOM. An invalid floating-point exception (FE_INVALID) is raised.
 

cwriter

Erfahrenes Mitglied
Das Beschränken der Werte auf [-1, 1] kann numerisch gesehen durchaus sinnvoll sein. "man 3 acos" sagt auf meinem System:
Aber dann wäre der Rückgabewert ja NaN, was ohnehin nicht vergleichbar sein dürfte. (/Edit: Das war Quark. Das Problem ist ja, dass acos() einen Definitionsbereich von [-1, 1] hat. Um zu zeigen, dass es kein Problem ist, die Werte direkt einzusetzen, muss gezeigt werden, dass die Eingabe für acos im Betrag nie grösser als 1 ist. So, ab jetzt stimmt es (hoffentlich) wieder :) ) Und da bei A*B / (|A| * |B|) der Zähler nie grösser als der Nenner sein kann, ist der Test schlicht nicht nötig.
(Den Beweis bleibe ich schuldig, aber ich denke, man könnte mit der Unendlichnorm argumentieren). Rundungsfehler passieren hier auch nicht, da selbst bei Subtraktionsrundungen der Zähler nur kleiner werden kann, und der Nenner in der Euklidischen Norm keine Subtraktionen aufweist).

Gruss
cwriter
 
Zuletzt bearbeitet: