Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.postscript > #1137

Re: Putting lines from a file into an array

From John Deubert <john@acumentraining.com>
Organization Acumen Training
Newsgroups comp.lang.postscript
Date 2012-12-03 13:20 -0800
Message-ID <2012120313202243338-john@acumentrainingcom> (permalink)
References <87624kp6hc.fsf@Compaq.site.inet> <y7Pus.223533$kt5.184865@fx08.am4>
Subject Re: Putting lines from a file into an array

Show all headers | View raw


On 2012-12-02 20:47:26 +0000, Chris said:

> On Sun, 02 Dec 2012 21:02:55 +0100, Cecil Westerhof wrote:
> 
>> I have the following script:
>> /buffer 80 string def /inputFile INPUT (r) file def {
>> inputFile buffer readline {
>> =
>> }{
>> pop inputFile closefile exit
>> } ifelse
>> } loop
>> 
>> This displays the file. But instead of displaying I would like to put
>> the lines into an array.
>> 
>> Just keeping the values on the stack Like:
>> /buffer 80 string def /inputFile INPUT (r) file def {
>> inputFile buffer readline {
>> % Keep it on the stack
>> }{
>> pop inputFile closefile exit
>> } ifelse
>> } loop stack
>> 
>> does not work, because the lower values are overwritten.
>> 
>> The first script gives:
>> They are not only idle who do nothing,
>> but they are idle also who might be better employed.
>> 
>> Socrates
>> 
>> While the second gives:
>> Socrates
>> 
>> Socratest be better employed. Socratest be better em Socratest be
>> better employed. nothing,
>> 
>> How would I get the lines correctly into an array?
> 
> The values get overwritten because you only allocate one string for the
> lines to be read into ("/buffer 80 string def"), then reuse it for each
> iteration through the loop.
> 
> Something like:
> 
>   /inputFile INPUT (r) file def
>   /linearray
>   [
>     {
>       inputFile 80 string readline
>       not
>       {
>         pop inputFile closefile
>         currentdict /inputFile undef
>         exit
>       } if
>     } loop
>   ]
>   def
> 
> 
> will give you the lines of the file in an array called "linearray".
> 
> You can dump the contents thus:
> 
>   linearray {print (\n) print } forall
> 
> (Note the explicit new line)
> 
> Chris

Note that there is possible error condition implicit in the above 
method; using brackets to construct the array places the array contents 
temporarily on the stack. All of the lines in the file are being piled 
up on the stack, remaining there until the close bracket. If you have a 
very large file (that is, a file with a large number of lines in it), 
you will eventually provoke a stack overflow. The maximum size of the 
operand stack is implementation dependent in Level 2 & 3 devices, so 
it's hard to say when (or if) you'll encounter the problem.

I'm not at all saying this is a bad solution; it's probably how I'd do 
it. But if you get the very occasional stack overflow from this 
solution, that's probably the source of the problem.

Hmmm. How can we fix this? The problem is that unless you use the 
brackets to construct your array, PostScript requires you allocate the 
array ahead of time, which, in turn, requires knowing how many lines 
there are in the file. You could read the file twice (once counting 
lines, the second actually constructing the array), but that seems 
inelegant, somehow.

<< ... some minutes later ... >>

Here's a novel solution based on the fact that PostScript dictionaries 
automatically expand as needed. Let's read the lines into a dictionary, 
see how many key-value pairs end up in the dictionary, make an array 
with room for that many items, and then transfer the strings from the 
dictionary to the array. A bit convoluted, but should be immune to 
stackoverflow errors.

Lessee here...

% ============== Cut here ==============
/$lines 100 dict def	% Our dictionary of lines; initially room for 100 
lines, expandable

/inputFile INPUT (r) file def
/i 0 def
$lines begin		% Put the dict on the dict stack for convenience

% Let's construct the dictionary
{	inputFile 100 string readline		% read a line of text
	exch				% Bring the string to the top of the stack
	i exch def			% define i and the line as a key-value pair
	/i i 1 add store	% and increment i
	not { exit } if		% leave the loop if that was the last line
} loop

% At this point, the $lines dictionary contains line numbers and line 
text as key-value pairs
% Now we need to transfer the lines to an array.

