[erledigt] char*/String-Frage

Hallo allerseits!

In einer Bibliothek befindet sich eine Funktion, die ein char* zurück gibt. Wenn ich diese Funktion mit

  String foo=funktion(parameter);

aufrufe, ist die Ausgabe via Serial.print(foo) korrekt. Wenn ich jedoch

  char* foo=funktion(parameter);

schreibe, ist die Ausgabe fehlerhaft. Wieso?

Hier Header und ein Ausschnitt der cpp-Datei der Bibliothek:

gDS1307.h

// gDS1307.h

#ifndef GDS1307_H
#define GDS1307_H

#include <Arduino.h>
#include <Wire.h>

class gDS1307
{
 private:
  byte i2cAddress;
  char result[3]; // Hier steht jeweils die Rueckgabe drin
 public:
  gDS1307(byte i2cAddress=0x68);
  void init(); // Initialization
  char* decodeDOW(byte); // Decode day of week
  char* decodeHours(byte); // Decode hours
  char* decodeMinutes(byte); // Decode minutes
  char* decodeSeconds(byte); // Decode seconds
  char* decodeDate(byte); // Decode date
  char* decodeMonth(byte); // Decode month
  char* decodeYear(byte); // Decode year
  void set(byte, byte, byte, byte, byte, byte); // set clock
                                                // (h,m,dow,d,m,y)
};

#endif

// eof

gDS1307.cpp

// gDS1307.cpp

#include "gDS1307.h"
#include <Arduino.h>
#include <Wire.h>

...

char* gDS1307::decodeSeconds(byte s_)
{
  byte lowNibble=s_&15;
  byte highNibble=(s_/2/2/2/2) & 7;

  switch(highNibble)
  {
    case 0: result[0]=48; break;
    case 1: result[0]=49; break;
    case 2: result[0]=50; break;
    case 3: result[0]=51; break;
    case 4: result[0]=52; break;
    case 5: result[0]=53; break;
    case 6: result[0]=54; break;
    case 7: result[0]=55; break;
    case 8: result[0]=56; break;
    case 9: result[0]=57; break;
  }
  switch(lowNibble)
  {
    case 0: result[1]=48; break;
    case 1: result[1]=49; break;
    case 2: result[1]=50; break;
    case 3: result[1]=51; break;
    case 4: result[1]=52; break;
    case 5: result[1]=53; break;
    case 6: result[1]=54; break;
    case 7: result[1]=55; break;
    case 8: result[1]=56; break;
    case 9: result[1]=57; break;
  }

  result[2]=0;

  return(result);
}

...

Im Anhang außerdem ungekürzte Versionen der betreffenden Dateien.

Fehlen Infos?

Gruß

Gregor

191211_gDS1307-Test-II_0_5.ino (1.16 KB)

gDS1307.h (726 Bytes)

gDS1307.cpp (7.48 KB)

Ich sehe dein Problem nicht!

#include <Streaming.h>


 char result[3] {0,0,0}; // Hier steht jeweils die Rueckgabe drin



char* decode(byte s_)
{
   result[0] = (s_>>4)+'0';
   result[1] = (s_&0xf)+'0';
   result[2] = 0;
   return result;
}


void setup() 
{
  Serial.begin(9600);
  Serial << "Start: "<< __FILE__ << endl;
  char* foo;
  foo = decode(0x01);  Serial << foo << endl;
  foo = decode(0x02);  Serial << foo << endl;
  foo = decode(0x09);  Serial << foo << endl;
  foo = decode(0x10);  Serial << foo << endl;
  foo = decode(0x11);  Serial << foo << endl;
  foo = decode(0x12);  Serial << foo << endl;
}

void loop() 
{

}

Du machst also was anderes falsch!

Die Frage hat sich erledigt. Ich hätte zwar gerne zweistellige Rückgaben gehabt (deshalb char* für Zahlen kleiner 9), aber das kann ich auch anders erledigen. Nach der Umstellung der Rückgabe von char* auf byte funktioniert alles wie es soll.

Gruß

Gregor

Ich verstehe dich nicht!

Möchtest Du möglicherweise eine Terminierung der Zeichenkette?

result[2]='\0';

agmue:
Möchtest Du möglicherweise eine Terminierung der Zeichenkette?

result[2]='\0';

Ist das nicht gleichbedeutend mit

result[2]=0;

?

Gruß

Gregor

Ist es.

Hallo,

moment, kann nicht sein. :o
Wir schreiben doch ASCII Code von 0...9 und A ... z.
Diese 0 ist Ziffer 0 und damit ASCII Code 48.
'\0' ist ein Steuerzeichen und ASCII Code 0 bzw. NUL.

Laut meinem Verständnis auch logisch, sonst würde jede Leseoperation bei der Ziffer 0 enden und nicht beim Nullterminator.

Doc_Arduino:
Diese 0 ist Ziffer 0 und damit ASCII Code 48.

Nein. Das wäre '0'

