Input loop: Difference between revisions
(added python) |
(added perl) |
||
Line 210: | Line 210: | ||
read_lines print_endline (open_in Sys.argv.(1)) |
read_lines print_endline (open_in Sys.argv.(1)) |
||
</ocaml> |
</ocaml> |
||
=={{header|Perl}}== |
|||
The angle brackets operator ( <code><...></code> ) reads one line at a time from a filehandle in scalar context: |
|||
<perl>open FH, "< filename" or die "can't open file: $!"; |
|||
while ($line = <FH>) { |
|||
# process $line, includes newline |
|||
}</perl> |
|||
Or you can get a list of all lines when you use it in list context: |
|||
<perl>@lines = <FH>;</perl> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
Line 217: | Line 227: | ||
try: |
try: |
||
for line in my_file: |
for line in my_file: |
||
pass # process line |
pass # process line, includes newline |
||
finally: |
finally: |
||
my_file.close()</python> |
my_file.close()</python> |
||
Line 226: | Line 236: | ||
with open(filename, 'r') as f: |
with open(filename, 'r') as f: |
||
for line in f: |
for line in f: |
||
pass # process line</python> |
pass # process line, includes newline</python> |
||
You can also get lines manually from a file: |
You can also get lines manually from a file: |
Revision as of 06:34, 25 August 2008
You are encouraged to solve this task according to the task description, using any language you may know.
Read from a text stream either word-by-word or line-by-line until the stream runs out of data. The stream will have an unknown amount of data on it.
Ada
This example reads in a text stream from standard input line by line and writes the output to standard output. <ada> with Ada.Text_Io; use Ada.Text_Io;
procedure Read_Stream is
Line : String(1..10); Length : Natural;
begin
while not End_Of_File loop Get_Line(Line, Length); -- read up to 10 characters at a time Put(Line(1..Length)); -- The current line of input data may be longer than the string receiving the data. -- If so, the current input file column number will be greater than 0 -- and the extra data will be unread until the next iteration. -- If not, we have read past an end of line marker and col will be 1 if Col(Current_Input) = 1 then New_Line; end if; end loop;
end Read_Stream; </ada>
AWK
This just reads lines from stdin and prints them until EOF is read.
//{ print $0 }
C
<c>#include <stdio.h>
- define MAX_LEN 20
/* line by line: */ /* This may not read the whole line; just up to MAX_LEN characters at a time. */ void process_lines(FILE *stream) {
char line[MAX_LEN + 1]; while (fgets(line, MAX_LEN + 1, stream) != NULL) { /* process the string here */ /* the string includes the line return, if it reached the end of line */ }
}
/* word by word */ /* This may not read the whole word; just up to MAX_LEN characters at a time. */
- define Str(x) #x
- define Xstr(x) Str(x)
void process_words(FILE *stream) {
char word[MAX_LEN + 1]; while (fscanf(stream, "%" Xstr(MAX_LEN) "s", word) == 1) { /* process the string here */ }
} </c>
C++
The following functions store the words resp. lines in a vector. Of course, instead arbitrary processing of the words could be done. <cpp>#include <istream>
- include <string>
- include <vector>
// word by word void read_words(std::istream& is, std::vector<std::string>& words) {
std::string word; while (is >> word) { // store the word in the vector words.push_back(word); }
}
// line by line: void read_lines(std::istream& is, std::vector<std::string>& lines) {
std::string line; while (std::getline(is, line)) { // store the line in the vector lines.push_back(line); }</cpp>
An alternate way to read all words into a vector is to use iterators:
<cpp>#include <istream>
- include <string>
- include <iterator>
- include <algorithm>
- include <vector>
void read_words(std::istream& is, std::vector<std::string>& words) {
std::copy(std::istream_iterator<std::string>(is), std::istream_iterator<std::string>(), std::back_inserter(words));
}</cpp>
For arbitrary processing, replace std::copy with std::for_each or std::transform calling an appropriate function (or function object).
D
<d>import tango.io.Console; import tango.text.stream.LineIterator;
void main (char[][] args) {
foreach (line; new LineIterator!(char)(Cin.input)) { // do something with each line }
}</d>
<d>import tango.io.Console; import tango.text.stream.SimpleIterator;
void main (char[][] args) {
foreach (word; new SimpleIterator!(char)(" ", Cin.input)) { // do something with each word }
}</d>
Note that foreach variables 'line' and 'word' are transient slices. If you need to retain them for later use, you should .dup them.
Forth
4096 constant max-line : read-lines begin stdin pad max-line read-line throw while pad swap \ addr len is the line of data, excluding newline 2drop repeat ;
Haskell
The whole contents of a file can be read lazily. The standard functions lines and words convert that lazily into the lists of lines resp. words. Usually, one wouldn't use extra routines for that, but just use readFile and then put 'lines' or words somewhere in the next processing step.
import System.IO readLines :: Handle -> IO [String] readLines h = do s <- hGetContents h return $ lines s readWords :: Handle -> IO [String] readWords h = do s <- hGetContents h return $ words s
Java
Some people prefer Scanner or BufferedReader, so a way with each is presented. <java>import java.util.Scanner; ... Scanner in = new Scanner(System.in);//stdin //new Scanner(new FileInputStream(filename)) for a file //new Scanner(socket.getInputStream()) for a network stream while(in.hasNext()){ String input = in.next(); //in.nextLine() for line-by-line //process the input here }</java> Or <java>import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; ... try{ BufferedReader inp = new BufferedReader(new InputStreamReader(System.in));//stdin //new BufferedReader(new FileReader(filename)) for a file //new BufferedReader(new InputStreamReader(socket.getInputStream())) for a netowrk stream while(inp.ready()){ String input = inp.readLine();//line-by-line only //process the input here } } catch (IOException e) { //There was an input error }</java>
OCaml
<ocaml>let rec read_lines ic =
try let line = input_line ic in line :: read_lines ic with End_of_file -> []</ocaml>
The version above will work for small files, but it is not tail-recursive.
Below will be more scalable:
<ocaml>let read_line ic =
try Some (input_line ic) with End_of_file -> None
let read_lines ic =
let rec loop acc = match read_line ic with | Some line -> loop (line :: acc) | None -> List.rev acc in loop []
- </ocaml>
Or with a higher order function:
<ocaml>let read_lines f ic =
let rec loop () = try f(input_line ic); loop() with End_of_file -> () in loop()
read_lines print_endline (open_in Sys.argv.(1)) </ocaml>
Perl
The angle brackets operator ( <...>
) reads one line at a time from a filehandle in scalar context:
<perl>open FH, "< filename" or die "can't open file: $!";
while ($line = <FH>) {
# process $line, includes newline
}</perl>
Or you can get a list of all lines when you use it in list context: <perl>@lines = <FH>;</perl>
Python
Python file objects can be iterated like lists:
<python>my_file = open(filename, 'r') try:
for line in my_file: pass # process line, includes newline
finally:
my_file.close()</python>
One can open a new stream for read and have it automatically close when done, with a new "with" statement: <python>from __future__ import with_statement
with open(filename, 'r') as f:
for line in f: pass # process line, includes newline</python>
You can also get lines manually from a file: <python>line = my_file.readline() # returns a line from the file lines = my_file.readlines() # returns a list of the rest of the lines from the file</python> This does not mix well with the iteration, however.
Ruby
Ruby input streams are Enumerable objects like Arrays, so one can use the standard #each:
stream.each do |line|
# process line
end
One can open a new stream for read and have it automatically close when done:
File.open(filename, "r") do |stream|
stream.each do |line| # process line end
end
UnixPipes
the pipe 'yes XXX' produces a sequence
read by lines
yes 'A B C D ' | while read x ; do echo -$x- ; done
read by words
yes 'A B C D ' | while read -d\ a ; do echo -$a- ; done