Forum: Compiler & IDEs Frage zur sprintf-Fkt mit Variablen


von Stefanie (Gast)


Lesenswert?

Hallo,

ich möchte gerne die Formatierung der sprintf-Funktion über die Variable 
digits steuern
zB:
statt
sprintf(string,"%3d",value);

sprintf(string,"%"+digits+"d,value);
klappt nicht!

Wie mache ich es, dass "digits" in diesem Zusammenhang al0s Variable 
gesehen wird und den Zahlenwert ersetzt?

von Ralf (Gast)


Lesenswert?

In ein Zeichen verwandeln? Wenn neun Stellen reichen:
1
char c=(char)('0'+digits)

von Stefanie (Gast)


Lesenswert?

Sorry, versteh ich nicht ganz.

Ich möchte halt das der Wert der Variable digits an der Stelle 
eingesetzt wird, wie hier die 3 :
sprintf(string,"%3d",value);

von Ralf (Gast)


Lesenswert?

Ääh, hab die Variablen verwechselt. Also so:
1
char digits=(char)('0'+n);
Zeichenketten addieren geht nur mit AnsiString. Also erst schön mit 
strncat (oder so ähnlich) zusammenbasteln. Aah, fällt mir noch ein:
1
uint8_t n=9; // maximal!
2
formatString[]="%Xd";
3
formatString[1]=(char)('0'+n);
4
sprintf(string,formatString,value);
Das müsste auch gehen.

von Stefanie (Gast)


Lesenswert?

Super, danke ich hab's verstanden!

von Jörg G. (joergderxte)


Lesenswert?

Du solltest auch folgendes verwenden können:
1
sprintf(string,"%*d", digits, value);
d.h. der Asterisk anstatt einer Zahl.

von Klaus W. (mfgkw)


Lesenswert?

1
  int digits = 3;
2
  int value = 12;
3
  char   string[20];
4
5
  sprintf( string, "%*d", digits, value );
(falls ich die Frage richtig verstanden habe)

von Klaus W. (mfgkw)


Lesenswert?

@Jörg G.:

wenigstens einer, der auch mal die man-page zu Formatstrings gelesen hat 
:-)

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:
> @Jörg G.:
>
> wenigstens einer, der auch mal die man-page zu Formatstrings gelesen hat
> :-)


:-)

Und ehe es diese Möglichkeit gab, hat man sich halt daran erinnert, dass 
der Formatstring auch nur ein String ist. Es spricht also nichts 
dagegen, sich diesen ebenfalls mittels Programm generieren zu lassen
1
  char FormatString[10];
2
3
  sprintf( FormatString, "%%%dd", digits );
4
  sprintf( string, FormatString, value );


Aber mit dem * ist es natürlich eleganter, solange man nur eine Zahl 
ersetzen lassen will. Will man noch zusätzliche 'Optionen' in den 
Formatstring bei Bedarf einbauen (führende 0-en, Vorzeichen, etc.) dann 
ist die Generiermethode immer noch kein schlechter Weg.

von Stefanie (Gast)


Lesenswert?

Hallo,

ich hab nun folgendes getestet:
1
 
2
 char FormatString[10];
3
4
  sprintf( FormatString, "%%%dd", digits );
5
  sprintf( string, FormatString, value );

Bekomme vom Compiler aber leider folgende Fehlermeldung:

function argument #2 of type 'flash unsigned char[10]' is incompatible 
with required parameter of type 'flash unsigned char*'

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Der komische Compiler pacht automatisch String-Literale ins Flash und 
erwartet sie dort auch für  *printf*-Funktionen?

Unterstützt der keine nicht-konstanten Format-Strings?

von Stefanie (Gast)


Lesenswert?

Und bei dieser Methode wird ständig nur "d  " ausgegeben:
1
  int digits = 3;
2
  int value = 12;
3
  char   string[20];
4
5
  sprintf( string, "%*d", digits, value );

von Klaus W. (mfgkw)


Lesenswert?

