Autor Beitrag
ibh_compucat
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 130

Win 2000, Win 8.1
D6, Ent. XE5 Ent.
BeitragVerfasst: Di 21.09.10 11:08 
Hallo zusammen,

ich muss einen kleinen Ausflug aus meiner Delphi Welt in die Entwicklungsumgebung eines embedded Processors machen und der lässt sich nur in C++ programmieren. Mir ist auch bekannt, dass C++ mit nullterminierten Strings arbeitet und ich habe dort eine Variable als array von char HS[20] deklariert.


volatile char HS[20]; // HilfsString
volatile Char s[1];

Dazu habe ich 2 Fragen:

1. wie kann ich z.B. das 3. Zeichen abfragen, bei Delphi: s := HS[3];

2. wie kann ich das abgefragte Zeichen mit einem vorgegebenen Zeichen vergleichen,
bei Delphi: if (s = '>') . . .


Das funktioniert beides nicht so unter C++, aber wie?

schöne Grüße ibh_compucat

_________________
Was du nicht begreifst, kannst du nicht verlernen!
shadow123
Hält's aus hier
Beiträge: 6
Erhaltene Danke: 1



BeitragVerfasst: Di 21.09.10 11:36 
Hallo,

solange du den Index nicht überschreitest kannst du auch in C/C++ wie in Delphi auf Array-Inhalte zugreifen:
s[0] = HS[3];
Das vorausgesetzt, wenn du nur auf ein Zeichen zugreifen willst.

Zu 2.: Den Vergleich kannst du ebenfalls einfach über die Indizierung des Arrays machen:
for(int i = 0; i < 20; i++) {
if(HS[i] == s[0]) {
cout << "treffer!" << endl;
break;
}
}

Ich hoffe ich konnte dir helfen.

MfG
Jakob_Ullmann
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1747
Erhaltene Danke: 15

Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
BeitragVerfasst: Di 21.09.10 15:06 
Alternativ wäre die string-Klasse zu nennen, die bei C++ in der Standardbibliothek ist.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
#include <iostream>
#include <string>

int main(void)
{
    std::string str = "Hallo";
    char s = str[0];
    // oder
    s = str.at(0); // EDIT: Meinte natürlich str.at() und nicht str.of()
}


Du kannst bei dieser String-Klasse sogar Vergleiche mit dem == Operator machen, statt strcmp() zu benutzen. Ist um einiges angenehmer als die C-Strings.

Weiteres findest du hier: de.wikibooks.org/wik...henketten#Einleitung

Abgesehen davon, dass sie die Lesbarkeit erhöhen, gibt es eigentlich nichts, was gegen die string-Klasse spricht. Sogar = kann man statt strcpy() zum Zuweisen nutzen.


Zuletzt bearbeitet von Jakob_Ullmann am Di 21.09.10 18:37, insgesamt 1-mal bearbeitet
ibh_compucat Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 130

Win 2000, Win 8.1
D6, Ent. XE5 Ent.
BeitragVerfasst: Di 21.09.10 16:32 
Hallo,

ich arbeite wie ein Maikäfer daran, aber ich komme trotzdem nicht weiter:

bei dem ersten Vorschlag von shadow123 funktioniert z.B. die Zuweisung s[0] = HS[3] bei mir leider nicht. Der Compiler meckert zwar nicht, aber das Ergebnis ist nicht wie es sein soll.
bei dem zweiten Vorschlag von Jakob habe ich elementarere Probleme: der Compiler findet <string> und <iostream> nicht, ansonsten scheint mir diese Lösung simpel und sehr delphiähnlich.

Ich suche weiter . . .

ibh_compucat

_________________
Was du nicht begreifst, kannst du nicht verlernen!
Jakob_Ullmann
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1747
Erhaltene Danke: 15

Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
BeitragVerfasst: Di 21.09.10 17:30 
Wie gesagt, iostream und string gehören eigentlich zur Standardbibliothek. Ich weiß allerdings nicht, inwiefern die bei Microprozessoren wichtig ist oder nicht. Also auf jeden Fall wirst du dich mit den C-Strings herumschlagen müssen. ;-)

