C++ Array Länge

Für allgemeine Fragen zur Programmierung, welche nicht! direkt mit Lazarus zu tun haben.
Antworten
Mathias
Beiträge: 6165
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

C++ Array Länge

Beitrag von Mathias »

Wie kann ich es machen, das bei len die Länge der Array bekomme ?
In diesem Beispiel wäre dies 5.
Momentan wird 8 ausgegeben, das sieht eher nach der Bit-Grösse eines int aus.

Code: Alles auswählen

#include <iostream>
 
using namespace std;
 
struct status {
   int start;
   int stop;
};
 
status helli[] = {{0, 30}, {60, 90}, {120, 150}, {180, 210}, {0, 0}};
 
void testCounter(struct status value[]) {
//   int len= sizeof(value) / sizeof(status);
   int len= sizeof(value); // Es kommt ein falscher Wert.
 
   cout << len << endl;
}
 
int main()
{
    cout << endl;
    testCounter(helli);
 
    return 0;
}
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: C++ Array Länge

Beitrag von Warf »

Gar nicht. In Pascal hat ein Array neben den daten noch ein Length feld welches die funktion length ausliest (das liegt kurz bevor dem Referenzzähler). In C ist das nicht so, da ist ein Array einfach nur ein Pointer ohne zusätzliche informationen, die muss der entwickler selbst tracken. Darum führt C++ die Klasse vector ein, welche einen Array mit zusatzinformationen und methoden bereitstellt. Bei external C calls wie execev müssen Arrays die als argument übergeben werden daher nullterminiert sein, und für die Main funktion wird daher die Argcount auch als int zusätzlich zum ArgValue array übergeben

Mathias
Beiträge: 6165
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: C++ Array Länge

Beitrag von Mathias »

Da bleibt mir wohl nichts anderes übrig, als es so zu lösen:

Code: Alles auswählen

#include <iostream>
 
int counter = 0;
 
struct status {
   int  start;
   int stop;
};
 
status helli[] = {{0, 30}, {60, 90}, {120, 150}, {180, 210}, {0, 0}};
 
void testCounter(struct status value[], int len) {
    len /= sizeof(status);
 
   std::cout << len << std::endl;
   std::cout << sizeof(status) << std::endl;
 
 
   for (int i=0; i<len; i++) {
      if (value[i].start == counter){
         return;
      }
      if (value[i].stop == counter){
         return;
      }
   }
}
 
 
int main()
{
    std::cout << std::endl;
    std::cout << sizeof(helli) <<std::endl;
 
    testCounter(helli, sizeof(helli));
 
    return 0;
}
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: C++ Array Länge

Beitrag von Warf »

Mathias hat geschrieben:Da bleibt mir wohl nichts anderes übrig, als es so zu lösen:


Ich hätte da noch ein paar Anmerkungen, using namespace std gilt als bad practice. Viele Bibliotheken haben Funktionen die genauso heißen wie die std Funktionen, daher sollte man mit using namespace std vorsichtig sein, und lieber die Funktionen die man braucht einzeln includen.
Außerdem würde ich, wenn dein array eine konstante ist einfach eine konstante helilen oder so dazumachen. Und was spricht gegen eine vector? Wäre doch deutlich angenehmer

Mathias
Beiträge: 6165
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: C++ Array Länge

Beitrag von Mathias »

Ich hätte da noch ein paar Anmerkungen, using namespace std gilt als bad practice. Viele Bibliotheken haben Funktionen die genauso heißen wie die std Funktionen, daher sollte man mit using namespace std vorsichtig sein, und lieber die Funktionen die man braucht einzeln includen.
Da bin ich gleicher Meinung, das dies eine Fehlerquelle ist.
Aber im obigen Code ist mir dies eigentlich egal, da dies ein Versuchscode ist, welcher die Array-Übergabe testen sollte, welche später auf einem Ardunio laufen soll.

Natürlich würde ich den Arduino-Sketch am liebsten mit Lazarus coden, nur das Problem, das ich den Code einem Kollegen weiter geben muss. Eine Arduino-IDE ist schneller und einfacher installiert, als ein Lazarus für AVR.

C++ ist einfach eine Katastrophe. :evil:

Und was spricht gegen eine vector? Wäre doch deutlich angenehmer
Wegen des Arduinos.

Außerdem würde ich, wenn dein array eine konstante ist einfach eine konstante helilen oder so dazumachen.

Die Konstanten sollten von einem Leihen sehr einfach modifizierbar sein.

