Forum: PC-Programmierung C-Code Probleme mit structs


von Tom (Gast)


Lesenswert?

Hallo,

ich hoffe ich bin nicht im völlig falschen Forum.

Folgendes Problem:

Ich habe für die Bearbeitung von Daten structs angelegt und diese werden 
bei Programmstart mit Werten aus einer Datei geladen. Das funktioniert 
wunderbar.

Nun möchte ich im Laufe der Abarbeitung des Programms auf diese Daten 
zugreifen.
Leider liegen die Werte nicht mehr so wie abgelgt vor. Scheinbar.

Kontrolliere ich den Inhalt jedes Feldes gleich nach übertragen in die 
Variable mit einer Konsolenausgabe ist der Wert i.O.
Kontrolliere ich den gleichen Wert nach auslesen aller Werte des 
Structs, leigen falsche Werte vor. Zur Verdeutlichung der Quellcode 
dazu:

struct profil_setup
{
int id_modul;
int led_nummer;
char led_art[2];
int wert;
}settings[300];

struct profile_basics
{
char name[20];
int anzahl_led;
int time_to_next;
int direction;
struct profile_setup settings[300];
} profile[20];

//Funktion zum einlesen der Daten wird zum Programmstart aufgerufen
//Kontrollausgabe ergibt richtigen Inhalt

//nun werden die Abgelegten Daten in Variablen gelegt und durch eine
//Funktion verwendet. Zur Kontrolle werden diese Variablen nochmals
//ausgegeben:

for(i=0;i<20;i++)
{
if((strcmp(profile[i].name,dateiname)) ==0)
{
for(y=0;y<profile[i].anzahl_led;y++)
{
modul_id = profile[i].settings[y].id_modul;
//dieser Wert stimmt immer

nmr= profile[i].settings[y].led_nummer;
//an dieser stelle mittels printf() stimmt der Wert für nmr noch
value = profile[i].settings[y].wert;
//an dieser stelle mittels printf() stimmt der Wert für value noch

led_art = profile[i].settings[y].led_art;
//dieser Wert stimmt immer

//erfolgt die gleiche Ausgabe an dieser Stelle hat der Wert für
//nmr den Wert des value
//es scheint irgendwie ein Überschreiben des Wertes
//nmr durch den Wert value zu passieren. Woher könnte das
//kommen?
}
}
}

Ist das struct falsch angelegt oder gibt es da Probleme bei der 
Speicherzuweisung? Ich bin nicht "Der" Programmierer..daher meine Frage 
dazu.

Vielen Dank schonmal für die Antworten

Thomas

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ist Dir aufgefallen, daß Du zusätzlich zu den 20 Arrays namens 
"settings" im Array profile nochmal ein Array namens settings anlegst?

Trenne Strukturdeklaration und Arraydefinition, das macht das ganze 
lesbarer.

Im übrigen wird C-Code noch lesbarer, wenn er vernünftig formatiert und 
eingerückt wird, obendrein unterstützt dieses Forum ein einfaches 
Syntaxhighlighting, das Du erhältst, wenn Du Deine C-Sourcen in [С] ... 
[/С] einschließt.

Desweiteren wäre interessant, auf welche Art und Weise das Einlesen aus 
der Datei erfolgt und welche Datentypen Deine Variablen nmr und value 
haben.

von Tom (Gast)


Lesenswert?

danke fürs erste Feedback

das Einrücken war, scheint aber irgendwie abhanden gekommen zu sein. 
Formatierung!! das wusste ich nicht, habe hier noch nicht so oft 
gepostet..ich denk demnächst dran.

Das mit dem struct settings habe ich deshalb gemacht, um einen direkten 
Bezug zu dem struct herzustellen. Es soll element des struct profile 
sein.
Wie würde das anders gehen?

nmr ist auch ein int und value ein unsigned int.

Danke!

von Karl H. (kbuchegg)


Lesenswert?

Tom wrote:

> Das mit dem struct settings habe ich deshalb gemacht, um einen direkten
> Bezug zu dem struct herzustellen. Es soll element des struct profile
> sein.
> Wie würde das anders gehen?

Du deklarierst erst mal deinen Datentyp:
1
struct profil_setup
2
{
3
  ...
4
};

Damit sagst du dem Compiler: Pass mal auf, so sieht ein profil_setup
aus. Wenn in Folge also davon die Rede ist, das ist das Ding das ich
damit meine.

Weiters deklarierst du dir die andere struct
1
struct profile_basics
2
{
3
  char name[20];
4
  int anzahl_led;
5
  int time_to_next;
6
  int direction;
7
  struct profile_setup settings[300];
8
};

