Decimal and Text in File Streams, Explained with Code Examples

UPI Study › Courses › C++ Programming › Free lessons › Lesson 10.2 Free with a free account

Decimal and Text in File Streams

C++ Programming · Chapter 10: File Access and MemorySection 10.2 · lesson 70 of 84video coming soon

← Non-Sequential File AccessNext lesson: Designing a File-Driven Record System →

Earn 3 college credits for C++ ProgrammingRecommended for credit by NCCRS · Computer Science 242 · self-paced · one payment, lifetime access

In this lesson

Precision and formatting concerns.

  • Weigh text storage against raw bytes
  • Write a double so it reads back exactly
  • Choose a delimiter, and avoid the getline trap
  • Convert text fields back to numbers with a check

Transcript

Everything said in the video, section by section (1,744 words). Read along, or search it.

Opening Problem

Round Trips Can Silently Lose Data

Writing a number to a file converts it into characters. Reading it back converts those characters into a number again. Neither step is guaranteed to be lossless, and by default, it isn't. A value can leave your program, be written, be read back, and no longer be the value you started with, with nothing anywhere reporting a problem. This section is about controlling that round trip deliberately.

Two Approaches

Text Versus Binary Storage of Doubles

A double in memory is eight bytes with a fixed meaning. There are two quite different things a program can do with it. Text storage converts the value into the characters a person would write, and stores those. Binary storage copies the eight bytes exactly as they sit in memory. Written a thousand times each way, the binary file is exactly eight thousand bytes. The text file here is more than twice the size, because a value like one seventh needs nineteen characters plus a line ending.

Trade-offs

Weighing Readability Against Exactness

Text is readable by a person, and highly portable: any machine, any language, any tool. Its fidelity is only as good as the precision you request. Binary is meaningless without a program that knows the layout, and type widths and byte order differ between machines. But binary is exact, and its size is predictable. That text fidelity is recoverable, which is why text is the default choice for most work. Binary suits bulk numbers for your own program. Text suits configuration, reports, and shared data.

The Problem

Default Precision Corrupts Point One Plus Point Two

Here's the problem in its clearest form. A value is computed, zero point one plus zero point two, written to a file, and read straight back. The file contains zero point three. Not because anything went wrong, but because a stream's default precision is six significant digits, the same display setting as on the screen. Six digits was plenty to display the value. It wasn't enough to reconstruct it. In memory, it's zero point three zero zero, and then a four, out at the seventeenth digit. Read back, it's zero point two nine nine, nine nine. They don't match. And nothing reported this. The write succeeded, the read succeeded, and the program now holds a different number. Repeat the cycle, loading, adjusting and saving, and the drift compounds.

The Fix

Writing Enough Digits for Exact Recovery

Now follow the round trip. With the default precision, the value is written as zero point three, and read back as something slightly different. The loss happens at the moment of writing. With enough digits, the file holds all seventeen, and the value read back is exactly the original. Run the second call and the match is exact. Reading isn't at fault in either case. It faithfully reconstructs whatever the file actually holds. The number of digits needed isn't a guess. The library states it: numeric limits of double, max digits ten. That's seventeen for every double, on any conforming implementation. Write the name rather than the literal seventeen, so the code stays correct if the type ever changes.

Digit Counts

Three Easily Confused Digit Settings

Three digit counts are easily confused. Max digits ten is how many digits to write so a value can be read back exactly: seventeen for a double. That's the one for saving data. Digits ten is how many decimal digits a value can carry reliably: fifteen for a double. That's the honest precision of the type. And the stream default of six is neither of those. It's a display setting, chosen because six digits is comfortable to read. That makes it a perfectly sensible default for a screen, and a poor one for a file.

Quick Check

Digits Needed to Save Floats

Quick check. A program saves float values, not doubles, and must reload them exactly. How many digits does it need to write? Pause and think. Nine. Seventeen is the figure for a double; it would still work, but it's more than a float needs. Max digits ten of float reports nine, so writing the name gets it right automatically.

Fixed Decimals

Fixing Decimal Places for Meaningful Data

Seventeen digits in every field makes a file large and hard to read, and for a lot of data, it's pointless. A price, a temperature, or a percentage has nowhere near seventeen meaningful digits. For those, fix the number of decimal places instead. With fixed and a precision of two, the file holds zero point three zero. That doesn't round-trip exactly, and that's the correct outcome. The file says what the value means, thirty paise, rather than what the machine happens to hold. And the manipulators are sticky here too. Set them once on the file stream, before the first value. A setting applied to c out doesn't apply to your file. Each stream carries its own.