Dann musst du mal die Doku zu deinem System bemühen; vielleicht ist
das sprintf() dort ja nicht Std-C?

von Stefanie (Gast)


Lesenswert?

Dort steht folgendes:


int sprintf(char *str, char flash *fmtstr [ , arg1, arg2, ...])
      this function is identical to printf except that the formatted 
text is placed in the null terminated character string str.
The function returns the number of outputed characters.

von Klaus W. (mfgkw)


Lesenswert?

Dann musst du die Doku zu deinem printf() bemühen ...

von Stefanie (Gast)


Lesenswert?

OK, hier ist sie

int printf(char flash *fmtstr [ , arg1, arg2, ...])


      outputs formatted text, using putchar, according to the format 
specifiers in the fmtstr string.
The format specifier string fmtstr is constant and must be located in 
FLASH memory.
The implementation of printf is a reduced version of the standard C 
function.
This was necessary due to the specific needs of an embedded system and 
because the full implementation would require a large amount of FLASH 
memory space.
The function returns the number of outputed characters.
...

von Guru (Gast)


Lesenswert?

Du musst, wie schon geschrieben, die Doku von printf anschauen. Die 
besteht nicht nur aus dem von Dir geposteten Text sondern auch aus der 
Beschreibung des Formatstrings.

Es ist zu prüfen ob dies hier:
>The implementation of printf is a reduced version of the standard C
>function.

evtl. auch bedeutet, das '*' nicht unterstützt wird.

Wenn '*' nicht unterstützt wird, dann musst Du eine eigene 
Ausgabefunktion bzw. Stringerstellungsfunktion basteln, die eine 
variable Anzahl Stellen ausgibt.

von Guru (Gast)


Lesenswert?

Irgendwie kommt mir das auch komisch vor.

>ich hab nun folgendes getestet:


> char FormatString[10];

>  sprintf( FormatString, "%%%dd", digits );
>  sprintf( string, FormatString, value );

>Bekomme vom Compiler aber leider folgende Fehlermeldung:

>function argument #2 of type 'flash unsigned char[10]' is incompatible
>with required parameter of type 'flash unsigned char*'

Auf welche Zeile genau bezieht sich die Fehlermeldung? Das einzige wo Du 
ein unsigned char[10] übergibst ist das erste printf. FormatString hat 
aber gar keinen Type-Modifier "flash". Ist das wirklich der 
Originaltext?

von Stefanie (Gast)


Lesenswert?

Na super :-(

Gibt's wo ein fertiges Beispiel für int und float-Ausgabe?

Ich möchte  %d und %3.1f nutzen...

von Guru (Gast)


Lesenswert?

>Gibt's wo ein fertiges Beispiel für int und float-Ausgabe?

Häh? Das sind absolute Grundlagen. Dafür gibts höchstens in einem 
Lehrbuch Beispiele.

Klär doch erstmal die Punkte die offen sind.

von Guru (Gast)


Lesenswert?

Sag mal, handelt es sich wirklich um den GCC? Welcher Prozessor?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

In der Doku steht doch eindeutig, daß der Format-String im Flash sein 
muss. Also werden keine dynamisch erzeugten Formatstrings unterstützt.

von Guru (Gast)


Lesenswert?

>In der Doku steht doch eindeutig, daß der Format-String im Flash sein
>muss. Also werden keine dynamisch erzeugten Formatstrings unterstützt.

Hm. Das erklärt aber nicht, warum das hier:
1
sprintf( string, "%*d", digits, value );

nicht geht.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Guru schrieb:
>>In der Doku steht doch eindeutig, daß der Format-String im Flash sein
>>muss. Also werden keine dynamisch erzeugten Formatstrings unterstützt.
>
> Hm. Das erklärt aber nicht, warum das hier:
>
>
1
> sprintf( string, "%*d", digits, value );
2
>
>
> nicht geht.

Ak, ok. Das fällt im Zweifelsfalle fällt's unter "reduced version of the 
standard C function". ;-)

von Guru (Gast)


Lesenswert?

>Ak, ok. Das fällt im Zweifelsfalle fällt's unter "reduced version of the
>standard C function". ;-)

Genau!

Beitrag "Re: Frage zur sprintf-Fkt mit Variablen"

:-)