Kleiner Tipp noch: char[1] ist ziemlich sinnlos. Das letzte Element muss nämlich "\0", also der ASCII-Wert 0, sein. Dient der Abgrenzung, da C-Strings ja nicht umsonst nullterminiert sind. Ein Zeichen speicherst du am besten mit char. Für einen String, der ein Zeichen hat (plus ein weiteres, nämlich \0), musst du char s[2] deklarieren.

Guckst du hier: de.wikibooks.org/wik...rung:_Arrays#Strings

EDIT: Was du machst, wenn du s[0] überschreibst, ist ziemlich fatal. Bei einem Char-Array mit einem Element, gibt es wie gesagt nur die \0. Wenn du die überschreibst, werden alle Funktionen, die Strings erwarten, einfach bis zur nächsten \0 lesen. Da du aber die anderen Variablen in ihrer Adresse nicht änderst (ja, Array = Pointer, also *(s+2) = s[2]), hat das nur auf die eine Variable Auswirkungen.
ibh_compucat Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 130

Win 2000, Win 8.1
D6, Ent. XE5 Ent.
BeitragVerfasst: Di 21.09.10 17:59 
Hallo Jakob,

der Hinweis ist sehr interessant, ich habe inzwischen auch die string.h gefunden.
Die Erklärung ist gut, aber ich steh' mit den pointern nun mal auf Kriegsfuß. Ich werde versuchen mich da durchzuarbeiten!
Erstmal vielen Dank.

Gruß ibh_compucat

_________________
Was du nicht begreifst, kannst du nicht verlernen!
Jakob_Ullmann
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1747
Erhaltene Danke: 15

Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
BeitragVerfasst: Di 21.09.10 18:15 
Du musst nicht viel über Pointer wissen. Ein Pointer speichert nun einmal die Adresse einer Variable im Speicher. Mit der kannst du ähnlich wie mit Zahlen rechnen. Ein Array des Datentyps x ist nichts anderes als ein Pointer auf das erste Element. Das schreibst du dann so:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
int a[5] = {12345};
int *b;

for (int i = 0; i <= 5; i++)
  std::cout << a[i] << " vs. " << *(a + i)
            << std::endl;

for (b = a; *b != 5; b++)
  std::cout << *b << std::endl;


Mit *b liest du eben den Wert aus. Mit b++ erhöhst du b, jedoch nicht immer um eins, sondern immer um den Speicherbedarf eines Elements des jeweiligen Typen. Ist bei int glaube ich 2 oder 4 Bytes, bei char 1 Byte. Und nichts anderes machst du bei Strings. Du definierst ihn als ein Array of char.

ausblenden C#-Quelltext
1:
2:
3:
4:
char str[] = {'A''f''f''e''\0'};
// Besser:
char str[5];
strcpy(str, "Affe");


Was zur Ausgabe:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
void meineAusgabe(char *str)
{
  while (*str)  // also solange *str etwas anderes als 0 ist
  {
    std::cout << *str << std::endl;
    str++;      // auf das nächste Zeichen zeigen
  }
}


Hoffe, das hilft dir zum Verständnis. Damit weißt du übrigens auch, wie du von einem String ganz einfach die ersten fünf Zeichen wegnehmen kannst:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
#include <cstring>

void entferneZeichen(char **str; int anzahl) // Pointer auf Pointer.
{
  if (strlen(*str) > anzahl)
    *str += anzahl;
  else
    throw Error("entferneZeichen(): str ist zu kurz.");
}


Noch etwas: string.h ist womöglich nicht der C++-Header <string>, sondern der C-Header <string.h>, der in C++ mit <cstring> eingebunden wird. Der enthält Funktionen für C-Strings, aber eben nicht die String-Klasse. Genauso wie <cmath> dem C-Header <math.h> entspricht. Und auch <iostream> und <iostream.h> sind übrigens nicht das gleiche.
shadow123
Hält's aus hier
Beiträge: 6
Erhaltene Danke: 1