Decision Guide

Matching Precision to the File's Reader

So the choice depends on who the file is for. For your own program to reload, write max digits ten, so reloading gives back the same value. For money, exactly two decimal places, or better, hold whole paise. For measurements, the instrument's precision, so the file doesn't state precision the data lacks. And for a person to read, fixed, with a few digits. Readability is the point.

Common Failure

When a Delimiter Appears Inside Data

A file holding more than one value per record needs a delimiter between them. Choosing it badly causes a specific, common failure. Here's a comma-separated file in which one field legitimately contains a comma: Pune comma M H, in quotation marks. The third line splits into four fields, because the delimiter appeared inside a value. The quotation marks mean something to a person, and nothing to a splitter that only knows about commas. And on the second line, the age arrived as space thirty-seven, with a leading space. A space after the comma is invisible to the eye, and part of the field to the program.

Comparing Options

The Cost of Each Delimiter

Every delimiter has a cost. A comma fails when a field contains a comma, which is common in names, addresses and free text. Its real advantage is that other tools universally understand it, but it needs quoting rules to be safe. A tab fails only when a field contains a tab, which is rare in typed data. A pipe is rarer still. And one field per line can't collide at all.

Safeguards

Three Ways to Protect a Delimiter

There are three ways to make a delimiter safe. Choose one the data can't contain, which removes the problem rather than managing it. Reject values containing it at the point of writing, so the fault is reported then, not discovered months later. And trim leading and trailing whitespace from every field you read.

Common Mistake

Mixing Extraction and Get Line

Two ways of reading text behave quite differently around whitespace, and mixing them produces one of the most reported puzzles in the language. The extraction operator skips leading whitespace, reads until the next whitespace, and leaves that whitespace in the stream. Get line reads everything up to the line ending, keeps the spaces, and discards the line ending. Take a file whose first line is Anya Sharma. Read with extraction alone, the name is just Anya, and the age read fails, because it tried to read Sharma as a number. Read with get line, then extraction, both work. But extraction followed by get line gives space Sharma: the rest of the same line, not the next one. The usual form is worse. When extraction reads the last item on a line, the very next get line finds the leftover line ending immediately, and returns an empty string. The program appears to skip a line.

Rules

Avoiding the Whitespace Trap

Two rules avoid it entirely. Don't mix the two on one stream. Read whole lines with get line and split them yourself, or read item by item with extraction. Choosing one and staying with it removes the problem, rather than working around it. If you must mix, discard the rest of the line after the last extraction, before calling get line. Reaching for that second rule repeatedly is a sign the first rule was the right one.

Conversion Risks

Why A T O F Hides Bad Fields

Once a line has been split, each field is text. Converting one to a number is where, quietly, a file of slightly wrong data becomes a program of slightly wrong results. Compare two functions. On forty-two point five, both give forty-two point five. On forty-two point five k g, both give forty-two point five, but S T O D also tells you how much of the text it used. On a b c, or on an empty field, S T O D throws an exception. A T O F returns zero. And zero is a perfectly ordinary value. So a corrupted field becomes a zero that flows into the rest of the program, indistinguishable from a real one. On a number too large to represent, S T O D throws. The standard promises nothing about A T O F there, and here it handed back infinity.

Safe Practice

Checking How Much S T O D Used

So convert with a check. Pass S T O D a variable to receive how many characters it used. If that isn't the whole field, something was left over, so treat it as a bad field. S T O D reports outright failure by throwing an exception. And the count answers a question the older function can't. It catches forty-two point five k g: text that converts successfully, and still isn't what the field was supposed to contain.

Key Terms

Vocabulary for Text and Binary Storage

A few key terms. Text storage stores a value as the characters that spell it. Binary storage stores its bytes exactly as they sit in memory. A round trip is writing a value out and reading it back. It's exact when the value returns unchanged. Max digits ten is the number of digits to write for an exact read-back, seventeen for a double. Digits ten is how many a type carries reliably, fifteen. A delimiter separates fields, and trimming removes whitespace around one. And a checked conversion turns text into a number by a means that reports failure.

Think About It

What Lands in the Name

Here's something to think about. One line of a file reads forty-two, then Anya Sharma. A program reads the age with extraction, then the name with get line. What ends up in the name? Pause and think. Space Anya Sharma, with a leading space. Extraction stopped right after forty-two, so get line took the rest of that same line, space included.

Key Takeaways

Summary of Safe File Practices

