Forum: Mikrocontroller und Digitale Elektronik int Array abschneiden


von Markus (Gast)


Lesenswert?

Hallo


Ich habe eine Konstante zB
#define TRUNCATEARRAYFROMVALUE= 150 und ein Int Array mit 200 Elementen.
Jetzt möchte ich einfach die letzten 50 rubbish Werte wegschneiden.
Gibt es eigentlich eine Funktion, die das automatisch macht oder muss 
ich das selbst mit einer for-Schleife in C erledigen?

von Markus (Gast)


Lesenswert?

Markus schrieb:
> #define TRUNCATEARRAYFROMVALUE= 150

ähmm ohne =

vor lauter copy paste sorry  :(

von zitter_ned_aso (Gast)


Lesenswert?

Markus schrieb:
> Jetzt möchte ich einfach die letzten 50 rubbish Werte wegschneiden.

Warum nicht einfach die Iteration auf 150 Arraywerte beschränken?

for(int i=0; i<TRUNCATEARRAYFROMVALUE; i++)

Und den Rest ignorieren.

von Ert (Gast)


Lesenswert?

Kann man das nicht mit nem Pointer lösen?

von Adam P. (adamap)


Lesenswert?

Willst du dein Array verkleinern oder beim umkopieren nur die ersten 150 
Werte beachten?

Du sagtest dein Datentyp wäre Int...also 32bit?

Falls du kopieren willst:
1
#include <string.h>
2
3
#define TRUNCATEARRAYFROMVALUE    150
4
5
/* Quelle */
6
int32_t src_array[200];
7
/* Ziel */
8
int32_t dst_array[TRUNCATEARRAYFROMVALUE];
9
10
/* kopieren */
11
memcpy(dst_array, src_array, TRUNCATEARRAYFROMVALUE * sizeof(int32_t));


Ert schrieb:
> Kann man das nicht mit nem Pointer lösen?

Klar geht auch, aber ich weiß jetzt nicht was er genau machen möchte.

Für Kopieren würde ich keine for-Schleife nehmen, ist langsamer als 
memcpy...will er jedoch mit jedem Wert etwas machen und nur bis zum 
150ten, dann kann er for-Schleife nehmen und mit Zeigern arbeiten:
1
#define TRUNCATEARRAYFROMVALUE    150
2
3
/* Quelle */
4
int32_t src_array[200];
5
6
int32_t *actual;
7
int32_t *end;
8
9
actual = src_array;
10
end = &src_array[TRUNCATEARRAYFROMVALUE];
11
12
for ( ; actual<end; actual++)
13
{
14
    /* Tu was mit den Daten, z.B. + 15 */
15
    
16
    *actual += 15;
17
}

von Markus (Gast)


Lesenswert?

Adam P. schrieb:
> Willst du dein Array verkleinern oder beim umkopieren nur die
> ersten 150
> Werte beachten?
>
> Du sagtest dein Datentyp wäre Int...also 32bit?
>
> Falls du kopieren willst:
> #include <string.h>
>
> #define TRUNCATEARRAYFROMVALUE    150
>
> /* Quelle */
> int32_t src_array[200];
> /* Ziel */
> int32_t dst_array[TRUNCATEARRAYFROMVALUE];
>
> /* kopieren */
> memcpy(dst_array, src_array, TRUNCATEARRAYFROMVALUE * sizeof(int32_t));

Danke, das habe ich gesucht

Adam P. schrieb:
> Willst du dein Array verkleinern oder beim umkopieren nur die
> ersten 150
> Werte beachten?
>
> Du sagtest dein Datentyp wäre Int...also 32bit?
>
> Falls du kopieren willst:
> #include <string.h>
>
> #define TRUNCATEARRAYFROMVALUE    150
>
> /* Quelle */
> int32_t src_array[200];
> /* Ziel */
> int32_t dst_array[TRUNCATEARRAYFROMVALUE];
>
> /* kopieren */
> memcpy(dst_array, src_array, TRUNCATEARRAYFROMVALUE * sizeof(int32_t));

Danke, das habe ich gesucht.
Würde das so auch funktionieren?
1
uint16_t*  TSC_copyArray(uint16_t src_array[], uint16_t index)
2
{
3
  uint16_t* pArray;
4
  
5
  /* Ziel */
6
  uint16_t dst_array[index];
7
  pArray = dst_array;
8
9
  /* kopieren */
10
  memcpy(dst_array, src_array, index * sizeof(int16_t));
11
  return pArray;
12
}

In der Zwischenzeit habe ich Folgendes probiert:
So müsste es eigentlich auch funktionieren.
Was sagt ihr?
1
uint16_t*  TSC_truncateArray(uint16_t array[], uint16_t index)
2
{
3
  uint16_t* pArray;
4
  uint16_t my_array[index];
5
  pArray = my_array;
6
  
7
  for(uint8_t i = 0; i < index; i++)
8
  {
9
    my_array[i] = array[i];
10
  }
11
12
  return pArray;
13
  
14
}

von Adam P. (adamap)


Lesenswert?

ICH würde das so nicht machen...

Das ist aber kein C sondern C++, stimmts?

Man sollte NIE aus einer Funktion einen Zeiger auf eine Variable 
zurückgeben die nur lokal in der Funktion existiert!

von zitter_ned_aso (Gast)


Lesenswert?

Markus schrieb:
> uint16_t dst_array[index];
>   pArray = dst_array;

Das ist dohc ein Zeiger auf eine lokale Variable, der nach dem Verlassen 
der Funktion zerstört wird.

Also vorher Speicher dynamisch (auf dem Heap) allokieren.

von Adam P. (adamap)


Lesenswert?

zitter_ned_aso schrieb:
> Also vorher Speicher dynamisch (auf dem Heap) allokieren.

Ich versuch dir da mal kurz was...

von zitter_ned_aso (Gast)


Lesenswert?

Markus schrieb:
> uint16_t my_array[index];
>   pArray = my_array;
>
>   for(uint8_t i = 0; i < index; i++)
>   {
>     my_array[i] = array[i];
>   }
>
>   return pArray;


Auch hier das Gleiche wie oben: Zeiger auf eine lokale Variable.

1
uint16_t* my_array = malloc(sizeof(uint16_t));
2
3
for(uint8_t i = 0; i < index; i++)
4
  {
5
    my_array[i] = array[i];
6
   }
7
8
return my_array;


Oder halt mit memcpy / memmove

von zitter_ned_aso (Gast)


Lesenswert?

zitter_ned_aso schrieb:
> uint16_t* my_array = malloc(sizeof(uint16_t));

Korrektur:

uint16_t* my_array = malloc(sizeof(uint16_t)*NEUE_ARRAY_GROESSE);

von zitter_ned_aso (Gast)


Lesenswert?

Adam P. schrieb:
> Ich versuch dir da mal kurz was...

ähm, was?

von Markus (Gast)


Lesenswert?

zitter_ned_aso schrieb:
> Markus schrieb:
>> uint16_t dst_array[index];
>>   pArray = dst_array;
>
> Das ist dohc ein Zeiger auf eine lokale Variable, der nach dem Verlassen
> der Funktion zerstört wird.
>
> Also vorher Speicher dynamisch (auf dem Heap) allokieren.

Ja macht Sinn.
Das habe ich mir schon irgendwie gedacht, dass das so nicht 
funktioniert, weil C die Variable in der Funktion im Stack ablegt und 
nach der Funktion die Variable nicht mehr existiert. Ich bin eben im 
Moment dabei, das Ganze zu lernen.

Adam P. schrieb:
> ICH würde das so nicht machen...
>
> Das ist aber kein C sondern C++, stimmts?
>
> Man sollte NIE aus einer Funktion einen Zeiger auf eine Variable
> zurückgeben die nur lokal in der Funktion existiert!

Mein Grundgedanke war eben den Ursprungsarray nicht zu überschreiben, 
sondern eine Kopie davon in der Funktion zu nutzen.
Um die bearbeitete Kopie aber weiter zu verwenden, muss ich sie 
zurückgeben können. Man kann ja nicht einfach ein Array zurückgeben.

von Adam P. (adamap)


Lesenswert?

zitter_ned_aso schrieb:
> Adam P. schrieb:
>> Ich versuch dir da mal kurz was...
>
War nicht an dich gerichtet.


Hier so wie du dir wohl vorgestellt hast mal als ganzes, aber wie gesagt 
es gibt viele wege ob nun mit 2 pointern als parameter, oder dann doch 
mit new bzw. malloc, kommt immer auf den anwendungsfall drauf an.
1
uint16_t *TSC_truncateArray(uint16_t src[], uint16_t length)
2
{
3
  uint16_t *dst = new uint16_t[length];
4
5
  if (dst == NULL)
6
  {
7
    return NULL;
8
  }
9
10
  memcpy(dst, src, length * sizeof(uint16_t));
11
  return dst;
12
}
13
14
int main()
15
{
16
  uint16_t buf[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
17
  uint16_t *p;
18
19
  p = TSC_truncateArray(buf, 5);
20
21
  if (p == NULL)
22
  {
23
    /* FEHLER */
24
  }
25
26
  return 0;
27
}

von Markus (Gast)


Lesenswert?

Danke euch beiden

Mir gefällt das memcpy schon sehr gut, vor allem wenn es schnell geht.

Die 2. Variante mit dem Pointer hat mich interessiert.

Dazu habe ich aber eine Frage:

Wenn ich den Array im Heap ablege (dynamischer Speicher)
Den Array aber für eine Auswertung durch das Ganze programm benötige.
Wann gebe ich dann den Speicher wieder frei?

von Adam P. (adamap)


Lesenswert?

Bevor du das Programm verlässt.

Aber dann würde ich den Speicher nicht in der Funktion reservieren.

Machst du das auf dem PC oder Mikrocontroller?

von Stefan F. (Gast)


Lesenswert?

Da Arrays eine feste Größe haben, kann man sie nicht verkleinern - nur 
umkopieren. Aber was gewinnst du damit, außer zeitweise doppelten 
Speicherbedarf?

Wenn dein Array je nach Situation unterschiedlich viele Elemente 
enthalten kann, brauchst du zusätzlich eine Variable für die 
Längenangabe oder eine spezielle Ende-Markierung mit einem reservierten 
Wert, der sonst niemals vorkommt, wie das bei Zeichenketten üblich ist.


Mit Ende-Markierung:
1
int array[1000]={0};
2
3
void append_to_array(int value)
4
{
5
    for (int i=0; i<999; i++)
6
    {
7
        if (array1[i]==0) // end marker found?
8
        {
9
            array[i]=value;
10
            array[i+1]=0;
11
            return;
12
        }
13
    }
14
    printf("Fehler: Array ist schon voll");
15
}
16
17
void read_maximum_100_values()
18
{
19
    for (int i=0; i<100 && array[i]!=0; i++)
20
    {
21
        int value=array[i];
22
        printf("wert=%i\n",value);
23
    }
24
}

Mit Längenangabe:
1
int array[1000];
2
int array_length=0;
3
4
void append_to_array(int value)
5
{
6
    if (array_length<1000)
7
    {
8
        array[array_length]=value;
9
        array_length++;
10
    }
11
    else
12
    {
13
        printf("Fehler: Array ist schon voll");
14
    }
15
}
16
17
void read_maximum_100_values()
18
{
19
    for (int i=0; i<100 && i<array_length; i++)
20
    {
21
        int value=array[i];
22
        printf("wert=%i\n",value);
23
    }
24
}

Die Verwerndung von sizeof(), strlen() und strcat() könnte hier nützlich 
sein.

von Dirk B. (dirkb2)


Lesenswert?

Markus schrieb:
> Mein Grundgedanke war eben den Ursprungsarray nicht zu überschreiben,
> sondern eine Kopie davon in der Funktion zu nutzen.

Dann übergib der Funktion schon eine Kopie vom Array.

von Markus (Gast)


Lesenswert?

Dirk B. schrieb:
> Markus schrieb:
>> Mein Grundgedanke war eben den Ursprungsarray nicht zu überschreiben,
>> sondern eine Kopie davon in der Funktion zu nutzen.
>
> Dann übergib der Funktion schon eine Kopie vom Array.

Ich hätte noch einige Fragen zu den Kommentaren der anderen, aber vorweg 
einmal:

Ein übergebener Array an eine Funktion zerfällt ja bekanntlich in einen 
Zeiger. Wie meinst du das "übergib der Funktion die Kopie vom Array"
Geht das irgendwie direkt auch oder gibt es nur die Variante, den 
src-array schon vorhor in eine andere arrayvariable zu speichern?

von Cyblord -. (cyblord)


Lesenswert?

Markus schrieb:
> Wie meinst du das "übergib der Funktion die Kopie vom Array"

Array halt vorher kopieren. Zeiger auf Kopie übergeben. Anders gehts 
nicht.

Aber das ist meist der falsche Weg. Will man mit Teilen eines Arrays 
arbeiten gibt man den Funktionen nicht nur das Array sondern einfach 
Offset und Länge mit. Und die arbeiten dann nur auf diesem Teil.

Siehe z.B. solche Implementierungen von QuickSort.

von Markus (Gast)


Lesenswert?

Cyblord -. schrieb:
> Markus schrieb:
>> Wie meinst du das "übergib der Funktion die Kopie vom Array"
>
> Array halt vorher kopieren. Zeiger auf Kopie übergeben. Anders gehts
> nicht.
>
> Aber das ist meist der falsche Weg. Will man mit Teilen eines Arrays
> arbeiten gibt man den Funktionen nicht nur das Array sondern einfach
> Offset und Länge mit. Und die arbeiten dann nur auf diesem Teil.
>
> Siehe z.B. solche Implementierungen von QuickSort.



Danke Cyblord für den Tipp zugleich

Meine nächste Frage ist: was hat es mit new uint16_t[length] auf sich.
Was passiert da in der Zeile. Ich kenne das nur von Java, wenn man ein 
neues Objekt erzeugt. Was passiert hier und warum macht man das?

Adam P. schrieb:
> zitter_ned_aso schrieb:
>> Adam P. schrieb:

> {
>   uint16_t *dst = new uint16_t[length];
>

von Cyblord -. (cyblord)


Lesenswert?

Markus schrieb:
> Meine nächste Frage ist: was hat es mit new uint16_t[length] auf sich.

Das ist C++ Syntax.

> Was passiert da in der Zeile. Ich kenne das nur von Java, wenn man ein
> neues Objekt erzeugt. Was passiert hier und warum macht man das?

Was schon? Es wird ein neues Array erzeugt. In reinem C nimmt man dafür 
malloc.

von Markus (Gast)


Lesenswert?

Cyblord -. schrieb:
> Markus schrieb:
>> Meine nächste Frage ist: was hat es mit new uint16_t[length] auf sich.
>
> Das ist C++ Syntax.


Also könnte ich das in reinem C gar nicht anwenden.
Ich frage mich dann wieso, das trotzdem als Lösung vorgeschlagen wurde, 
denn ich hatte doch weiter oben C erwähnt. Oder ist das irgendwie 
Kompatibel und Adam hat es bewusst so vorgeschlagen.

Die anderen Beiträge muss ich mir erst mal heute Abend noch durchlesen.

Bis dann

von Dirk B. (dirkb2)


Lesenswert?

Brauchst du denn noch die Originalwerte im Array oder kann das 
überschrieben werden?

von Cyblord -. (cyblord)


Lesenswert?

Markus schrieb:
> Cyblord -. schrieb:
>> Markus schrieb:
>>> Meine nächste Frage ist: was hat es mit new uint16_t[length] auf sich.
>>
>> Das ist C++ Syntax.
>
>
> Also könnte ich das in reinem C gar nicht anwenden.

Nein, aber es spielt doch keine Rolle WIE du nun einen neuen 
Speicherbereich für ein neues Array allokierst.
DAS solltest du in deiner Sprache mindestens mal beherrschen. Ansonsten 
würde ich vorschlagen du schaust dir die Grundlagen diesbezüglich erst 
nochmal an.

von Dirk B. (dirkb2)


Lesenswert?

Markus schrieb:
> Ich frage mich dann wieso, das trotzdem als Lösung vorgeschlagen wurde,
> denn ich hatte doch weiter oben C erwähnt.

Wer liest sich schon alle Beiträge und auch noch gründlich durch.
Da kommen dann Buzzwort-Antworten. (C++ ist besser, new statt malloc 
(obwohl man das auch nicht mehr nimmt))

von Markus (Gast)


Lesenswert?

Cyblord -. schrieb:
> Markus schrieb:
>> Cyblord -. schrieb:
>>> Markus schrieb:
>>>> Meine nächste Frage ist: was hat es mit new uint16_t[length] auf sich.
>>>
>>> Das ist C++ Syntax.
>>
>>
>> Also könnte ich das in reinem C gar nicht anwenden.
>
> Nein, aber es spielt doch keine Rolle WIE du nun einen neuen
> Speicherbereich für ein neues Array allokierst.
> DAS solltest du in deiner Sprache mindestens mal beherrschen. Ansonsten
> würde ich vorschlagen du schaust dir die Grundlagen diesbezüglich erst
> nochmal an.

Du hast Recht, ich versuche sowas gleich einmal umzusetzen.
Meinst du eigentlich konkret wie man dynamischen Speicher auf dem Heap 
anfordert und wieder freigibt? Ich habe es eigentlich schon mal 
durchgelesen, aber ich muss es dann einfach nochmals selber versuchen in 
Form von einer eigenen, praktischen Umsetzung.
Erst dann sitzen die Dinge bei mir so richtig, leider... :( Beim Lesen 
scheinen die Dinge immer erst so klar und beim Ausführen haperts dann 
oftmals.
Ich danke euch aber trotzdem für die bisherige Hilfe.

von Markus (Gast)


Lesenswert?

Dirk B. schrieb:
> Brauchst du denn noch die Originalwerte im Array oder kann das
> überschrieben werden?

Nein, Dirk.
Wenn ich es mir so richtig überlege, bräuchte ich das alte Array dann 
eigentlich nicht, weil ich ja die letzten Wert nie benötige. Das ist 
unnötiger Speicherverbrauch, wenn es slso fast 2 identische Arrays 
gibt..
Dann müsste ich einfach den Array der Funktion übergeben.
Die Elemente bis zu einem Index kopieren und den bestehenden Array mit 
dem dst_array überschreiben. Richtig?

von Stefan F. (Gast)


Lesenswert?

Ich gebe mal ein Konkretes Beispiel.

Wir haben ein Array mit etwas Text.
1
char text[]="Blablabla:Stefan";

Wir wollen nur den Namen ausgeben, nicht den ganzen Text. So bekommen 
wir einen Zeiger auf den Namen "Stefan":
1
int posi=strchr(text,':');
2
char* name=&text[posi+1];

Und den können wir jetzt an printf übergeben:
1
printf("Dein Name ist %s\n",name);

Umkopieren des Arrays war gar nicht nötig. Stattdessen haben wir einfach 
einen Zeiger auf das gewünschte Stück des Arrays übergeben.


Anstelle von
1
char* name=&text[posi+1];
hätte ich auch
1
char* name=text+posi+1;
schreiben können.

von Stefan F. (Gast)


Lesenswert?

Noch ein Beispiel.

Wir haben ein Array mit etwas Text.
1
char text[]="Stefan ist panne";

Wir wollen nur den Namen ausgeben, nicht den ganzen Text. In diesem Fall 
kann ich damit Leben, wenn der Rest des Arrays verloren geht, also 
terminiere ich den String einfach an der gewünschnten Stelle:
1
int posi=strchr(text,' ');
2
text[posi]=0;

Und den können wir jetzt an printf übergeben:
1
printf("Dein Name ist %s",name);

Umkopieren des Arrays war wieder nicht nötig.

Wenn ich den String (das Array) für spätere Verwendung nicht abschneiden 
bzw modifizieren will, muss ich der Ausgabefunktion eine Längenangabe 
mit geben:
1
int len=strchr(text,' ');
2
printf("Dein Name ist ");
3
fwrite(text,len,1,stdout);

Dieses mal musste ich auf fwrite() ausweichen, weil ich bei printf() 
keine Länge angeben kann.

von Dirk B. (dirkb2)


Lesenswert?

Stefanus F. schrieb:
> Dieses mal musste ich auf fwrite() ausweichen, weil ich bei printf()
> keine Länge angeben kann.

Doch, geht:
1
printf("Dein Name ist %.*s", len, name);

von Stefan F. (Gast)


Lesenswert?

Dirk B. schrieb:
> Doch, geht:printf("Dein Name ist %.*s", len, name);

Oh cool, das kannte ich noch nicht.

Kleine Korrektur:

printf("Dein Name ist %s",name);
printf("Dein Name ist %.*s", len, name);

Da gehört die Variable "text" hin, nicht "name".

Beitrag #5717914 wurde von einem Moderator gelöscht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.