How to do printf in r?
printf <- function(...) invisible(print(sprintf(...)))
The outer invisible
call may be unnecessary, I'm not 100% clear on how that works.
Is it possible to grab/scrape the .Call() output of C printf() within R (or with Rprintf())?
So, the issue here is printf
negates R's built collection mechanisms for output. In particular, there is no C-level 'stdout' file stream and, thus, no output to collect in either Rgui or RStudio. For details, please see Section 6.5 Printing
of Writing R Extensions
Two possible solutions:
- Define a macro that sets
printf
to direct intoRprintf
and include the#define STRICT_R_HEADERS
to avoid errors. - Switch instances of
printf
toRprintf
in the offending code.
From here, the capture can be passed off to either capture.output()
, which directly assigns output to a variable, or sink()
, which redirects output to a file whose contents must then be read back in using readLines()
. The latter makes it possible to have a clear enclose over multiple lines of code to capture output while the prior is focused on securing output present from an inputted expression.
Option 1
For the first iteration, just define a header that includes the custom define and then include the third party library, e.g.
my_code.h
#ifndef MY_CODE_H
#define MY_CODE_H
#include <R.h>
// this load R_ext/Print.h.
// #include <YOUR_LIBRARY.h>
// Define strict headers
#define STRICT_R_HEADERS
// Map printf to Rprintf
#define printf Rprintf
#endif
toad.c
#include <R.h>
#include <Rdefines.h>
#include "my_code.h"
SEXP helloA1() {
printf("Hello World!\n");
return(R_NilValue);
}
toad_example.R
system("R CMD SHLIB ~/Desktop/toad.c")
dyn.load("~/Desktop/toad.so")
helloA1 <- function() {
result <- .Call("helloA1")
}
# Gregor's suggestion
captured_data = capture.output(helloA1())
# Using sink around multiple function calls to redirect output
# to a single file
sink("sink-examp.txt")
helloA1()
sink()
input_data = readLines("sink-examp.txt")
all.equal(input_data, captured_data)
# [1] TRUE
I've implemented this approach in an R package that can be found here:
https://github.com/coatless/printf2Rprintf
Option 2
This option manually redefines the printf
functions.
toad.c
#include <R.h>
#include <Rdefines.h>
SEXP helloA1() {
Rprintf("Hello World!\n"); // manually changed
return(R_NilValue);
}
toad_example.R
system("R CMD SHLIB ~/Desktop/toad.c")
dyn.load("~/Desktop/toad.so")
helloA1 <- function() {
result <- .Call("helloA1")
}
# Gregor's suggestion
captured_data = capture.output(helloA1())
# Using sink around multiple function calls to redirect output
# to a single file
sink("sink-examp.txt")
helloA1()
sink()
input_data = readLines("sink-examp.txt")
all.equal(input_data, captured_data)
# [1] TRUE
how to print a variable number of arguments in r?
The doc is right. In first case, do.call(sprintf, c(list("%s %s"), vec))
is equal to:
sprintf("%s %s", "a","b","c","d")
The fmt string "%s %s"
requires two vectors while you provided four and the last two ("c", "d") were not used for printing.
The second case is similar. do.call(sprintf, c(fmt = base_string, as.list(v1)))
is equal to:
sprintf(fmt = "%s, %s, %s", "foo", "bar", "baz","foo", "bar", "baz")
Three variables were to be printed based on fmt
but you provided six.
Then, what does "recycled" in the doc mean?
and I guess you might misunderstand it. It means when the formating string and vectors are of different lengths, the short er ones will be recycled to the longest one. An example:
> sprintf(c('%s %s', '%s, %s'), c('a', 'b', 'c'), 1:6)
[1] "a 1" "b, 2" "c 3" "a, 4" "b 5" "c, 6"
How to print variable number of arguments: You can try paste
:
> sprintf(paste0(vec, collapse = ' '))
[1] "a b c d"
> sprintf(paste0(v1, collapse = ', '))
[1] "foo, bar, baz, foo, bar, baz"
Printing newlines with print() in R
An alternative to cat()
is writeLines()
:
> writeLines("File not supplied.\nUsage: ./program F=filename")
File not supplied.
Usage: ./program F=filename
>
An advantage is that you don't have to remember to append a "\n"
to the string passed to cat()
to get a newline after your message. E.g. compare the above to the same cat()
output:
> cat("File not supplied.\nUsage: ./program F=filename")
File not supplied.
Usage: ./program F=filename>
and
> cat("File not supplied.\nUsage: ./program F=filename","\n")
File not supplied.
Usage: ./program F=filename
>
The reason print()
doesn't do what you want is that print()
shows you a version of the object from the R level - in this case it is a character string. You need to use other functions like cat()
and writeLines()
to display the string. I say "a version" because precision may be reduced in printed numerics, and the printed object may be augmented with extra information, for example.
Need help understanding how \n, \b, and \r will render printf output
Let's take it one step at a time:
<new line>ab<backspace>si<carriage return>ha
First, handle the backspace. Note that even though it is "non-erase", the next character to be output would overwrite what was backspaced over:
<new line>asi<carriage return>ha
Now, a carriage return means to go back to the beginning of the line. So the "ha" overwrites the "as" in "asi:
<new line>hai
Now, the cursor is currently sitting on the i
, so the next character to be output would overwrite i
.
\r in C stops output before it
The statement printf("one")
does not immediately print "one" to the terminal, but it writes the string to the standard output stream (stdout
) - which is usually buffered. Only when this stream is flushed, do its contents get printed to the terminal. Usually, this happens whenever a newline is printed or when the program exits, among other conditions.
The output stream can be forced to flush by calling fflush(stdout)
, which produces the desired result:
#include <stdio.h>
#include <unistd.h>
int main(void) {
printf("one");
fflush(stdout); // Line added
sleep(1);
printf("\r");
printf("two");
return 0;
}
See fflush
for more information. The buffering mode of a stream can be set using the setvbuf
function.
Also, note that the usual main
signature, when using no parameters, is int main(void)
.
Acknowledgements: Thanks to Andreas Wenzel for a correction and the setvbuf
addition.
R - do I need to add explicit new line character with print()?
The nature of R means that you're never going to have a newline in a character vector when you simply print it out.
> print("hello\nworld\n")
[1] "hello\nworld\n"
That is, the newlines are in the string, they just don't get printed as new lines. However, you can use other functions if you want to print them, such as cat:
> cat("hello\nworld\n")
hello
world
Related Topics
How to Do Gaussian Elimination in R (Do Not Use "Solve")
Evaluate Inline R Code in Rmarkdown Figure Caption
References Truncated in Beamer Presentation Prepared in Knitr/Rmarkdown
Creating a Monthly/Yearly Calendar Image with Ggplot2
Beginner Tips on Using Plyr to Calculate Year-Over-Year Change Across Groups
Reshape Data from Long to Wide, with Time in New Wide Variable Name
Select Random Element in a List of R
How Does One Aggregate and Summarize Data Quickly
What Is R's Crossproduct Function
How to Test If Object Is a Vector
Formatting Number Output of Sliderinput in Shiny
R Subsetting a Data Frame into Multiple Data Frames Based on Multiple Column Values
Format Latitude and Longitude Axis Labels in Ggplot
Taking a Disproportionate Sample from a Dataset in R
Plotting Average of Multiple Variables in Time-Series Using Ggplot
How to Create Geom_Boxplot with Large Amount of Continuous X-Variables