To summarize. Text storage is readable and portable. Binary storage is exact and compact. The default six digits loses data, so write max digits ten when your program will reload the values. Use fixed decimals when the data means a set precision. Choose a delimiter the data can't contain, and trim every field you read. Don't mix extraction and get line on one stream, and convert with S T O D, checking how much it used.

About C++ Programming at UPI Study

C++ Programming (Computer Science 242) is a self-paced online course of 84 video lessons in 11 chapters, from your first program to decisions, loops, arrays, functions, classes, files, pointers and inheritance. It carries a NCCRS credit recommendation for 3 semester credits.

Every lesson transcript is free on pages like this one, and the videos are free with a free UPI Study account. Enrolling adds a practice quiz after each lesson, the graded work and final exam that earn the credit, lifetime access, and an official transcript on completion. UPI Study has helped over 130,000 students with college credits. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Why take it here

Why students take C++ Programming with UPI Study

Your first real programming languageC++ teaches how programs really work: variables, control flow, functions, memory and objects. It is the base for data structures, algorithms, systems and game programming, and for most computer-science degrees.
Credit at a fraction of the priceThe same 3 credits can cost $750 or more at a US college. Here it is one payment, self-paced, with lifetime access.
Finish your degree soonerTransfer credits reduce the courses you still owe, so you can graduate earlier or lighten a heavy semester.
Strengthen an applicationA completed college-level course on an official transcript shows admissions and scholarship committees you can do the work.
Study on your own scheduleNo start dates, no deadlines. Watch the lessons, practice, and take the final when you are ready.
130,000+students helped with college creditsACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Where the credit goes

Universities that work with NCCRS

C++ Programming carries a NCCRS credit recommendation. These universities work with NCCRS; some are UPI Study's signed partners. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Find my college → Not listed? Ask Athena in the corner of this page, or book a 15-minute call.

FAQ

Questions students ask us

About Decimal and Text in File Streams

How do I write a double to a file in C++ so it reads back exactly?
Set the file stream's precision to std::numeric_limits<double>::max_digits10, which is 17, before writing any values. The default precision is six significant digits, so 0.1 + 0.2 is saved as 0.3 and reads back as a slightly different number. Apply the setting to the file stream itself, because a setting on cout does not affect it.
What is the difference between text and binary storage of a double in a file?
Text storage writes the characters a person would read, while binary storage copies the eight bytes of a double exactly as they sit in memory. Text is readable and portable, but only as exact as the precision you request. Binary is exact and predictable in size, so 1000 doubles take 8000 bytes, but it needs a program that knows the layout.
Why does getline return an empty string after cin >> in C++?
The extraction operator stops at whitespace and leaves the line ending in the stream, so the next getline finds that line ending immediately and returns an empty string. The program appears to skip a line. The cleanest fix is to avoid mixing the two on one stream. If you must mix them, discard the rest of the line after the last extraction.
How do I convert a string field to a double in C++ and detect bad input?
Call std::stod with its second argument and compare the characters used to the field length. For example, std::size_t used; double v = std::stod(field, &used); then treat the field as bad if used != field.size(). For 42.5kg, used is 4 but the length is 6. stod throws an exception on abc or an empty field, while atof quietly returns 0.

About the C++ Programming course

How many college credits is C++ Programming?
C++ Programming (Computer Science 242) carries a NCCRS credit recommendation for 3 semester credits. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.
How much does C++ Programming cost and what is included?
$250, paid once, with lifetime access: all 84 video lessons, a practice quiz after each, the graded work and final exam, and an official transcript when you finish. Students who want several courses choose UPI Study PRO instead.
Which universities accept UPI Study credits?
UPI Study has signed partner agreements with universities such as Thomas Edison State University, University of the People and Charter Oak State College, and works with universities such as Penn State, SNHU and SUNY. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities. Use "Find my college" on this page to check yours.
How long does C++ Programming take?
It is self-paced with no deadlines. The 84 lessons total about 0 hours of video; most students add reading and practice time and finish in a few weeks to a few months, on their own schedule.
How are the exams done?
Quizzes and assignments are online in the course. The final exam is taken online with proctoring; a person on the UPI Study team checks assignments, usually within two days.
How do my credits reach my college?
When the course shows 100% complete, request the official transcript from your dashboard. It is sent to the college you name, and you can send it to more than one. Check your college first with "Find my college" on this page, or ask Athena.

Ready for the full course? Earn 3 credits in C++ Programming.

84 video lessons, a quiz after each one, and the graded work that earns the credit. Recommended for credit by NCCRS.

C++ Programming
3 credits · NCCRS
Enroll →