BeitragVerfasst: Di 21.09.10 18:26 
Hallo ibh_compucat,

du hast allem Anschein nach einen reinen C-Compiler. Da hast du keine Standardfunktionalität von C++.

Es kommt ganz drauf an, was du mit den Zeichenketten anstellst. Werden diese als richtige Strings verarbeitet oder dienen die lediglich als byte-Array?
Wenn das Strings sein sollen, dann ist das Argument korrekt, dass du das '\0'-Byte an das Ende der Zeichenkette hinzufügen musst (d. h. auch Platz dafür haben musst).

In der string.h gibt es viele nützliche Funktionen rund um das Arbeiten mit Strings. Z. B. für den String-Vergleich die strcmp(const char* s1, const char* s2) ...
Jakob_Ullmann
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1747
Erhaltene Danke: 15

Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
BeitragVerfasst: Di 21.09.10 18:33 
Wie ich schon sagte, das \0 ist wichtig, um den String abzugrenzen. Bei kannst du halt ohne weiteres den reservierten Bereich überschreiben (oder eben lesen ;-) ). Ohne zu kontrollieren, ob das zum String gehört. Und ohne zu prüfen, ob das, was da steht, denselben Typ hat (falls man das so formulieren darf). Du kannst so eben ziemlich viel Unsinn anstellen. Deshalb hat die Funktion meineAusgabe() ja auch eine Längenprüfung. Was passiert, wenn das nicht dabei ist, kannst du ja ausprobieren.

Wenn er allerdings nur einen C-Compiler hätte, hätte er deinen Code gar nicht compilieren können, weil C weder std::cout, noch den Operator << in diesem Zusammenhang kennt (eben nur als SHIFT-LEFT).

ÜBRIGENS @ibh_compucat: Du weißt aber, wozu das volatile da ist?
ibh_compucat Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 130

Win 2000, Win 8.1
D6, Ent. XE5 Ent.
BeitragVerfasst: Di 21.09.10 19:03 
es könnte sein, daß ich nur einen c-compiler habe, da std::cout immer bemeckert wurde. Aber ich habe nun soviele (und auch konkrete) Beispiele, daß ich an die Erforschung gehen kann.
Ich möchte mich bei euch beiden herzlich bedanken und melde mich noch einmal, wenn alles läuft.

Gruß ibh_compucat

_________________
Was du nicht begreifst, kannst du nicht verlernen!
Jakob_Ullmann
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1747
Erhaltene Danke: 15

Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
BeitragVerfasst: Di 21.09.10 19:08 
Falls es wirklich nur ein C-Compiler ist: Ausgaben und Eingaben gehen dann so:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
#include <stdio.h>

int main(void)
{
  int a;
  printf("Wie alt bist du? >");          /* Ausgabe */
  scanf("%i", &a);                       /* Eingabe; unbedingt mit Pointer auf a! */
  printf("Du bist %i Jahre alt.\n", a);  /* Ausgabe */
  return 0;                              /* Beenden */
  /* oder */
  exit(EXIT_SUCCESS);
}


Es könnte auch durchaus sein, dass er keine //-Kommentare, sondern nur die /*...*/ kennt.
ibh_compucat Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 130

Win 2000, Win 8.1
D6, Ent. XE5 Ent.
BeitragVerfasst: Sa 25.09.10 17:37 
ich habe in den letzten Tagen eine Menge über Char Arrays und nullterminierte C-Strings gelernt (und z.B. den Unterschied von 'A' und "A"). Die Pointer sind mir immer noch nicht ans Herz gewachsen, aber ich habe alles ans laufen gebracht.
Für die guten Tipps nocheinmal recht herzlichen Dank!

Gruß ibh_compucat

_________________
Was du nicht begreifst, kannst du nicht verlernen!