von Stefanie (Gast)


Lesenswert?

OK, dann programmier ich mir die Funktion selbst..

Hier erst mal der Code für die Integer-Ausgabe:
Die Übergabeparamter sind (int value, unsigned char digits)
[c]
unsigned char string[StringBufferSize];
unsigned char string_temp[StringBufferSize];
unsigned int digits_temp;
unsigned int i;


itoa(value, string_temp);

digits_temp = strlen(string_temp);

if(digits_temp < digits)
{
    for(i=0; i<((unsigned int)digits-digits_temp); i++)
    {
        strcat(string," ");
    }
}
strcat(string, string_temp);
[\c]

Dies funktioniert die meiste Zeit ganz gut, nur wenn manchmal stehen am 
Anfang des Strings noch alte Ergebnisse oder andere Zeichen.

Wie kann ich die beiden Arrays:
unsigned char string[StringBufferSize];
unsigned char string_temp[StringBufferSize];
bei der Deklaration initialisieren?

Seht ihr sonst im dem Code noch einen Fehler oder habt einen 
Verbesserungsvorschlag?

von Klaus W. (mfgkw)


Lesenswert?

An einer kompletten Funktion könnte man vielleicht Fehler sehen ....

Abgesehen davon, daß strcat() da vielleicht nicht besonders effizient 
ist.

Willst du die Leerzeichen links oder rechts angefügt haben?


Ggf. wäre es vielleicht sinnvoller, das Schreiben des Werts in einen 
String und das Auffüllen mit Leerzeichen auf eine gewünschte Länge 
(links oder rechts auffüllen) zu trrennen, sonst musst du das Auffüllen 
für int, unsigned int, short, float... jedesmal neu machen.

von Klaus W. (mfgkw)


Lesenswert?

1
#include <string.h>
2
3
// füllt einen String str links auf mindestens l_min Zeichen auf
4
// Achtung - keine Fehlerprüfungen!
5
// Der String muß groß genug sein (l_min+1).
6
// Rückgabe ist der String.
7
char *fill_l( char *str, size_t l_min, char fill_char )
8
{
9
  size_t l = strlen( str );
10
  if( l<l_min )
11
  {
12
    memmove( str+l_min-l, str, l+1 );
13
    memset( str, fill_char, l_min-l );
14
  }
15
  return str;
16
}
17
18
// füllt einen String str rechts auf mindestens l_min Zeichen auf
19
// Achtung - keine Fehlerprüfungen!
20
// Der String muß groß genug sein (l_min+1).
21
// Rückgabe ist der String.
22
char *fill_r( char *str, size_t l_min, char fill_char )
23
{
24
  size_t l = strlen( str );
25
  if( l<l_min )
26
  {
27
    memset( str+l, fill_char, l_min-l );
28
    str[l_min] = '\0'; // terminieren
29
  }
30
  return str;
31
}
32
33
34
#include <stdio.h>
35
36
int main( int nargs, char **args )
37
{
38
  char   puffer1[100] = "12";
39
  char   puffer2[100] = "12";
40
41
  printf( "<%s>\n", fill_l( puffer1, 4, ' ' ) );
42
  printf( "<%s>\n", fill_r( puffer2, 4, ' ' ) );
43
44
  return 0;
45
}

von Klaus W. (mfgkw)


Lesenswert?

PS:
Wenn es dann nur noch darum geht, eine int irgendwie in Textform zu 
bringen (12 -> "12"), dann ist sprintf() nicht das Mittel der Wahl. Denn 
sprintf() ist eine Monsterfunktion, die viel Code hat und nicht 
besonders schnell ist.
Besser nimmt man dann etwas wie itoa().

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.