Dies sind Konstanten, welche Laufzeiten bestimmen. 200 einspricht 20h.

Code: Alles auswählen

status StationTime[] = { 200, 220 };
status StrassenLampeTime[] = { 45, 75 };
status SchneeKanoneTime[] = { 75, 105 };
status HelliTime[] = { { 0, 30 }, { 60, 90 }, { 120, 150 }, { 180, 210 } };
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6165
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: C++ Array Länge

Beitrag von Mathias »

Ich wollte es mal mit Lazarus, was die Array-Übergabe betrifft.

Code: Alles auswählen

var
  ar:array[0..7] of Byte;
 
procedure Test(a:array of Byte);
var
  i:Int16;
begin
  for i:= 0 to 7 do UARTSendChar(char(a[i]));
end;

Dies wird mit folgendem Fehler quittiert:

Code: Alles auswählen

Hint: (11030) Start of reading config file /home/tux/fpcupdeluxe_ATmega328/fpc/bin/x86_64-linux/fpc.cfg
Hint: (11031) End of reading config file /home/tux/fpcupdeluxe_ATmega328/fpc/bin/x86_64-linux/fpc.cfg
Free Pascal Compiler version 3.1.1-r20:38392 [2018/03/03] for avr
Copyright (c) 1993-2018 by Florian Klaempfl and others
(1002) Target OS: Embedded
(3104) Compiling Project1.pas
/n4800/DATEN/Programmierung/Lazarus/AVR/ATmega328p/Array_an_procedure/Project1.pas(54,1) Fatal: Internal error 2017091103
Fatal: (1018) Compilation aborted
Error: /home/tux/fpcupdeluxe_ATmega328/fpc/bin/x86_64-linux/ppcrossavr returned an error exitcode

Dabei habe ich die procedure Test nicht mal aufgerufen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6165
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: C++ Array Länge

Beitrag von Mathias »

Da man beim AVR keine dynamische Array verwenden kann, bin ich auf folgende Lösung gekommen.
Dies sieht ähnlich aus, wie bei C++.
Oder hat jemand eine bessere Lösung ?

Code: Alles auswählen

type
  TPara = record
    start, stop:Int16;
  end;
  PPara = ^TPara;
 
var
  ar1: array[0..2] of TPara = ((start: 10; stop: 20),(start: 20; stop: 30),(start: 40; stop: 50));
  ar2: array[0..0] of TPara = ((start: 111; stop: 222));
  ar3: array[0..1] of TPara = ((start: 3333; stop: 4444),(start: 5555; stop: 6666));
 
  procedure Test(p: PPara; l: integer);
  var
    i: Int16;
    b: TPara;
    s: ShortString;
 
  begin
    for i := 0 to l - 1 do begin
      b := p^;
      str(b.start: 6, s);
      UARTSendString(s);
      str(b.stop: 6, s);
      UARTSendString(s);
      Inc(p);
    end;
    UARTSendChar(#13);
    UARTSendChar(#10);
  end;
 
begin
  UARTInit;
 
  UARTSendString('Anfang' + #13#10);
  Test(@ar1, Length(ar1));
  Test(@ar2, Length(ar2));
  Test(@ar3, Length(ar3));
  UARTSendString('Ende' + #13#10);
 
  repeat
  until 1 = 2;
end.


Ausgabe:

Code: Alles auswählen

Anfang
    10    20    20    30    40    50
   111   222
  3333  4444  5555  6666
Ende
 
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6165
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: C++ Array Länge

Beitrag von Mathias »

Oder hat jemand eine bessere Lösung ?

Ich habe unterdessen etwas besseres gefunden:

Code: Alles auswählen

procedure Test(const p :array of TPara); // Zwingend const oder var
var
  i: Int16;
  s: ShortString = '';
begin
  for i := 0 to Length(p) - 1 do begin
    str(p[i].start: 6, s);
    UARTSendString(s);
    str(p[i].stop: 6, s);
    UARTSendString(s);
  end;
  UARTSendChar(#13);
  UARTSendChar(#10);
end;
 
begin
  UARTInit;
 
  UARTSendString('Anfang' + #13#10);
  Test(ar1);
  Test(ar2);
  Test(ar3);
  UARTSendString('Ende' + #13#10);

Dabei ist es wichtig, da bei der Deklaration in der Procedure ein const oder var steht.
Lässt man dies weg, gibt es einen: Error: Internal error 2017091103

Man entdeckt immer wieder etwas neues. :wink:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten