Input loop

From Rosetta Code
Revision as of 01:32, 4 May 2008 by rosettacode>Waldorf (Ada)
Task
Input loop
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.

{{header}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>

C

<c>#include <stdio.h>

  1. 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 */ /* WARNING: The scanf family of functions are very dangerous for reading strings

  because there is no mechanism to specify how long the buffer is, so it can overflow
  without warning. Avoid this if you can. Maybe there is a better way to do it. */

void process_words(FILE *stream) {

 char word[MAX_LEN + 1];
 while (fscanf(stream, "%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>

  1. include <string>
  2. 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>

  1. include <string>
  2. include <iterator>
  3. include <algorithm>
  4. 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).

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>

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