-
-
Notifications
You must be signed in to change notification settings - Fork 7k
sprintf, sscanf is not correctly implemented in stdio.h #1719
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I believe that is by design because of the substantial extra space required for such features. Since sscanf and sprintf need to decode their formatting strings at runtime, the compiler can not optimize away unneeded code. Implementing this change would make everyone's code larger, bearing in mind program memory is usually in short supply. You can scan floats by scanning a string and then applying atof on them. You can print floats by using dtostrf. |
@dgrat you should see this page for details: http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#gaa3b98c0d17b35642c0f3e4649092b9f1. You can enable it by using the compiler options described on the page. printf:
scanf:
|
Thx 2013/12/20 Kristian Sloth Lauszus [email protected]
|
I don't think this is a good idea. If anyone is supposed to exclude standards then he is expected to exclude them by himself. #pragma config noeffingformatbugs or whatever ! I got functions like: sprintf(sdata,"%08d %08d %08.3f %08.3f", p, q, x, y);
cnt = sscanf (sdata,"%08d %08d %08.3f %08.3f", &m, &n, &v, &w); I'm using them by an Arduino Due, who wants and who doesn't want these features, shall leave it off or shall use a #include <crippledio.h> instead! |
Well, not really on a platform like the Arduino Uno. Where is stdin, stdout, stderr? What about FILE pointers? It's reasonable to provide a cut-down version for a machine that has 2 kB of RAM and 32 kB of programmable memory. Maybe on the Due, I can't speak for that. |
I'm not talking about Unos! Arduino is not just equal to Unos or Nanos!
Acting from necessity I finally already had to write my homebrewed fgets() by my own - that is really unreasonable and unconscionable! So please provide all standard libs as a default (gpp already provides them all !!), optionally to be #included as usual (anyway, who doesn't need it woudn't need to #include it !), And please before the last day'll come - give me workarounds to utilize float formatters for sscanf !!! |
I actually think that at least printf is already available on AVR / Arduino. Not sure about scanf. But you didn't answer the essential question yet:
If you want to use printf, you'll have to tell it where to send its data. libc allows you to assign the "stdout" variable to a custom stream, created with e.g. FDEV_SETUP_STREAM. See for example: https://github.com/erictj/uracoli/blob/master/wibo/wibo.c#L146-L161 and https://github.com/erictj/uracoli/blob/master/wibo/wibo.c#L237. Admittedly, Arduino could make it easier to e.g. select "Serial" as the target for printf. However, printf is not a very friendly and easy API for novice users, which is Arduino's primary target audience. If you want to use it, you're welcome to, but it's up to you to set it up. Going back to the original question, which was about floats, not printf itself, as mentioned that needs link-time options, that will probably not be enabled by default due to the space overhead. Until there is a decent mechanism for specifying compiler flags in a sketch, there's not much that can be done there. As for the Due, I wouldn't be surprised if sprintf'ing floats actually works there. It's disabled by avr-libc by default, not Arduino, so I wouldn't be surprised if the arm version just has them enabled. |
my comment first of all is about providing all float formatters for all printf-like functions or Mega and Due (e.g., sprintf, sscanf), and the rest is urgently needed for the future additionally ! Finally : float formatters don't work for sscanf on my Dues (neither 1.5.8 nor 1.6.0 ), and obviously not on my Megas! |
I just tried running this on my Arduino Due:
Here's what it prints in the serial monitor:
|
Maybe you should give sprintf and sscanf another try? |
no, can't you read??? My functions look like this, and that's just what I expect them to work: sprintf(sdata,"%08d %08d %08.3f %08.3f", p, q, x, y); This is standard C syntax and I expect it to work like this and to read formatted floats and not just 0.00 for each float variable!! And don't expect me to write code as much to sink a ship just for those effing "workarounds" ! |
Post a complete program that can be copied into Arduino and run on a real board. Your code fragment has 4 different variable names on each line. |
for all I care, ok, but that wouldn't change this issue: // sprintf() plus sscanf()
// Sketch 1.6.0
void setup() {
//
Serial.begin(9600);
int16_t p=33, q=66, m, n, cnt;
float x=PI, y=987.654, v, w;
char sdata[64], sbuf[64];
// pre-test
Serial.println("Start pre-Test");
Serial.println("Original x als float");
Serial.println(x);
Serial.println("Original-String: 1x float formatiert per sprintf()");
sprintf(sdata,"%08.3f",x);
Serial.println(sdata);
cnt = sscanf (sdata,"%08.3f", &w);
Serial.print("Anzahl Werte per sscanf()="); Serial.println(cnt);
Serial.println("Kopie-Werte per sscanf()");
Serial.println(w);
Serial.println("Ende pre-Test");
Serial.println();
Serial.println("Original-Werte");
Serial.println(p);
Serial.println(q);
Serial.println(x);
Serial.println(y);
Serial.println("Original-String per sprintf()");
sprintf(sdata,"%08d %08d %08.3f %08.3f", p, q, x, y);
Serial.println(sdata); // Originalstring ausgeben
cnt = sscanf (sdata,"%08d %08d %08.3f %08.3f", &m, &n, &v, &w);
Serial.print("Anzahl Werte per sscanf()="); Serial.println(cnt);
Serial.println("Kopie-Werte per sscanf()");
Serial.println(m);
Serial.println(n);
Serial.println(v);
Serial.println(w);
strcpy(sbuf, sdata);
Serial.println("Kopie-String");
Serial.println(sbuf); // kopierten String ausgeben
sscanf (sbuf,"%08d %08d %08.3f %08.3f", &m, &n, &v, &w);
Serial.println("Kopie-Werte per sscanf()");
Serial.println(m);
Serial.println(n);
Serial.println(v);
Serial.println(w);
}
void loop() {
// put your main code here, to run repeatedly:
} |
Serial output:
|
I just tried this on Linux:
The compiler warns:
When actually run, it prints:
|
Maybe you should go post a string an angry comments on the gcc or linux dev lists? |
I can't see the point why it shouldn't work: http://www.cplusplus.com/reference/cstdio/sscanf/ int sscanf ( const char * s, const char * format, ...); http://www.cplusplus.com/reference/cstdio/scanf/ |
in an another post these following compiler options have been mentioned, maybe this is related to this issue - but I don't understand how to utilize it for Sketch though printf: scanf: |
Arduino doesn't use the C99 standard. But even when I compile that test with this "gcc -Wall -std=c99 test.c", the result is still:
|
well - then please tell me what's going on with this effing sscanf issue....? |
Maybe gcc and the C library on Ubuntu 12.04 aren't following the standard either? Or maybe you're mistaken about what syntax sscanf() is supposed to accept? |
@PaulStoffregen has already wasted a lot of his precious time to following this issue, I guess you should read the standard (that you love so much) more carefully: http://www.cplusplus.com/reference/cstdio/scanf/ The dot "." format specifier is not allowed in sscanf, as the error message posted by Paul clearly explains. |
"optionally containing a decimal point" |
Those are the "characters extracted" not the format specifier. |
@cmaglie - I do have a little interest in this issue. For Teensy, I recently switched to different library settings, which exclude float support from these functions by default. There's a workaround, from sketch code, to get the linker to still use the float version. |
Turns out, this conversation is unrelated... but this is something I'm wanting out for issues with, since there's a need to balance desires from users who want to target much smaller chips vs people who want float support (as I do occasionally). |
I'm not talking about teensy or nanos, I'm talking about Megas and Dues, and I don't see where's explicitely written that a dot is not allowed ? |
Well, when I posted this thing I was not used to Arduino. I see the point to disable these features. |
users for smaller chips may use a crippled io lib with mutilated features (or leave them completely off), |
As far as I'm concerned, whether or not a dot is allowed in a %f format specifier in sscanf() doesn't belong anywhere on Arduino's website, since Arduino doesn't officially support printf and scanf as part of their official API. You can post another 1000 angry rants and none of it will convince anyone Arduino's sscanf() is broken if it gives the same result as sscanf() on Linux. |
ok, given a dot was not allowed (it finally is not written anywhere) - then I stand corrected, then that was simply missing in the documentation. But to exclude float formatters by Sketch completely (as written in the post above) actually IS an Arduino Sketch issue. |
Yes, it is an issue, but as previously explained, this is an intentional trade-off between code size and features. If you really need it, modify platform.txt to add the proper linker options to enable it. |
users for smaller chips may use a crippled io lib with mutilated features (or leave them completely off), |
I'll test the dot issue in the formatter ASAP when I'm at home with my Arduino Boards. |
You're now ranting that large boards like Arduino Due should support sscanf, and indeed Arduino Due does. |
Till now it actually didn't work for the Due as I widely explained! But as I also have written that in case this was a deficiency in the documentation then I surely stand corrected! But no one ever had pointed out before so far (neither in this thread here nor somewhere else) that a dot inside a float formatter wouldn't be allowed at all! |
update: Thanks to all for your inputs ! |
just for better search results: |
Float operations don't work with these functions. Instead a zero is inserted. Integers do work.
The text was updated successfully, but these errors were encountered: