`fprintf` with SD.h's File type - arduino

I'm using the SD.h library to write onto an SD card with the Arduino Uno. I need to write out in a file a template string with some placeholder replaced by certain values, in the way of printf behaves. I would use the fprintf function, but when I tried this:
File dataFile = SD.open("myfile.txt", FILE_WRITE);
fprintf(dataFile, "mynumber: %d\n", 100);
I got this error:
cannot convert 'File*' to '__file*' for argument '1' to 'int
fprintf(__file*, const char*, ...)'
How can I manage this?

printf() makes your executable object ~1000 bytes larger, so you may not want to use it if size is a problem.
The fprintf is not intended to use with the SD.h so I think
The simple solution that comes into my mind is using sprintf to format your text then write it to the file with the println function
File dataFile = SD.open("myfile.txt", FILE_WRITE);
char text[100];
sprintf(text,"My number: %d",yournumber);
dataFile.println(text);

Related

With Qt, how to check if stdin is empty?

I have a Qt program that processes stdin data like this:
QTextStream qtin(stdin);
QString stdindata = qtin.readAll();
QByteArray ba;
ba = stdindata.toUtf8();
QJsonDocument exJSONDoc(QJsonDocument::fromJson(ba));
QJsonObject extRoot;
extRoot = exJSONDoc.object();
QStringList keys;
keys = extRoot.keys();
for (int n=0; n <= keys.count()-1; n++)
{
qDebug() << extRoot.value(keys[n]).toString();
}
It works when I call my program like this:
myprogram < ./data.json
But if I call it without any "<" it hangs in qtin.readAll().
How can I check with Qt if the stdin is empty?
(I am assuming a Linux -or at least POSIX- operating system)
QTextStream qtin(stdin);
QString stdindata = qtin.readAll();
This would read stdin till end-of-file is reached. So works with a redirected input like
myprogram < ./data.json
But if I call it without any "<" it hangs ...
But then (that is, if you run myprogram alone) stdin is not empty. It is the same as your shell's stdin. and your program, being the foreground job, is waiting for input on the terminal you are typing (see also tty(4)). Try (in that case) typing some input on the terminal (which you could end with Ctrl D to make an end-of-file condition). Read about job control and the tty demystified and see also termios(3).
Perhaps you could detect that situation with e.g. isatty(3) on STDIN_FILENO. But that won't detect a pipe(7) like
tail -55 somefile | myprogram
You need to define what an empty stdin is for you. I have no idea what that means to you, and I would instead think of myprogram < /dev/null (see null(4)) as the way to get an empty stdin.
Perhaps you should design myprogram so that some program
option (perhaps --ignore-stdin) is avoiding any read from stdin.
Problem here is readAll. See documentation:
Reads the entire content of the stream, and returns it as a QString.
Avoid this function when working on large files, as it will consume a
significant amount of memory.
So it reads stdin until it encounters end of file and since stdin is associated with console you have to signal end of file. Usually it is Ctrl-D and press enter.
It is more probable you what to read stdin line by line.
To alow user text editing console transfers data to standard input of the application only line by line. This was designed like this ages ago when computer had only a printer as user interface (no screen).
Now question is how to read JSon form stdin console connected with console without end of file information?
I would use some SAX parser, but this would be to complicated for you.
So is there another way to detect end of JSon?
You can try this approach (this is basic idea, not final solution, so it has couple shortcomings):
QFile file(stdin);
QByteArray data = file.peak(largeNumber);
QJsonParseError error;
QJSonDocument doc = QJSonDocument::fromJson(data, &error);
while (!doc.isValid() && JSonNotTerminatedError(error.error))
{
// TODO: wait for new data - it would be best to use readyRead signal
doc = QJSonDocument::fromJson(data, &error);
}
Where JSonNotTerminatedError returns true for respective QJsonParseError::ParseError values (see linked documentation) which are related with unterminated JSon data.
Now I see QFile doesn't have required constructor, but main concept should be clear. Read data from stdin and check if it is a valid JSon document.

QSettings INI file: value containing semicolon

I'm trying to read and edit a Desktop Entry .desktop file using Qt QSettings. The problem is that these files contain keys with multiple values separated by semicolon ;. I tried reading these as QStringList but no luck. I only get the first value. For example:
Keywords=disc;cdrom;dvd;burn;audio;video;
Categories=GTK;GNOME;AudioVideo;Audio;Video;DiscBurning;
MimeType=application/x-cd-image;application/x-cdrdao-toc;application/x-cue;application/x-toc;audio/x-scpls;audio/x-ms-asx;audio/x-mp3-playlist;audio/x-mpegurl;application/x-brasero;x-content/audio-cdda;x-content/video-dvd;x-content/video-vcd;x-content/video-svcd;x-content/image-picturecd;
Getting the values with:
settings.value("Desktop Entry/MimeType").toStringList();
settings.value("Desktop Entry/MimeType").toString();
returns only the first value (in my example: disc, GTK or application/x-cd-image).
How to I return the full value from those keys? And how do I write it back using QSettings?
Update (first attempt was completely useless)
Variant 1
QMap<QString, QString> settings;
QFile inFile("<input filename.ini>");
if(inFile.open(QIODevice::ReadOnly))
{
QTextStream in(&inFile);
while (!in.atEnd())
{
QString line = in.readLine();
QStringList linelist = line.split("=");
settings[linelist[0]] = linelist[1];
}
}
Variant 2
use QSettings::registerFormat().
This is probably the only "clean" way to do it with QSettings. The advantage is that you can register it with the .desktop extension. You'll have to write a pair of ReadFunc() and WriteFunc() functions.
I think you can't do it. QSettings has certain interpretation of .ini file format, which is very close to Windows interpretation, and is not meant for generic parsing. Semicolon starts a comment, and apparently QSettings allows comment after value until end of line, and AFAIK there's no way around it.
You need to find a different library to handle .desktop files, or implement one yourself.

How to creat printf with slightly different name

I am using ATmega128 and I need two serial ports for communication. I have been using printf from "stdio.h" header file to send data through USART 0. I also need to send data through USART 1 to lcd and I am curious about using formatted input function. I have been thinking that connecting same printf function to USART 1 and USART 0 makes the compiler confused so I haven't tried it.
Can anyone suggest how to make another printf say "Lprintf" to send data through USART 1 ??
What you want to do here is to use fprintf(). See the documentation on avr-libc for the function. Essentially, you want to have a fputc() function for UART1 and one for UART0. Then, based on that, you can create two FILE buffers. Once you do so, you are free to use fprintf() on each. Optionally, you can point stdout to one of these buffers, as to be able to use printf().
FILE uart1_out = FDEV_SETUP_STREAM(uart1_putc, 0, _FDEV_SETUP_WRITE);
FILE uart0_out = FDEV_SETUP_STREAM(uart0_putc, 0, _FDEV_SETUP_WRITE);
fprintf(&uart1_out, "printing to UART1");
fprintf(&uart0_out, "printing %d to UART0", 0);
stdout = &uart1_out;
stderr = &uart0_out;
printf("This string will be printed thru UART1");
fprintf(stderr, "This string will be printed thru UART0");
You just need to provide the implementation for int uart1_putc(int, FILE*) and int uart0_putc(int, FILE*) to manipulate data as you wish.
Hope this helps.
Cheers.
Depending on how you've linked it, there are two alternatives that are possibly simpler:
Use sprintf() to write your formatted text to a string, and then use your own putchar() or putstring() to send it to the desired USART.
If you're using the FILE struct to link your USARTs to the stdio functions (likely), you can use fprintf() to direct the results to a particular stream.

unix open file for write given file descriptor

I want to open a file for write and I have been given the file descriptor for that file.
I know that fdopen can be used to write to the file as follows:
FILE * fp;
fp = fdopen(filedes, "a+");
fwrite("\n", sizeof(char), 1, fp);
Is there any other way to achive the same, i.e., write to a file given a file descriptor?
Thanks
Is there any other way to achive the same, i.e., write to a file given
a file descriptor
You can write directly using the system call write(2).
write(fd, "\n", 1);
You can write a buffer of data to a file descriptor with the write system call.

qstring white space

QString fe = "C:\\Program Files\\Autodesk\\Maya2008\\bin\\imconvert.exe ";
This line gives a problem because of space between Program and Files. How is it possible to decode it so that it is treated as one complete string
Brgds,
kNish
You can use a QFileInfo object to store it. This object accepts all path even if they have spaces. In addition you have some functions to do all checks you need before using it.
Use QUrl::toPercentEncoding static method
In windows you would do:
QString fe = "\"C:\\Program Files\\Autodesk\\Maya2008\\bin\\imconvert.exe\"";

Resources