Soweit so gut. Der Compiler weiss jetzt wie der Datentyp aussieht
und was damit gemeint ist, wenn du von profile_basics bzw.
profile_setup als Datentyp sprichst.

Und dann definierst du deine 20 profile Variablen
1
struct profile_basics profile[20];

Die 300 settings Variablen in deiner Urversion braucht anscheind
kein Mensch.
Jedes einzelne der 20 profile Array Elemente besitzt selbst ein
300 Elemente umfassendes profile_setup Member. Dsa hast du ja
hier so vereinbart
1
struct profile_basics
2
{
3
  char name[20];
4
  int anzahl_led;
5
  int time_to_next;
6
  int direction;
7
  struct profile_setup settings[300];    // jedes profile_basics Element
8
                                         // hat automatisch 300 profile_setup
9
                                         // Elemente, die allesamt unter dem
10
                                         // Namen settings laufen
11
};

In Summe gibt es also 6000 profile_setup!
Jedes profile[i] verfügt über 300, und da es 20 profile gibt, gibt
es insgesamt 6000 profile_setup. Bist du sicher, das du das so
wolltest?

>
> nmr ist auch ein int und value ein unsigned int.

Welchen Typ hat die freistehende led_art?

Ansonsten: Im geposteten Code-Schnipsel gibt es keine Erklärung für
dein Problem. Der Fehler muss also wo anders liegen. Hast du mal
überprüft, ob auch wirklich alle Array Zugriffe immer innerhalb
des Arrays liegen (egal welches Array). Besonders das Array
led_art im profile_setups hat es mir angetan. Ein char Array der
Länge 2 ist ungewöhnlich, weil es eigentlich meistens zu nichts
wirklich gut zu gebrauchen ist.
Einen String darin speichern wird man nicht tun, weil der String dann
nur aus max. 1 Nutzzeichen bestehen kann -> Da kann ich genausogut
einen einzelnen char dafür hernehmen und spare die hälfte Speicher.
Eventuell könnten da noch irgendwelche Codes drinn liegen, das kann ich
aber von hier nicht beurteilen.

Ansonsten: Die meisten Debugger können auch direkt den Speicher
überwachen. Entweder indem man ein spezielles Memory-Fenster aufmacht
oder indem man einen Watch-Point setzt. Sinn der Sache ist es immer
am Programm vorbei einen Blick direkt in den Speicher zu erlangen
und rauszukriegen, wann genau ein Byte seinen Wert ändert.

von Tom (Gast)


Lesenswert?

Super, das mit den structs sieht schon eleganter aus. Ändere ich sofort.

Und ja, das Char-Array led_art scheint diese Problem zu verursachen, 
denn nach Zugriff auf dieses erscheint dieser fehler. Es beinhaltet 
jeweils nur eine Kennung aus Buchstaben. z.B. "WS" oder "IR " oder "UV" 
für die Art der LED. darüber wird eine entscheidung in der 
Ansteuerroutine getroffen. Ich musste beim Beschreiben des Array auch 
mit '\0' abschließen, sonst gab es auch dort Probleme. Um dieses zu 
umgehen dachte ich schon an eine Lösung per Ziffer.
Was wäre denn noch eine praktische Lösung dafür?

Tom

von Karl H. (kbuchegg)


Lesenswert?

Tom wrote:
> jeweils nur eine Kennung aus Buchstaben. z.B. "WS" oder "IR " oder "UV"
> für die Art der LED.

Dafür brauchst du aber ein Array der Länge 3.
Du hast den obligatorischen '\0'-Character am Ende des Strings
vergessen

http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F

von Tom (Gast)


Lesenswert?

Hallo,

also ich habe dieses char -Array immer so beschrieben:

led_art[0] = 'U';
led_art[1] = 'V';
led_art[2] = '\0';

also nur symbolisch. Ich dachte für das Stringendezeichen ist nur eine 
Stelle erforderlich? habe mal die Größe auf 3 erhöht und ja, es klappt. 
Aber wie kommt das denn dann zustande? 0-2 sind doch 3 Stellen?



Danke schonmal! Die Tips und Hilfen hier sind sehr hilfreich! Ein großes 
Lob an eurer Forum!!!

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

In Deinem Quelltext steht aber

   char led_art[2];

Das ist ein Array mit exakt zwei Elementen, die über die Indices 0 und 
1 angesprochen werden können.

Nein, die in den Klammern angegebene Zahl ist nicht der größte 
erlaubte Index, sondern die Anzahl der Elemente.

von Tom (Gast)


Lesenswert?

Jo, ich glaube das war eine Erkenntnis jetzt, die mir so einige Sachen 
aus der Vergangenheit erklärt.
Schon etwas peinlich aber naja. Danke für das Klarstellen nochmals!

Frohe Pfingsten!

Tom

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.