5  Input and Output Statements

NoteWhat This Chapter Covers

This chapter introduces the two halves of every useful program: getting data in and sending results out. You will learn how R prints values to the console, the difference between implicit auto-printing and explicit print() and cat(), how to format output cleanly with paste(), paste0(), sprintf(), and format(), and the main functions for reading keyboard input or lines from a file. You will also meet the three message-signalling functions message(), warning(), and stop(), which tell the reader of your script whether something is fine, noteworthy, or broken. By the end of this chapter you will be able to write short programs that communicate clearly with their user.

flowchart LR
    U["User / Keyboard / File"] -->|input| R["R Program"]
    R -->|output| C["Console"]
    R -->|output| F["File"]
    R -->|message| M["Messages / Warnings / Errors"]
    style U fill:#e3f2fd,stroke:#1976D2
    style R fill:#fff3e0,stroke:#F57C00
    style C fill:#e8f5e9,stroke:#388E3C
    style F fill:#e8f5e9,stroke:#388E3C
    style M fill:#fbe9e7,stroke:#D84315


5.1 How R Prints Values

NoteCore Concept: Auto-Printing at the Top Level

When you type an expression at the R console and press Enter, R evaluates it and prints the result automatically. This behaviour is called auto-printing, and it only happens at the top level. Inside functions, loops, or scripts sourced with source(), auto-printing is suppressed; if you want output, you have to ask for it explicitly.

TipExpert Insight: Why Auto-Print Is Convenient but Risky in Scripts

Auto-printing is the reason R feels so interactive; every expression you type shows its result. Inside a function or loop, however, only explicit print() or cat() calls produce output. Beginners often write a loop that “does nothing” when in fact it is computing values perfectly and simply not printing them.


5.2 print() vs cat()

NoteTwo Ways to Send Output to the Console

R has two main functions for printing. They produce different output and are used in different situations.

Function What It Does Typical Use
print() Uses R’s full print method for the object; shows quotes on strings, type info on complex objects, and always starts on a new line. Showing results while debugging; inside scripts and functions.
cat() Concatenates its arguments and writes them as plain text; no quotes, no [1] prefix, no automatic newline. Human-readable messages; composing output from several pieces.
NoteA Richer Example
TipBest Practice: Use cat() for People, print() for Objects

If you are composing a readable message for a human (“Processed 42 rows”), use cat(). If you want to show a full R object as it is internally (a data frame, a list, a model object), use print(). The two are complementary, not competitors.

WarningCommon Mistake: Forgetting the Newline in cat()

cat() does not add a trailing newline. If you omit \n, the next piece of output starts on the same line as the previous one, producing confusing output in loops.


5.3 Building Readable Strings: paste(), paste0(), sprintf(), format()

NoteFour Tools for Text Assembly

Most real output is not a single value but a sentence that mixes text and values. R provides four core functions for assembling such strings.

Function Purpose Typical Call
paste() Joins pieces with a separator (default a space). paste("Total:", n)
paste0() Same as paste() with sep = "" (no separator). paste0("file_", i, ".csv")
sprintf() C-style format strings; precise control of width, decimals, padding. sprintf("%.2f", pi)
format() Turns a number into a nicely formatted string. format(1234567, big.mark = ",")
Notepaste() and paste0() in Action
Notesprintf() for Precise Formatting

sprintf() is the tool of choice when you need fixed decimal places, padding, or aligned columns.

Noteformat() for Numbers
TipExpert Insight: Choose the Right Tool for the Job

A quick rule of thumb: reach for paste() when you are joining ordinary strings, paste0() when building file names or URLs, sprintf() when decimals, widths, or padding matter, and format() when you need human-readable numbers with grouping marks or fixed precision. Mixing tools in one script is fine; consistency inside a single output statement is what matters.


5.4 Reading Input from the Keyboard

NoteCore Concept: Interactive Input in R

R is usually used in interactive mode, where you type expressions and see results. For programs that need to ask the user a question, R provides two core functions.

Function Purpose Returns
readline(prompt) Reads a single line of text from the console. A character string.
scan(what = ...) Reads one or more values separated by whitespace or a custom separator. A vector of the requested type.
WarningInteractive Input Does Not Work in the Browser

readline() and scan() only work when R is attached to an interactive terminal. They cannot prompt the reader inside the webr-powered chunks you see in this book, because webr does not have a keyboard session to read from. The examples below show the exact code you would run in RStudio or the R console on your own machine.

