perl6 IO::Handle has no printf method, inconsistent with documentation, or I missed something? - file

I am trying to open a file for writing and use printf to do formatting, but documentation and reality do not seem to agree. Am I missing something?
To exit type 'exit' or '^D'
> my $fh=open "test", :w;
IO::Handle<"test".IO>(opened, at octet 0)
> $fh.printf: "test";
No such method 'printf' for invocant of type 'IO::Handle'
in block <unit> at <unknown file> line 1
But my code seems okay according to documentation:
https://docs.perl6.org/routine/printf
Thank you very much !!

Apparently IO::Handle.printf was added on Nov 27, 2016 and Rakudo 2016.11 is tagged on Nov 19. So my guess is your Rakudo is older than that.

The printf() example in the docs doesn't work for me either:
~/p6_programs$ perl6 -v
This is Rakudo version 2016.11 built on MoarVM version 2016.11
implementing Perl 6.c.
~/p6_programs$ cat 4.pl6
my $fh = open 'outfile.txt', :w;
$fh.printf: "The value is %d\n", 32;
$fh.close;
~/p6_programs$ perl6 4.pl6
No such method 'printf' for invocant of type 'IO::Handle'
in block <unit> at 4.pl6 line 3
You could use sprintf() as a workaround:
my $fh = open 'outfile.txt', :w;
$fh.say: sprintf "The value is %d", 32;
$fh.close;
or fmt():
my $fh = open 'outfile.txt', :w;
$fh.say: 32.fmt("The value is %d");
$fh.close;

Related

How do I make printf() print output in the correct order?

I have a simple working function that creates a table logging file information.
However, printf prints my output in the wrong order. I tried using fflush(stdout) to flush the buffer but it didn't change anything.
The function:
void printTable(char *libraryName)
{
printf("%-40s%-30s%-25s%-20s\n", "[File Name]", "[Creation Time]", "[Version]", "[Size]");
fflush(stdout);
printf("%-40s%-30d%-25d%-20f\n", libraryName, getCreationTime(libraryName), getVersion(libraryName), getSize(libraryName));
fflush(stdout);
}
The get functions are defined in a seperate file and give accurate output.
After compilation, the output looks like this:
[File Name] [Creation Time] [Version] [Size]
125 kB
Version: 1.0.0.0 [6-02-2020 03:32:21 PM] Objects.dll
But it needs to look like this:
[File Name] [Creation Time] [Version] [Size]
Objects.dll [6-02-2020 03:32:21 PM] 1.0.0.0 125 kB
What do I need to do to my printf() function to get the correct order output? I've tried flushing the buffer and rearranging order of the functions. Is it possible to get the output in the correct order without writing a separate printf() statement for each function?
The code you posted is fine and flushing isn't the answer. There's no way %d specifier could print strings like [6-02-2020 03:32:21 PM] and Version: 1.0.0.0, nor could %f result in 125 kB.
I suspect your get functions are printing their results rather than returning them, something like:
int getCreationTime(char *libraryName)
{
printf("[6-02-2020 03:32:21 PM] ");
}
int getVersion(char *libraryName)
{
printf("Version: 1.0.0.0 ");
}
double getSize(char *libraryName)
{
printf("125 kB\n");
}
I'm not sure what you are returning. Perhaps nothing? I have the feeling that you've got some compiler warnings you're ignoring. If so, read them, and address them!
If you're wondering why the results are mixed up it's because C doesn't proscribe that function arguments be evaluated in any particular order, such as left-to-right. It looks like getSize is being called first followed by getVersion and getCreationTime. Finally, the printf we see prints libraryName.

splittling a file into multiple with a delimiter awk