% First we create the array:
/numLines currentdict length def 	% Note that numLines ends up in our 
"$lines" dict; this is fine with me.
numLines array				% Create the new array

0 1 numLines 1 sub		% Interate through the lines in the dictionary
{					% Stack:  [ ] i
	2 copy			% Stack:  [ ] i [ ] i
	dup load		% Stack:  [ ] i [ ] i (line o' text)
	put pop			% Stack:  [ ]
} for
% The loop exits with our array of strings on the stack

end		% We don't need $lines anymore 


% Save the array as a variable, if we wish:
/linearray exch def


% =============== Cut here =================

As I say, not as simple as Chris' version, but it does work around the 
stack limitation. I'd go with Chris' code unless the number of lines 
was likely to be northward of 1000 lines or so. (By the way, there's 
some cleanup one could do on this code, but lunch is beckoning.)

- John


-- 
========
John Deubert
Acumen Training
PostScript & PDF Engineering Classes & Consulting
www.acumentraining.com

Learn PostScript programming techniques
Read the free Acumen Journal
acumentraining.com/acumenjournal.html

Back to comp.lang.postscript | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

Putting lines from a file into an array Cecil Westerhof <Cecil@decebal.nl> - 2012-12-02 21:02 +0100
  Re: Putting lines from a file into an array Chris <cjl@spamcop.net> - 2012-12-02 20:47 +0000
    Re: Putting lines from a file into an array Cecil Westerhof <Cecil@decebal.nl> - 2012-12-03 00:52 +0100
      Re: Putting lines from a file into an array Don Lancaster <don@tinaja.com> - 2012-12-05 11:58 -0700
        Re: Putting lines from a file into an array "luser.droog" <luser.droog@gmail.com> - 2012-12-05 23:19 -0600
    Re: Putting lines from a file into an array John Deubert <john@acumentraining.com> - 2012-12-03 13:20 -0800
      Re: Putting lines from a file into an array "luser.droog" <luser.droog@gmail.com> - 2012-12-04 00:58 -0600
      Re: Putting lines from a file into an array Chris <cjl@spamcop.net> - 2012-12-04 09:09 +0000
        Re: Putting lines from a file into an array John Deubert <john@acumentraining.com> - 2012-12-04 07:03 -0800
          Re: Putting lines from a file into an array Chris <cjl@spamcop.net> - 2012-12-04 17:46 +0000
        Re: Putting lines from a file into an array Cecil Westerhof <Cecil@decebal.nl> - 2012-12-04 17:17 +0100
  Re: Putting lines from a file into an array "luser.droog" <luser.droog@gmail.com> - 2012-12-02 15:31 -0600
    Re: Putting lines from a file into an array Cecil Westerhof <Cecil@decebal.nl> - 2012-12-03 02:19 +0100
      Re: Putting lines from a file into an array "luser.droog" <luser.droog@gmail.com> - 2012-12-02 23:28 -0600
        Re: Putting lines from a file into an array Cecil Westerhof <Cecil@decebal.nl> - 2012-12-03 10:01 +0100
  Re: Putting lines from a file into an array luser droog <luser.droog@gmail.com> - 2016-08-01 13:25 -0700
    Re: Putting lines from a file into an array JohnF <john@please.see.sig.for.email.com> - 2016-08-02 03:39 +0000
      Re: Putting lines from a file into an array luser droog <luser.droog@gmail.com> - 2016-08-02 21:58 -0700
        Re: Putting lines from a file into an array Tonton Th <tTh@nowhere.invalid> - 2016-08-03 05:10 +0000
        Re: Putting lines from a file into an array luser droog <luser.droog@gmail.com> - 2016-08-02 22:20 -0700
          Re: Putting lines from a file into an array luser droog <luser.droog@gmail.com> - 2016-08-02 22:35 -0700
            Re: Putting lines from a file into an array JohnF <john@please.see.sig.for.email.com> - 2016-08-03 06:21 +0000
            Re: Putting lines from a file into an array JohnF <john@please.see.sig.for.email.com> - 2016-08-03 06:32 +0000
              Re: Putting lines from a file into an array luser droog <luser.droog@gmail.com> - 2016-08-22 22:31 -0700

csiph-web