Notereadline() in RStudio or the R Console
# Type this in RStudio's console:
name <- readline(prompt = "What is your name? ")
cat("Hello,", name, "!\n")

When you run that script, R pauses at the prompt, waits for you to type a name and press Enter, and then continues. readline() always returns a character string, even if the user types a number.

NoteConverting Input to Numbers

Because readline() returns text, any numeric input must be converted explicitly with as.numeric() or as.integer().

# Interactive version (run in RStudio):
raw_age <- readline(prompt = "Enter your age: ")
age     <- as.numeric(raw_age)
cat("In ten years you will be", age + 10, "\n")

If the user types something that cannot be converted, as.numeric() returns NA and emits a warning. Always validate the result before using it.

Notescan() for Multiple Values

scan() reads several values at once. It is handy when you want the user to enter, say, ten numbers separated by spaces.

# Interactive version (run in RStudio):
# Type numbers separated by spaces, then press Enter on an empty line:
nums <- scan(what = numeric())
mean(nums)
sum(nums)
TipExpert Insight: Prefer Function Arguments Over Prompts in Real Code

Prompting the user with readline() is fine for demos and classroom exercises. For real analysis scripts, pass inputs as function arguments, command-line arguments, or values read from a configuration file. Scripts that pause for user input are hard to automate, test, or rerun.


5.5 Reading and Writing Files (a First Look)

NoteCore Concept: Files Are the Most Common Input

In practice, most real R programs read data from files, not from the keyboard. Module 3 will cover the tidyverse functions read_csv() and read_excel() in depth. Here we meet the base-R equivalents you should at least recognise.

Function Reads or Writes Produces
readLines(path) Reads a text file line by line. A character vector, one element per line.
writeLines(x, path) Writes a character vector to a text file. A file on disk.
read.csv(path) Reads a comma-separated file. A data frame.
write.csv(x, path) Writes a data frame to a CSV. A file on disk.
NoteWriting and Reading a Tiny CSV
TipBest Practice: Think About Encoding and Line Endings

Text files can differ in their encoding (UTF-8, Latin-1, etc.) and in how they end lines (LF on Linux and macOS, CRLF on Windows). When you write files that will be read by other tools, stick with UTF-8 and let R handle line endings with its defaults. If a file read returns strange characters, the encoding is almost always the culprit.


5.6 Signalling Messages, Warnings, and Errors

NoteThree Ways to Tell the Reader Something Happened

R separates “informational output” from three other kinds of signals. Each has a dedicated function and a different intent.

Function Meaning Does It Stop Execution?
message() Informational note. Shown in red in RStudio but not an error. No.
warning() Something is suspicious and worth noting; execution continues. No.
stop() A condition from which the program cannot reasonably continue. Yes. Raises an error.
NoteWhen to Use stop()

Use stop() when continuing would produce a wrong answer rather than a slow or noisy one.

WarningDo Not Use print() Where message() or warning() Is Correct

A common beginner habit is to scatter print("something happened") across a script. print() writes to standard output and cannot be suppressed separately from real results. message() writes to standard error, can be silenced with suppressMessages(), and signals intent much more clearly. Use the right tool.


5.7 A Mini End-to-End Example

NotePutting I/O Together

The snippet below combines formatted output, a computed result, and the signalling functions in a single readable script.

Notice how each piece of output plays a different role: message() narrates progress, warning() flags a data quality issue, cat() plus sprintf() produce the main numeric report, and the vector itself is never auto-printed because every computation happens inside the top-level block but is explicitly consumed.


5.8 Summary

NoteKey Concepts at a Glance
Concept Key Takeaway
Auto-printing At the top level, R prints the value of any expression. Inside functions and loops it does not.
print() vs cat() print() shows the R object in full; cat() writes human-readable text.
paste() and paste0() Join strings with and without separators; both are vectorised.
sprintf() C-style format strings; best for decimals, widths, and padding.
format() Human-readable numbers with grouping marks and fixed precision.
readline() and scan() Read keyboard input; only work in interactive R sessions, not in webr.
File I/O basics readLines() / writeLines() for text, read.csv() / write.csv() for tabular data.
Signalling message() for info, warning() for concerns, stop() for fatal errors.
TipApplying This in Practice

Clear I/O is what turns a script from “my private notebook” into “something someone else can run”. Adopt a simple habit: one message() at the start of a long computation, cat() plus sprintf() for the results, and warning() or stop() the moment something looks wrong. In the next chapter you will meet R’s basic data types and see how type casting lets you convert between them safely.