[Rd] sprintf("%d", integer(0)) aborts
William Dunlap
wdunlap at tibco.com
Thu Mar 19 00:00:51 CET 2009
In R's sprintf() if any of the arguments has length 0
the function aborts. E.g.,
> sprintf("%d", integer(0))
Error in sprintf("%d", integer(0)) : zero-length argument
> sprintf(character(), integer(0))
Error in sprintf(character(), integer(0)) :
'fmt' is not a non-empty character vector
This comes up in code like
x[nchar(x)==0] <- sprintf("No. %d", seq_along(x)[nchar(x)==0])
which works if x contains any empty strings
x<-c("One","Two","") # changes "" -> "No. 3"
but not if it doesn't
x<-c("One","Two","Three") # throws error instead of doing nothing
When I wrote S+'s sprintf() I had it act like the binary
arithmetic operators, returning a zero long result if any
argument were zero long. (Otherwise its result is as long
as the longest input.) I think it would be nice if R's
sprintf did this also.
Currently you must add defensive code (if (any(nchar(x)==0))...)
to make functions using sprintf to work in all cases and that
muddies up the code and slows things down.
Do you think this is a reasonable thing to do? I've attached
a possible patch to src/main/sprintf.c makes the examples above
return character(0).
Bill Dunlap
TIBCO Software Inc - Spotfire Division
wdunlap tibco.com
-------------------------------------------------------------------
Index: sprintf.c
===================================================================
--- sprintf.c (revision 48148)
+++ sprintf.c (working copy)
@@ -79,13 +79,13 @@
static R_StringBuffer outbuff = {NULL, 0, MAXELTSIZE};
Rboolean use_UTF8;
- outputString = R_AllocStringBuffer(0, &outbuff);
-
/* grab the format string */
nargs = length(args);
format = CAR(args);
- if (!isString(format) || length(format) == 0)
+ if (!isString(format))
error(_("'fmt' is not a non-empty character vector"));
+ if (length(format) == 0)
+ return allocVector(STRSXP, 0) ;
args = CDR(args); nargs--;
if(nargs >= 100)
error(_("only 100 arguments are allowed"));
@@ -97,9 +97,12 @@
for(i = 0; i < nargs; i++) {
lens[i] = length(a[i]);
if(lens[i] == 0)
- error(_("zero-length argument"));
+ return allocVector(STRSXP, 0) ;
if(maxlen < lens[i]) maxlen = lens[i];
}
+
+ outputString = R_AllocStringBuffer(0, &outbuff);
+
if(maxlen % length(format))
error(_("arguments cannot be recycled to the same length"));
for(i = 0; i < nargs; i++)
More information about the R-devel
mailing list