0, '\0' und NULL sind das Gleiche. Ich nehme aber eher '\0' für Terminatoren und NULL/nullptr für Zeiger.

Hallo,

jetzt bin ich durcheinander. :o

Das ist nur so wie ihr sagt weil das ein char Array ist?
Was ich jetzt komplett nicht mehr verstehe.
Weil meine Testwert 0 ... 3 sowohl in ein char wie auch in den int Wertebereich passen.
Warum wird ein char Array anders interpretiert?
Bin gerade neben der Spur glaube ich. :confused:

int werte1[] = {0, 1, 2, 3};
// char werte2[] = {0, 1, 2, 3}; // funktioniert nicht
char werte2[] = {'0', '1', '2', '3'};

void setup(void) {
  Serial.begin(9600);

  for (auto &v : werte1)
  {
    Serial.println(v);
  }

  for (auto &v : werte2)
  {
    Serial.println(v);
  }
}

void loop(void) {
  
}
// char werte2[] = {0, 1, 2, 3}; // funktioniert nicht

Das sind die Dezimal-Werte der ASCII Zeichen. Damit bist du bei den Steuerzeichen

Doc_Arduino:
moment, kann nicht sein. :o

Doch doch....
Dieser Teil stammt aus C und ist (leider?) schwach typisiert.
char ist nicht wirklich "Buchstabe", sondern definiert, als die kleinste adressierbare Einheit.

Nochmal:
Ein char ist die kleinste adressierbare Einheit.
char bedeutet hier nicht unbedingt Buchstabe. Auch wenn es oft/meist dafür verwendet wird.

Der übliche C-String ist nur eine Vereinbarung/Konvention.
Eben die Null am Ende.
Der Compiler selber kennt sowas nicht wirklich.
Ein paar Library Funktionen halten sich an diese Vereinbarung. Längst nicht alle.

char a = 0:
ist das gleiche wie
char a = '\0';

Beide Varianten schreiben eine binäre Null in die Variable.
Du könntest da auch eine 8 rein schreiben, wenn dir danach ist

Schreibt eine dezimale 8 in die Zelle

char a = '\10';

:smiling_imp: :smiling_imp:

Hallo,

was ist schwach typisiert?

Bleibe mal beim

Serenifly:

// char werte2[] = {0, 1, 2, 3}; // funktioniert nicht

Das sind die Dezimal-Werte der ASCII Zeichen. Damit bist du bei den Steuerzeichen

Warum sind das plötzlich Dezimalwerte vom ASCII Zeichen? Das ist das was ich nicht verstehe.
Nur weil das ein char und nicht int Array ist? Obwohl das alles in die Wertebereiche passt.

Hi

char[]={0,1,2,3}; funktioniert schon - nur scheitert .print an der /0, Die Ihm Das das Ende des C-String signalisiert.
Also char[2] wäre immer noch 2 - nur angezeigt bekommst Du Das halt nicht von .print.

... meinem Verständnis nach :wink:

MfG

Weil du die Ziffern ohne die einzelnen Anführungsstriche schreibst!

0 ist 0
'0' ist 48

Hallo,

wir verstehen uns glaube ich noch nicht. Mein Problem ist noch nicht deutlich gewurden, denke ich.
Ich fange nochmal an.
Wo ist der Unterschied zwischen ... ?

int werte1[] = {0, 1, 2, 3};
char werte2[] = {0, 1, 2, 3};

Warum wird die char 0 anders interpretiert wie die int 0 ?
Diese 0 paßt in beide Wertebereiche.

Hallo,

würde bedeuten, dass man char Arrays wirklich nur für Zeichenketten verwenden kann?
Man ist gezwungen für Integerwerte, auch wenn diese in den Wertebereich von char passen und damit char ausreichend wäre, dann ein int Array verwenden?
Kann man das so sagen? Dann hätte ich mich wieder gefangen.

Denke daran dass print()/println() mehrfach überladen ist. So gibt es print(char*) und print(int). Gerade bei der 0 hat der Compiler da Probleme das zu unterscheiden und wählt nicht immer das aus was du willst. Das ist der Grund weshalb nullptr eingeführt wurde!

Bei write() gibt oder gab es das gleiche Problem. Vor allem in der Wire Klasse wo Wire.write(0) eine häufige Operation ist

Du kannst char ruhig für Zahlen verwenden. Das ist halt ein Byte mit Vorzeichen. Aber wenn man das an Funktionen wie print() übergibt braucht man eventuell Casts damit die richtige Version aufgerufen wird

Hallo,

so langsam dämmerts mir wieder jetzt wo du das erwähnst. Hatten wir das nicht vor langer Zeit mal ähnlich mit Serial.write wo du mir sagstest ich muss vorher auf int casten damit das sicher klappt? Irgendwie war doch was gewesen? Dann wäre jetzt alles wieder okay für klare Bilder. :wink:

Edit:
alles klar, alles geklärt, hatte sich jetzt zeitlich überschnitten.
Danke!