Zweidimensionales Array sortieren



  • Hallo,
    ich habe ein zweidimensionales Array, das ich gerne bzgl. einer der Spalten sortieren möchte.

    Alle Werte des Arrays sind long doubles.
    Die Größe des Arrays ist mit ARRAYSIZE vorgegeben.
    Die Dimension des Arrays entspricht "channels".

    Die Sortierung des Arrays soll aufsteigend oder absteigend hinsichtlich channel 3 stattfinden.

    Hierbei ist:
    #define ARRAYSIZE 50 // Anzahl der zu mittelnden Messwerte...könnte später größer werden...

    int channels = 4; // evtl. kann im späteren Verlauf noch ein channel hinzu kommen
    long double tmpch[4]; // tmp-array - one value each channel

    Bisher hatte ich versucht, die Sortierung relativ einfach mit C durchzuführen:

    if (pet == ARRAYSIZE-1) // if actual position = end of array
    	{
    		for (int i=0; i<ARRAYSIZE-1; i++)	// check all values
    		{
    
    			if (messwerte[3][i] > messwerte[3][i+1]) // arrange by channel 3
    			{
    				for (int chan=0; chan < channels-1; chan++)
    				{
    					tmpch[chan] = messwerte[chan][i+1];
    					messwerte[chan][i+1] = messwerte[chan][i];
    					messwerte[chan][i] = tmpch[chan];
    				}
    				if (i >= 1)
    					{
    						i--;
    					}
    				printf("i=%d\n",i);
    			}
    		}
    		printf("\n\nFINISHED\n\n");
    	}
    
    }	// end of endless for-loop
    

    Ich denke jedoch, dass das ne Menge Overhead erzeugt. Außerdem klappt das noch nicht so ganz.
    Da ich jedoch meine ersten Gehversuche in C++ machen möchte, wurde mir geraten, mir die Sortierung unter C++ anzusehen.
    Kann mir vielleicht jemand ein Beispiel zur Sortierung unter C++ nennen? Oder mir Suchbegriffe für Google an den Kopf werfen?



  • Cysign schrieb:

    #define ARRAYSIZE 50 // Anzahl der zu mittelnden Messwerte...könnte später größer werden...

    Als erstes solltest du dir std::vector ansehen, damit geht alles viel einfacher.

    typedef std::vector<double> channel;
    std::vector<channel> messwerte;
    // messwerte füllen mit push_back(...)
    std::sort(messwerte.begin(), messwerte.end());
    


  • Hi,
    du bist im falschen Forum gelandet, du machst ja C.


  • Mod

    Da du fragst, wie das in C++ besser geht:

    #include <iostream>
    #include <array>
    #include <algorithm>
    
    using namespace std;
    
    template <typename ElementType, size_t compare_column> 
    bool compare_by_column(ElementType const &lhs, ElementType const &rhs)
    {
      return lhs[compare_column] < rhs[compare_column];
    }
    
    int main()
    {
      array<array<int, 3>, 4> foo = {{{{1,6,8}},{{4,2,7}},{{8,3,1}},{{9,3,4}}}};
    
      cout << "Vorher:\n";
      for (auto zeile : foo)
        {
          for (auto eintrag: zeile)
            cout << eintrag << ' ';
          cout << '\n';
        }
    
      sort(foo.begin(), foo.end(), compare_by_column<array<int, 3>, 1>);
      cout << "\nNach zweiter Spalte sortiert:\n";
      for (auto zeile : foo)
        {
          for (auto eintrag: zeile)
            cout << eintrag << ' ';
          cout << '\n';
        }
    }
    

    Das ginge übrigens auch in C wesentlich schöner. Nutze die Standardbibliothek! qsort bietet sich an.



  • Da der Code des TE nicht C++, sondern C zu sein scheint -- in C ginge das beispielsweise so:

    #include <stdio.h>
    #include <stdlib.h>
    
    int compare_channel3(void const *lhs_v, void const *rhs_v) {
      double const *lhs = (double const *) lhs_v;
      double const *rhs = (double const *) rhs_v;
    
      return lhs[3] < rhs[3] ? -1 : (lhs[3] > rhs[3] ? 1 : 0);
    }
    
    int main(void) {
      int i;
      double werte[][4] = {
        { 1, 2, 3, 4 },
        { 3, 1, 4, 1 },
        { 1, 1, 2, 3 },
        { 1, 4, 1, 2 },
        { 2, 3, 4, 5 }
      };
    
      qsort(werte, 5, sizeof(werte[0]), compare_channel3); /* <-- hier. */
    
      for(i = 0; i < 5; ++i) {
        printf("%f %f %f %f\n", werte[i][0], werte[i][1], werte[i][2], werte[i][3]);
      }
    
      return 0;
    }
    


  • Man kann auch eine Indexmenge sortieren und die "Vertauschungen" erst am Ende vornehmen.



  • Danke für die schnelle Hilfe.

    "qsort" habe ich mir vorhin angesehen, aber damit hab ichs nicht hinbekommen.
    Da gabs ein undefinierbares Programmverhalten (nicht sortiert, komischer Wert, der weit über 300 Stellen hatte - das konnte kein long double mehr sein :D). Da ich jedoch nicht wusste, wie ich den Fehler eingrenzen konnte und kein Beispiel anhand eines mehrdimensionalen Arrays fand, hatte ichs mit meinem Codefetzen versucht.

    Dann will ich doch mal schaun, ob ich das hiermit gelöst bekomme 🙂



  • Hmmm...so ganz einfach ists für mich immer noch nicht.
    Die C-Variante spuckt Werte aus, die nicht so ganz meiner Vorstellung entsprechen:

    n: 2091: 	1669.000000	9783.000000	95.683952	180.000421
    n: 2091: 	1082.000000	9783.000000	95.586549	180.000421
    n: 2091: 	998.000000	9842.000000	95.810003	180.115012
    n: 2091: 	496.000000	9820.000000	95.701141	179.903018
    n: 2091: 	389.000000	9797.000000	95.626656	179.903018
    n: 2091: 	897.000000	9812.000000	95.534983	179.943125
    n: 2091: 	1016.000000	9797.000000	95.758436	179.845722
    n: 2091: 	1585.000000	9820.000000	96.021997	179.662376
    n: 2091: 	1729.000000	9775.000000	95.981890	179.903018
    n: 2091: 	1118.000000	9775.000000	95.981890	179.903018
    n: 2091: 	1183.000000	9797.000000	95.758436	179.834263
    n: 2091: 	597.000000	9842.000000	95.477687	179.943125
    n: 2091: 	1957.000000	9790.000000	95.758436	179.943125
    n: 2091: 	1747.000000	9775.000000	96.188155	179.834263
    n: 2091: 	1979.000000	9827.000000	95.643845	179.943125
    n: 2091: 	101.000000	9820.000000	95.850110	179.834263
    n: 2091: 	956.000000	9768.000000	95.867298	179.903018
    n: 2091: 	59.000000	9783.000000	95.964701	179.834263
    n: 2091: 	664.000000	9834.000000	95.575090	179.903018
    n: 2091: 	1251.000000	9775.000000	95.701141	179.943125
    n: 2091: 	221.000000	9768.000000	95.907405	179.845722
    n: 2091: 	203.000000	9797.000000	95.586549	180.212415
    n: 2091: 	974.000000	9797.000000	96.073563	179.845722
    n: 2091: 	622.000000	9805.000000	95.850110	179.903018
    n: 2091: 	453.000000	9761.000000	95.981890	179.553514
    n: 2091: 	329.000000	9783.000000	95.810003	179.845722
    n: 2091: 	2023.000000	9856.000000	95.683952	180.172308
    n: 2091: 	77.000000	9797.000000	95.810003	180.115012
    n: 2091: 	724.000000	9753.000000	96.033456	179.776967
    n: 2091: 	892.000000	9761.000000	95.420391	179.903018
    n: 2091: 	910.000000	9797.000000	95.810003	180.000421
    n: 2091: 	1413.000000	9878.000000	95.683952	180.097824
    n: 2091: 	1100.000000	9797.000000	95.850110	179.736860
    n: 2091: 	790.000000	9849.000000	95.643845	180.000421
    n: 2091: 	868.000000	9775.000000	95.701141	179.834263
    n: 2091: 	514.000000	9702.000000	96.130859	179.553514
    n: 2091: 	1160.000000	9768.000000	95.964701	179.845722
    n: 2091: 	1142.000000	9820.000000	95.867298	179.845722
    n: 2091: 	1999.000000	9790.000000	96.073563	179.662376
    n: 2091: 	933.000000	9805.000000	95.850110	179.834263
    n: 2091: 	598.000000	9761.000000	95.964701	179.943125
    n: 2091: 	748.000000	9812.000000	95.586549	179.943125
    n: 2091: 	1915.000000	9783.000000	95.683952	179.903018
    n: 2091: 	1201.000000	9805.000000	95.758436	179.943125
    n: 2091: 	1058.000000	9775.000000	96.073563	179.553514
    n: 2091: 	1040.000000	9886.000000	95.363095	180.212415
    n: 2091: 	183.000000	9775.000000	95.420391	179.845722
    n: 2091: 	808.000000	9775.000000	95.964701	179.834263
    n: 2091: 	766.000000	9790.000000	95.850110	179.903018
    
    Sortiert!
    
    int compare_chan3(void const *lhs_v, void const *rhs_v) {
      double const *lhs = (double const *) lhs_v;
      double const *rhs = (double const *) rhs_v;
    
      return lhs[3] < rhs[3] ? -1 : (lhs[3] > rhs[3] ? 1 : 0);
    }
    
    for (;;)			// read sensor data & save to array - endless loop
    {
    	usleep(SLEEPVALUE);
    	std::vector<int> values;
    	CHECK_OAK_CALL(readInterruptReport(deviceHandle, values));
    
    	const double mult2 = 180 / M_PI * pow(10.00, channelInfos[2].unitExponent);
    	const double mult3 = 180 / M_PI * pow(10.00, channelInfos[3].unitExponent);
    	messwerte[0][pet] = values[0];
    	messwerte[1][pet] = values[1];
    	messwerte[2][pet] = values[2] * mult2;
    	messwerte[3][pet] = values[3] * mult3;
    //	messwerte[4][pet] = // Logging der Temperatur - wie auslesen???
    
    				// For analyzing realtime data uncomment lines
    //	printf("Ch0:\t%.2Lf\n", messwerte[0][pet]);			// frame
    //	printf("Ch1:\t%.2Lf\n", messwerte[1][pet]);			// acceleration
    //	printf("Ch2:\t%.2Lf\n", messwerte[2][pet]);			// zenith
    //	printf("Ch3:\t%.2Lf\n", messwerte[3][pet]-KORREKTURWERT);	// azimuth
    //	printf("Ch4:\t%.2Lf\n", messwerte[3][pet]);			// temp
    
    	++net;	// total cycles
    	pet=(pet+1) % ARRAYSIZE;	// array position
    
    				// analysis of measurements
    	qsort(messwerte, ARRAYSIZE, sizeof(messwerte[0][0]), compare_chan3);
    
    	for (int i=0; i<ARRAYSIZE-1; i++)
    	{
    		printf("n: %d: \t%Lf\t%Lf\t%Lf\t%Lf\n", net, messwerte[0][i], messwerte[1][i], messwerte[2][i], messwerte[3][i]);
    	}
    	printf("\n\nSortiert!\n\n");
    
    }	// end of endless for-loop
    
    				// Cleanup
      CHECK_OAK_CALL(closeDevice(deviceHandle));
      return 0;
    }
    

    Während die C++-Variante gerne c++11-kompatibel kompiliert werden möchte:

    g++ -DHAVE_CONFIG_H -I. -I..     -g -O2 -MT oaklinux.o -MD -MP -MF .deps/oaklinux.Tpo -c -o oaklinux.o oaklinux.cpp
    In file included from /usr/include/c++/4.7/array:36:0,
                     from oaklinux.cpp:17:
    /usr/include/c++/4.7/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support is 
    currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
    make: *** [oaklinux.o] Error 1
    

    Was mich vor das Problem stellt, dass ich nicht weiß, wie/wo ich das dem automake-Makefile / configure mitteilen soll...

    Meine Vermutung wäre die Makefile.am im Projektordner. Und dann dort ein make ausführen, was die Make-Datei im src-Unterordner aktualisiert.
    Aber ich hab da um ehrlich zu sein keinen Überblick 😕


  • Mod

    Mische nie C und C++! Das wurde dir schon gesagt in anderen Threads.

    Die nötigen Stichworte, wie du dich über configure&make kundig machen kannst, wurden dir auch schon genannt, in anderen Threads.

    Programmiere nicht durch das Zusammenkopieren von Code aus dem Internet, besonders nicht, wenn du ihn nicht verstehst. Das wurde dir auch schon gesagt in anderen Threads.

    Wie soll man dir helfen, wenn du keine Hilfe annimmst? Ja, das sind Ratschläge, die jeweils viel Arbeit für dich sind. Aber je länger du sie nicht beachtest, desto mehr Arbeit wird es für dich, wenn du sie letztlich doch befolgst. Und irgendwann musst du sie befolgen, denn das was du derzeit versuchst, wird niemals funktionieren.
    Derzeit pickst du dir nur die Hilfe heraus, die du hören möchtest. Sachen, die kleine Fehler an deinem Programm oberflächlich ausbessern. Dies behebt vielleicht jeweils deine unmittelbaren Fehler, führt aber dann direkt zum nächsten, weil das ganze Grundgerüst nicht stimmt.



  • Da muss ich dir Recht geben. Aber als Anfänger ist es schwer, den Überblick zu behalten. Mit deinen Erfahrungswerten würde ich mir vermutlich nichts anderes raten.

    Leider ist das mit dem Sensor dringend und ich muss noch viele weitere Aspekte als die Programmierung bei meinem Problem lösen - sonst würde ich mir lieber die Zeit nehmen und mein frisch erworbenes C++-Buch wälzen.

    Hinsichtlich configure und make habe ich leider bisher keine wirklich aufschlussreiche Seite gefunden, auch wenn du mir bereits die relevanten Suchbegriffe geliefert hast.


  • Mod

    Cysign schrieb:

    Leider ist das mit dem Sensor dringend und ich muss noch viele weitere Aspekte als die Programmierung bei meinem Problem lösen - sonst würde ich mir lieber die Zeit nehmen und mein frisch erworbenes C++-Buch wälzen.

    Dann musst du eben jemanden dafür bezahlen. Mit deinen jetzigen Kenntnissen wird es nichts, das kann dir jeder hier bestätigen. Du wirst bloß weiter rumpfuschen und am Ende hast du weder dein Problem gelöst, noch irgendetwas gelernt. Man kann eben einfach nicht mal eben so ungelernt mit Werkzeugen arbeiten, deren Benutzung man normalerweise monatelang lernen müsste, und am Ende ein Ergebnis erwarten.



  • Jemandem, der nicht programmieren kann, würde ich bei Tabellenproblemen zu einer Software raten, die darauf spezialisiert ist. Gibt da glaube ich seit längerem eine von Microsoft und im Open-Source-Bereich versuchen sich glaube ich auch schon ein paar Jungs daran.



  • Versetzt und mit 4 Bier saß ich zuhause.
    Und weil Cysign einen geraden Satz schreiben kann, hab' ich mich mal an einem kleinen Refactoring seines original Codes versucht.
    Das Oak-Dingsbums hat schon ein fürchterliches C/C++ Gemisch in der Schnittstelle. Mangels Testmöglichkeiten bin ich nicht viel besser, aber etwas.
    (Im Sinne von: von dieser Version zu OO ist es nur ein kleiner Sprung.)

    #include <array>
    #include <cmath> // M_1_PI (on my platform)
    #include <iostream>
    #include <stdexcept>
    #include <string>
    #include <thread>
    #include <vector>
    #include "OakHidBase.h"
    #include "OakFeatureReports.h"
    
    struct oak_exception : std::runtime_error{
      typedef std::runtime_error base;
      oak_exception(const char* what) : base(what) {}
    };
    
    struct oak_status{
      explicit oak_status(Toradex::Oak::EOakStatus status){
        if( status != Toradex::Oak::eOakStatusOK )
          throw oak_exception(Toradex::Oak::getStatusString(status).c_str());
      }
    };
    
    typedef Toradex::Oak::DeviceInfo               device_info_t;
    typedef Toradex::Oak::EOakLedMode              led_mode_t;
    typedef Toradex::Oak::EOakReportMode           report_mode_t;
    typedef int                                    oak_device_handle;
    typedef std::vector<Toradex::Oak::ChannelInfo> channel_info_table;
    typedef unsigned                               rate_t;
    
    typedef std::array<double, 4>                  sample_t;
    
    std::ostream& operator<<(std::ostream& out, const sample_t& sample){
      return out << sample[0] << ' ' << sample[1] << ' ' << sample[2] << ' ' << sample[3];
    }
    
    oak_device_handle oak_open(const std::string& path = "/dev/usb/hiddev0"){
      using namespace Toradex::Oak;
      oak_device_handle h;
      oak_status(openDevice(path, h));
      return h;
    }
    
    void oak_close(oak_device_handle& h){
      oak_status(Toradex::Oak::closeDevice(h));
    }
    
    Toradex::Oak::DeviceInfo device_info(oak_device_handle h){
      device_info_t info;
      oak_status(Toradex::Oak::getDeviceInfo(h, info));
      return info;
    }
    
    report_mode_t report_mode(oak_device_handle h, bool persistent){
      report_mode_t mode;
      oak_status(Toradex::Oak::getReportMode(h, mode, persistent));
      return mode;
    }
    
    report_mode_t report_mode(oak_device_handle h, report_mode_t mode, bool persistent){
      using namespace Toradex::Oak;
      const report_mode_t ret(report_mode(h, ret, persistent));
      oak_status(setReportMode(h, mode, persistent));
    
      if( report_mode(h, persistent) != mode )
        throw oak_exception("Setting the report mode failed.");
      return ret;
    }
    
    led_mode_t led_mode(oak_device_handle h, bool persistent){
      led_mode_t mode;
      oak_status(Toradex::Oak::getLedMode(h, mode, persistent));
      return mode;
    }
    
    led_mode_t led_mode(oak_device_handle h, led_mode_t mode, bool persistent){
      using namespace Toradex::Oak;
      const led_mode_t ret(led_mode(h, persistent));
      oak_status(setLedMode(h, mode, persistent));
    
      if( led_mode(h, persistent) != mode )
        throw oak_exception("Setting the led mode failed.");
      return ret;
    }
    
    rate_t sample_rate(oak_device_handle h, bool persistent){
      rate_t rate;
      oak_status(Toradex::Oak::getSampleRate(h, rate, persistent));
      return rate;
    }
    
    rate_t sample_rate(oak_device_handle h, rate_t mode, bool persistent){
      using namespace Toradex::Oak;
      const rate_t ret = sample_rate(h, persistent);
      oak_status(setSampleRate(h, mode, persistent));
    
      if( sample_rate(h, persistent) != mode )
        throw oak_exception("Setting the sample rate failed.");
      return ret;
    }
    rate_t report_rate(oak_device_handle h, bool persistent){
      rate_t ret;
      oak_status(Toradex::Oak::getReportRate(h, ret, persistent));
      return ret;
    }
    
    rate_t report_rate(oak_device_handle h, rate_t mode, bool persistent){
      using namespace Toradex::Oak;
      const rate_t ret = report_rate(h, persistent);
      oak_status(setReportRate(h, mode, persistent));
    
      if( report_rate(h, persistent) != mode )
        throw oak_exception("Setting the report rate failed.");
      return ret;
    }
    
    channel_info_table channel_info(oak_device_handle h){
      using namespace Toradex::Oak;
      channel_info_table infos;
      const int size = device_info(h).numberOfChannels;
      infos.resize(size);
      for ( int i=0; i<size; ++i ){
        oak_status(getChannelInfo(h, i, infos[i]));
      }
      return infos;
    }
    
    sample_t sample(oak_device_handle h){
      using namespace Toradex::Oak;
      std::vector<int> irq_reports;
      irq_reports.reserve(4);
      oak_status(readInterruptReport(h, irq_reports));
    
      const channel_info_table infos = channel_info(h);
      const double mult2 = 180 * M_1_PI * pow(10.00, infos[2].unitExponent);
      const double mult3 = 180 * M_1_PI * pow(10.00, infos[3].unitExponent);
    
      return sample_t {{ static_cast<double>(irq_reports[0])
    	, static_cast<double>(irq_reports[1])
    	, irq_reports[2]*mult2
    	, irq_reports[3]*mult3 }};
    }
    
    int main(){
      typedef std::vector<sample_t> data_table;
      const std::chrono::milliseconds sleepval(230);
      const rate_t delay = 20;
      const int s_cnt = 100000;
      try{
        oak_device_handle handle = oak_open();
        report_mode(handle, Toradex::Oak::eReportModeAfterSampling);
        led_mode   (handle, Toradex::Oak::eLedModeOff);
        report_rate(handle, delay);
        sample_rate(handle, delay);
    
        data_table samples;
        samples.reserve(s_cnt);
        for( int i=0; i<s_cnt; ++i ){
          std::this_thread::sleep_for(sleepval);
          samples.emplace_back(sample(handle));
        }
        oak_close(handle);
    
        for(auto s : samples)
          std::cout << s << '\n';
    
      }
      catch(const oak_exception& e){
        std::cerr << e.what() << '\n';
        return -1;
      }
    }
    


  • Cysign schrieb:

    qsort(messwerte, ARRAYSIZE, sizeof(messwerte[0][0]), compare_chan3);
    

    Meintest du

    qsort(messwerte, ARRAYSIZE, sizeof(messwerte[0]), compare_chan3);
    

    ?

    Das Array besteht aus ARRAYSIZE Elementen der Größe sizeof(messwerte[0]), nicht aus ARRAYSIZE Elementen der Größe sizeof(messwerte[0][0]), nehme ich an. Ich gehe hier von der Vermutung aus, dass messwerte

    double messwerte[ARRAYSIZE][5];
    

    ist.



  • Also kompilieren kann ich die C++-Geschichte, indem ich in der Makefile bei den CXX-Flags ein -std=gnu++11 anhänge:

    CXXFLAGS = -g -O2 -std=gnu++11
    

    Ist das denn so gedacht? Ich bin davon ausgegangen, dass man in der configure etwas ändern muss und damit die Makefile automatisch angepasst generiert wird. Aber mir solls erstmal recht sein, dass ich nun c++11 kompilieren kann.

    Gestern Abend habe ich noch eine Weile mit einem befreundeten Programmierer geskypet, der mir noch ein paar Sachen erklären konnte.
    Als Webprogrammierer (Python, PHP,...) konnte er sich relativ schnell in die Syntax einlesen und mir anhand eines kleinen Beispielcodes ein Sortierung demonstrieren.

    Ein wichtiger Aspekt für mich war, dass der Datentyp vector eigentlich das ist, was ich mir von Anfang an als Array gewünscht hatte - ausgehend davon, dass ich nach Sachen wie push und pop in Arrays in diesem Zusammenhang gegoogelt hatte und nicht fündig wurde. Aber ohne mich näher diesbezüglich informiert zu haben, hatte ich das mit einem mathematischen Vektor assoziiert und nicht weiter verfolgt.

    @Decimad: Danke für deinen konstruktiven Vorschlag.
    Ich habe mal nach "Tabellenproblemen paar Jungs Open-Source-Bereich" gesucht, jedoch konnte ich nicht herausfinden, welches Programm du mir nahelegen möchtest, um einen Sensor in Echtzeit auszuwerten, Ausreißer zu analysieren, Werte zu filtertern, Korrekturwerte einzurechnen und einen präzisen Messwert auszugeben. Vielleicht bin ich auch einfach zu unerfahren, deine äußerst Hilfreiche Antwort richtig zu interpretieren... Dennoch vielen Dank für deine Mühen.

    @SeppJ: Genau das war Anfangs der Plan. Ich telefonierte also sämtliche Bekannte und Freunde ab, die auch nur annähernd etwas mit Programmierung zu tun haben könnten. Leider konnte mir niemand einen Programmierer empfehlen, der in dieser Hinsicht Erfahrungen hat und mir weiterhelfen kann.
    Also habe ich mich selbst ran gemacht, den gewünschten Sensor zu untersuchen.
    Und nachdem mein Code zur Analyse stand, konnte ich abwägen, dass der verwendete Sensor nicht für meinen Zweck tauglich ist. Ich hatte mehrmals mit dem Hersteller Kontakt, der das von mir angeprangerte Verhalten seines Sensors nicht kannte, es aber mit unterschiedlichen Sensoren der selben Modellreihe nachvollziehen, jedoch nicht erklären konnte.
    Aus diesem Grund habe ich meine Versuche auf Basis des ersten Sensors eingestellt und befasse mich nun mit diesem Sensor, der scheinbar die Anforderungen erfüllen könnte - zumindest nach einer manuellen Auswertung der Daten nach zu urteilen.

    Die Ausgabe von Furbles Code liefert übrigens:

    20 9768 95.8673 179.737
    125 9812 95.4605 180
    221 9761 95.7985 179.513
    327 9731 95.9819 179.794
    430 9805 95.7584 179.834
    526 9739 95.684 179.611
    633 9775 95.7985 180
    739 9768 95.7985 180.172
    835 9842 95.7412 180.098
    939 9768 95.9074 179.777
    1044 9783 95.81 179.737
    1140 9797 95.81 179.834
    1244 9820 95.684 180
    1348 9731 95.9819 179.611
    1444 9805 95.7584 179.777
    714 9761 96.0335 179.68
    810 9761 95.7011 179.794
    923 9820 95.7985 179.834
    1018 9746 95.7011 179.611
    1114 9768 95.7011 179.903
    1229 9775 96.0736 179.777
    1325 9805 95.5865 179.834
    1421 9805 95.7584 179.846
    1533 9731 95.9246 179.622
    1629 9820 95.8501 179.943
    1725 9797 95.8501 179.777
    1836 9820 95.7011 179.846
    1934 9827 95.6267 179.903
    2029 9820 95.7011 180.041
    91 9797 95.7584 179.834
    190 9768 95.7985 179.846
    1493 9753 95.8501 179.622
    1589 9746 95.8673 179.777
    1688 9842 95.7985 180
    1795 9842 95.6438 179.834
    1891 9797 96.022 179.846
    1990 9820 95.535 180
    52 9827 95.4777 180.172
    148 9768 95.7985 179.777
    244 9827 95.4605 180.041
    357 9812 95.5865 180.041
    453 9768 95.6438 179.777
    549 9812 95.8673 180
    663 9761 95.5751 179.777
    759 9775 95.8673 179.737
    855 9797 95.9074 179.737
    115 9805 95.7985 179.777
    175 9761 95.8673 179.737
    291 9820 95.535 179.903
    387 9805 95.7011 179.846
    483 9856 95.4777 179.943
    595 9783 95.9647 179.68
    690 9761 95.9819 179.68
    786 9797 95.7584 179.68
    900 9805 95.9819 179.943
    996 9775 95.8673 179.777
    1092 9753 95.9246 179.737
    1206 9775 95.9074 179.846
    1302 9797 96.2053 179.777
    1398 9834 95.81 180.264
    1511 9812 95.7584 179.834
    1607 9820 95.7985 179.846
    871 9790 95.7584 179.846
    967 9842 95.4204 179.846
    1068 9805 95.7985 179.777
    1179 9827 95.6267 179.903
    1274 9746 96.0335 179.622
    1372 9775 95.9074 179.834
    1484 9768 95.8673 179.903
    1580 9768 96.0335 179.846
    1676 9761 96.0908 179.834
    1790 9790 95.7412 179.903
    1886 9834 95.6438 180
    1982 9783 96.0335 179.68
    45 9746 95.5751 179.846
    141 9790 95.7412 179.846
    237 9797 96.022 179.834
    1544 9790 96.2053 179.777
    1586 9717 95.81 179.737
    1700 9820 95.684 179.903
    1796 9812 95.7011 179.903
    1892 9805 95.9246 179.777
    2005 9761 96.0908 179.737
    53 9783 95.81 180
    149 9768 95.8673 179.68
    261 9797 96.1309 179.834
    357 9761 95.9074 179.737
    453 9820 95.7011 179.846
    565 9768 95.5751 179.68
    661 9790 95.5178 179.903
    757 9783 95.8501 179.834
    870 9775 95.8673 179.777
    966 9783 95.6438 179.777
    234 9790 95.9074 179.737
    330 9805 95.7584 179.903
    443 9820 95.4605 179.834
    542 9812 95.684 180.115
    638 9812 95.8673 179.737
    743 9827 95.5751 179.903
    844 9797 95.8501 179.846
    

    Ich habe das Programm mehrmals ausgeführt und konnte keine Ausreißer mehr feststellen!
    Großes Lob und Dank an Furble!

    Hinsichtlich SeppJs Beispiel:

    array<array<int, 3>, 4> foo = {{{{1,6,8}},{{4,2,7}},{{8,3,1}},{{9,3,4}}}};
    

    array<datentyp, größe> namedesarrays = ...

    In wiefern unterscheidet sich dieses Array von einem Vector in der Möglichkeit der Sortierung? Könnte man beide Konstrukte (Array/Vector) auf die hier vorgeschlagene Art

    sort(foo.begin(), foo.end(), compare_by_column<array<int, 3>, 1>);
    

    sortieren?

    Wäre es denn sinnvoller auf vector oder array zu setzen?

    Ich möchte die Daten auslesen, eine kleine Menge (beispielsweise 50-200 Werte) sammeln, korrigieren.

    Zum Korrigieren muss ich ein zweites Programm schreiben, das, nachdem der Sensor in verschiedene Positionen gebracht wurde, dort Messwerte aufnimmt und als Datei abspeichert.

    Das eigentliche Programm liest später diese Werte aus der Datei ein und wertet die Winkel aus. Anhand der gespeicherten Werte aus der Datei wird nun eine Korrektur vorgenommen.

    Noch zum Verständnis:

    samples.reserve(s_cnt); ist quasi das malloc des C++.

    But unlike arrays, their size can change dynamically, with their storage being handled automatically by the container. (http://www.cplusplus.com/reference/vector/vector/ )

    Ich hatte das so verstanden, dass eine manuelle Reservierung in diesem Fall nicht nötig sei. Und muss der Speicher nicht wieder freigegeben (vgl. C free()) werden?

    @Seldon:

    qsort(messwerte, ARRAYSIZE, sizeof(messwerte[0][0]), compare_chan3);
    

    Meintest du

    qsort(messwerte, ARRAYSIZE, sizeof(messwerte[0]), compare_chan3);
    

    ?[/quote]
    Das dachte ich auch zunächst. Jedoch hat array[] im Gegensatz zu array[][] immer ein "Segmentation fault (core dumped)" ausgegeben. Den Fehler kannte ich nur, wenn auf einen unexistenten Bereich eines Arrays zugegriffen wird - und so versuchte ich array[][] und dieser Fehler trat nicht mehr auf.


  • Mod

    Cysign schrieb:

    @Decimad: Danke für deinen konstruktiven Vorschlag.
    Ich habe mal nach "Tabellenproblemen paar Jungs Open-Source-Bereich" gesucht, jedoch konnte ich nicht herausfinden, welches Programm du mir nahelegen möchtest, um einen Sensor in Echtzeit auszuwerten, Ausreißer zu analysieren, Werte zu filtertern, Korrekturwerte einzurechnen und einen präzisen Messwert auszugeben. Vielleicht bin ich auch einfach zu unerfahren, deine äußerst Hilfreiche Antwort richtig zu interpretieren... Dennoch vielen Dank für deine Mühen.

    Open Office, Libre Office, GNU R, usw.

    Du brauchst keine eierlegende Wollmilchsau.

    Unix Philosophie schrieb:

    Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.

    Schreib ein Programm, dass deinen Sensor ausliest. Datenauswertung machst du dann mit einem Datenauswertungsporgramm.

    @SeppJ: Genau das war Anfangs der Plan. Ich telefonierte also sämtliche Bekannte und Freunde ab, die auch nur annähernd etwas mit Programmierung zu tun haben könnten. Leider konnte mir niemand einen Programmierer empfehlen, der in dieser Hinsicht Erfahrungen hat und mir weiterhelfen kann.

    Wieso fragst du denn Freunde und Bekannte? Wenn du ein neues Auto brauchst, fragst du dann Freunde und Bekannte, ob sie dir eines bauen können? Und wenn nicht, dann baust du es selber? Nein, du gehst zu jemandem, der sich mit so etwas auskennt.

    Hinsichtlich SeppJs Beispiel:

    array<array<int, 3>, 4> foo = {{{{1,6,8}},{{4,2,7}},{{8,3,1}},{{9,3,4}}}};
    

    array<datentyp, größe> namedesarrays = ...

    In wiefern unterscheidet sich dieses Array von einem Vector in der Möglichkeit der Sortierung?

    Gar nicht. Das ist doch das schöne an Programmierung im Stil der STL. Du bist vollkommen unabhängig vom Datentyp. Ich wählte ein statisches Array, weil du ein statisches Array hattest. Ich nahm (fälschlicherweise?) an, dass dahinter irgendein tieferer Sinn stand.

    Könnte man beide Konstrukte (Array/Vector) auf die hier vorgeschlagene Art

    sort(foo.begin(), foo.end(), compare_by_column<array<int, 3>, 1>);
    

    sortieren?

    Ja. Zumindest wenn der innere Typ array<int, 3> bleibt. Ansonsten musst du der compare_by_column-Funktion noch den richtigen Typen geben. Das kann man natürlich auch noch automatisieren.

    Wäre es denn sinnvoller auf vector oder array zu setzen?

    Das kommt drauf an. vector ist flexibel in der Länge, array nicht. In vector sollte immer die Standardwahl sein, wenn man davon abweicht, sollte man dies Begründen. Eine Begründung (besser: Die Begründung) für Array ist, dass man die Anzahl der Datensätze zur Compilezeit kennt.

    Ich möchte die Daten auslesen, eine kleine Menge (beispielsweise 50-200 Werte) sammeln, korrigieren.

    Klingt nach vector, da "kleine Menge" und "50-200" unspezifische Größen sind.

    samples.reserve(s_cnt); ist quasi das malloc des C++.

    vector ist das malloc des C++ 🙂 .



  • SeppJ schrieb:

    Wäre es denn sinnvoller auf vector oder array zu setzen?

    Das kommt drauf an. vector ist flexibel in der Länge, array nicht. In vector sollte immer die Standardwahl sein, wenn man davon abweicht, sollte man dies Begründen. Eine Begründung (besser: Die Begründung) für Array ist, dass man die Anzahl der Datensätze zur Compilezeit kennt.

    Ein starker Grund gegen das Array ist, dass es so schlecht movable ist. Einen vector<array> zu sortieren sollte man besser vermeiden, besser ist vector<vector> .

    SeppJ schrieb:

    samples.reserve(s_cnt); ist quasi das malloc des C++.

    vector ist das malloc des C++ 🙂 .

    Besser nicht, reserve macht nicht das, was du willst, denn die Grösse des Vektors bleibt gleich.

    Du möchtest resize .


  • Mod

    korrigendum schrieb:

    Einen vector<array> zu sortieren sollte man besser vermeiden, besser ist vector<vector> .

    Dafür sollte man vector<vector> allgemein vermeiden. Falls die innere Datenstruktur zu teuer zu swappen ist, dann benutzt man, wie hier im Thread schon vorgeschlagen, eine Indexliste.



  • Wenn ich das Programm kompiliere, steht fest, aus wie vielen Werten ich mitteln möchte. Jetzt zum Testen wähle ich hier einen eher kleineren Wert (z.B. 50), damit ich schneller meine Testausgaben abgreifen kann. Später wird der Wert eher größer sein, um beim Mitteln einen möglichst aussagekräftigen Wert zu bekommen (eher um die 200 oder gar mehr).

    Also beim Testen:
    50(Werte) * 4-5(Kanäle)

    Hinterher, wenn alles funktionert:
    z.B. 200 * 5 Kanäle

    Deswegen hatte ich das bei meinen ersten Versuchen mit

    #define ARRAYSIZE 50
    

    gelöst, um lediglich einen Wert ändern zu müssen beim Testen.

    Dass ich mir Tabellenkalkulationsprogrammen Daten auswerten kann, ist mir klar.
    Aber in benötige später Werte, die bereits aussagekräftig sind - und dazu gehört die Relation der Daten auf Grund verschiedenen Kanäle.

    Und wenn ich ein Auto kaufen möchte, frage ich auch zunächst Freunde und
    Bekannte - nämlich welchen Händler und welche Marke sie mir empfehlen können.
    Das heißt ja nicht, dass sie mir das Auto bauen sollen. Wenn ich aber mangels Empfehlung und Erfahrung keinen Händler finde...muss ich das (Transport-)Problem eben anderst lösen 😉

    Bzgl. "zu teuer zu swappen" = zu aufwändig oder zu viel Overhead?
    Und was sollte man hier als Richtwert nehmen?


  • Mod

    Cysign schrieb:

    Bzgl. "zu teuer zu swappen" = zu aufwändig oder zu viel Overhead?

    Was ist denn da der Unterschied?

    Und was sollte man hier als Richtwert nehmen?

    Wenn es dir zu langsam ist und die andere Methode schneller ist 🙂 . Oder wenn du eine technischere Antwort möchtest: Wenn der Mehraufwand durch die Indirektion kleiner ist als die Mehrkosten des Swappens des Originaltyps gegenüber den Kosten des Swappens eines size_t. Oder wenn du willkürlich aus der Luft gegriffene Zahlen haben möchtest, die bei vielen Problemstellungen passen und bei anderen wiederum absolut nicht: Wenn sizeof(Datentyp) > 5*sizeof(size_t).


Log in to reply