I am trying to split files evenly in a number of chunks. This is my code:
awk '/*/ { delim++ } { file = sprintf("splits/audio%s.txt", int(delim /2)); print >> file; }' < input_file
my files looks like this:
"*/audio1.lab"
0 6200000 a
6200000 7600000 b
7600000 8200000 c
.
"*/audio2.lab"
0 6300000 a
6300000 8300000 w
8300000 8600000 e
8600000 10600000 d
.
It is giving me an error: awk: line 1: syntax error at or near *
I do not know enough about awk to understand this error. I tried escaping characters but still haven't been able to figure it out. I could write a script in python but I would like to learn how to do this in awk. Any awkers know what I am doing wrong?
Edit: I have 14021 files. I gave the first two as an example.
For one thing, your regular expression is illegal; '*' says to match the previous character 0 or more times, but there is no previous character.
It's not entirely clear what you're trying to do, but it looks like when you encounter a line with an asterisk you want to bump the file number. To match an asterisk, you'll need to escape it:
awk '/\*/ { close(file); delim++ } { file = sprintf("splits/audio%d.txt", int(delim /2)); print >> file; }' < input_file
Also note %d is the correct format character for decimal output from an int.
idk what all the other stuff around this question is about but to just split your input file into separate output files all you need is:
awk '/\*/{close(out); out="splits/audio"++c".txt"} {print > out}' file
Since "repetition" metacharacters like * or ? or + can take on a literal meaning when they are the first character in a regexp, the regexp /*/ will work just fine in some (e.g. gawk) but not all awks and since you apparently have a problem with having too many files open you must not be using gawk (which manages files for you) so you probably need to escape the * and close() each output file when you're done writing to it. No harm doing that and it makes the script portable to all awks.

LoadRunner sprintf and lr_eval_string

I am facing some issues that I'm certain is correct code, as I've seen it work before today, and without any changes made to the script, only a VUGen version change/upgrade.
HP Virtual User Generator:: Version: 12.02.0.0
ClockingIDCount = atoi(lr_eval_string("{ClockingID_count}"));
lr_output_message("CIDCount:%d",ClockingIDCount);
lr_output_message("ClockingID1::%s",lr_eval_string("{ClockingID_1}"));
for (i = 1; i <= ClockingIDCount; i++) {
sprintf(loopParam, "{ClockingID_%d}", i);
lr_output_message("ClockingID: %s %s %s", loopParam, lr_eval_string("{loopParam}"), lr_eval_string(lr_eval_string("{loopParam}")));
}
Outputs:
Action.c(120): CIDCount:21
Action.c(121): Notify: Parameter Substitution: parameter "ClockingID_1" = "6829888"
Action.c(121): ClockingID1::6829888
But using the sprintf function to iterate over the items captured, returns;
Action.c(125): ClockingID: {ClockingID_1} {loopParam} {loopParam}
Note: I'm aware the 3rd %s evaluation shouldn't work - was just a thought as I've seen it resolve things like this before.
Code tampered!
Solution :: Remove the "{ }" from the lr_eval_string function;
Solution :: lr_output_message("ClockingID: %s", lr_eval_string(loopParam));

Printf(%s) prints 0

I have this command in my project (in C):
int addFinalDataStr(char* value)
{
fprintf(objFile,"%-7.7s\n",value);
fflush(objFile);
}
When I call this method with the value like: "60100", it prints "60100" with no problems,
but when i call it with a string like "37777777773" it just prints out "0".
I think the your error is caused by the compiler check with another compiler (I recommend you the GCC compiler) and see if it works.
There are 2 issues
printf("%-7.7s\n", "60100");
// should print "60100 ", not "60100" as OP states
printf("%-7.7s\n", "37777777773");
// should print "3777777", not "0".
It appears the compiler is not compliant or something critical is missing from the post.

Updated: When to "mortalize" a variable in Perl Inline::C

I am trying to wrap a C library into Perl. I have tinkered with XS but being unsuccessful I thought I should start simply with Inline::C. My question is on Mortalization. I have been reading perlguts as best as I am able, but am still confused. Do I need to call sv_2mortal on an SV* that is to be returned if I am not pushing it onto the stack?
(PS I really am working on a less than functional knowledge of C which is hurting me. I have a friend who knows C helping me, but he doesn't know any Perl).
I am providing a sample below. The function FLIGetLibVersion simply puts len characters of the library version onto char* ver. My question is will the version_return form of my C code leak memory?
N.B. any other comments on this code is welcomed.
#!/usr/bin/perl
use strict;
use warnings;
use 5.10.1;
use Inline (
C => 'DATA',
LIBS => '-lm -lfli',
FORCE_BUILD => 1,
);
say version_stack();
say version_return();
__DATA__
__C__
#include <stdio.h>
#include "libfli.h"
void version_stack() {
Inline_Stack_Vars;
Inline_Stack_Reset;
size_t len = 50;
char ver[len];
FLIGetLibVersion(ver, len);
Inline_Stack_Push(sv_2mortal(newSVpv(ver,strlen(ver))));
Inline_Stack_Done;
}
SV* version_return() {
size_t len = 50;
char ver[len];
FLIGetLibVersion(ver, len);
SV* ret = newSVpv(ver, strlen(ver));
return ret;
}
Edit:
In an attempt to answer this myself, I tried changing the line to
SV* ret = sv_2mortal(newSVpv(ver, strlen(ver)));
and now when I run the script I get the same output that I did previously plus an extra warning. Here is the output:
Software Development Library for Linux 1.99
Software Development Library for Linux 1.99
Attempt to free unreferenced scalar: SV 0x2308aa8, Perl interpreter: 0x22cb010.
I imagine that this means that I don't need to mortalize in this case? I suspect that the error is saying that I marked for collection something that was already in line for collection. Can someone confirm for me that that is what that warning means?
I've been maintaining Set::Object for many years and had this question, too - perhaps best to look at the source of that code to see when stuff should be mortalised (github.com/samv/Set-Object). I know Set::Object has it right after many changes. I think though, it's whenever you're pushing the SV onto the return stack. Not sure how Inline changes all that.

Resources