1 of 60

COMPUTER

PROGRAMMING

Deck 5

How Can a Program

Process and Interpret Text?

Strings, explicit formats, and careful changes to an AI-assisted project

Guan-Ju Peng @ AM, NCHU

Deck 5 | 1

2 of 60

Our loop works. The input interface is still awkward.

Keep Deck 4’s calculations and totals; change how one record enters the program.

Bridge from Deck 4

Deck 5 | 2

[U1]

A text-processing change should not silently change the numerical model.

Version 0.4

Route label: Campus East

Distance in km: 12.5

Duration in minutes: 45

Version 0.5

One line per trip:

​

Campus East,12.5,45

​

Then another line — or DONE.

3 of 60

The request is “accept this whole line”

Driving problem: separate fields, clean only their edges, and preserve their meaning.

Driving problem

Deck 5 | 3

Whitespace tolerance is useful. Losing parts of a label is not.

USER INPUT · FOUR LINES

Campus East , 12.5 , 45

Broken,1

Station,3.5,30

done

Expected summary

Accepted trips: 2

Total distance: 16.00 km

Total duration: 75 min

Overall speed: 12.80 km/h

4 of 60

Today’s inquiry ladder

Driving question: How can a program process and interpret text?

Roadmap

Deck 5 | 4

Build: Trip Text v0.5 | AI skill: controlled modification | Foundations: encoding + storage

01

What is text, and what does our format promise?

02

How do we access and extract parts of text?

03

How do we inspect and transform text without damaging it?

04

How do we turn one line into validated fields?

05

How do characters become bytes and persistent files?

06

How can AI help us modify the tool without changing its rules?

5 of 60

What is text, and what does our format promise?

Q1 · A new text requirement creates a need for a new idea.

Q1 · Driving sub-question

Deck 5 | 5

The meaning comes from an agreed format, not from the string alone.

Q1

“Campus East,12.5,45”

​

How does the program know which part

is a name, a distance, or a duration?

6 of 60

Make the changes from v0.4 explicit

These are classroom design decisions, not universal rules for cleaning text.

Q1 · Versioned contract

Deck 5 | 6

[U1]

New behavior needs new tests. A “cleanup” must not invent a different policy.

Policy

Version 0.5 promise

Record

Exactly route, km, minutes; three comma-delimited fields.

Whitespace

Trim field edges; preserve internal spaces and label case.

Stop command

Only the entire trimmed line DONE, ignoring case.

Format limits

Reject double quotes and extra/missing fields.

Earlier behavior

Keep value checks, reports, bands, and accepted-only totals.

7 of 60

A string is data, not a calculation

Python uses str for text, including a single character.

Q1 · Text values

Deck 5 | 7

[P1] [P2] [P5]

Choose operations from the meaning of the data, not just its appearance.

PYTHON

print(type("007"))

print(len("007"))

print("3" + "5")

print(3 + 5)

print("Trip " * 2)

Output

<class 'str'>

3

35

8

Trip Trip

8 of 60

Some characters are easier to see with repr()

Quotes in source code delimit a literal; they are not usually part of its value.

Q1 · Literals and invisible characters

Deck 5 | 8

[P1] [P5]

Do not confuse how a value is written in Python with what the user types.

PYTHON

text = "A\tB\nC"

print(text)

print(repr(text))

print(len(text))

Read the representation

\t → tab

\n → newline

​

repr(text): 'A\tB\nC'

len(text): 5

9 of 60

Names can change; string objects do not

Immutability concerns the string value, not whether a name can be rebound.

Q1 · Names and immutable values

Deck 5 | 9

[P3] [P4]

Assignment binds names. It does not mean “always allocate and copy the string.”

PYTHON

s = "Campus"

t = s

s = "Station"

print(s)

print(t)

After the reassignment

s

"Station"

t

"Campus"

10 of 60

How do we access and extract parts of text?

Q2 · A new text requirement creates a need for a new idea.

Q2 · Driving sub-question

Deck 5 | 10

Indexing selects one item. Slicing describes a region.

Q2

A label contains several characters.

​

How do we request one character —

or a whole region — without retyping it?

11 of 60

Give every character a position

For this ASCII example, one visible letter is one code point.

Q2 · Indexing

Deck 5 | 11

[P1] [P2]

The last non-negative index is len(s) - 1, not len(s).

s = "Campus"

0

C

-6

1

a

-5

2

m

-4

3

p

-3

4

u

-2

5

s

-1

s[0] → "C" s[-1] → "s" len(s) → 6

12 of 60

An index must refer to an existing item

Empty text and one-past-the-end are ordinary cases to think about.

Q2 · Boundary checks

Deck 5 | 12

[P1]

Check the precondition before asking for a first or last character.

PYTHON

label = input("Label: ")

if label != "":

print(label[0])

else:

print("No first character")

Isolated error examples

"Campus"[6]

→ IndexError

​

""[0]

→ IndexError

13 of 60

A slice includes its start and excludes its stop

s[start:stop] returns a string; stop is a boundary, not a selected character.

Q2 · Slicing

Deck 5 | 13

[P1]

Think “up to, but not including stop.”

Expression, with s = "Campus"

Selected positions

Result

s[1:4]

1, 2, 3

"amp"

s[:3]

0, 1, 2

"Cam"

s[3:]

3, 4, 5

"pus"

s[3:3]

none

""

s[1:100]

1 through 5

"ampus"

14 of 60

Negative indices and steps describe useful regions

Use a small word to check the result rather than memorizing an opaque formula.

Q2 · Slices with a step

Deck 5 | 14

[P1] [P2]

A reversed string is a code-point reversal, not a universal text-layout operation.

PYTHON

s = "Campus"

print(s[-3:])

print(s[::2])

print(s[::-1])

print(s[:])

Predicted values

pus

Cmu

supmaC

Campus

​

Original s is unchanged.

15 of 60

Find a boundary before you slice around it

find() returns -1 when the substring is absent.

Q2 · Search plus extraction

Deck 5 | 15

[P2]

A missing delimiter is not a valid boundary at the end of the label.

PYTHON

line = input("Text: ")

pos = line.find(",")

if pos == -1:

print("No comma")

else:

print(line[:pos])

Try two inputs

Campus,12.5,45

→ Campus

​

Campus

→ No comma

16 of 60

Lab A: extract a useful label without losing information

Six minutes: predict, run, then explain the empty-input case.

Q2 · Lab A · 6 minutes

Deck 5 | 16

Keep 007 as text when its spelling is part of the identifier.

tag = "TRIP-007"

01

Get the first character, final character, prefix, and numeric-looking suffix.

02

Keep the suffix as text. What would int() change?

03

Handle an empty tag without an index error.

04

Explain tag[4:4], tag[:100], and tag[len(tag)].

17 of 60

How do we inspect and transform text without damaging it?

Q3 · A new text requirement creates a need for a new idea.

Q3 · Driving sub-question

Deck 5 | 17

A useful transformation follows a policy; it is not arbitrary deletion.

Q3

“Make the input more forgiving.”

​

Which differences may we ignore —

and which differences are real data?

18 of 60

The loop already knows how to visit text

Reuse a counter to ask a precise question about each character.

Q3 · Traversal

Deck 5 | 18

[P1] [P2]

State exactly what is being counted. A character test is not a number parser.

PYTHON

label = "Route 007"

digit_count = 0

for ch in label:

if ch in "0123456789":

digit_count += 1

print(digit_count)

Predict the counters

ASCII digits: 3

​

"aaaa".count("aa")

→ 2

​

Matches do not overlap.

19 of 60

Choose the search that matches your question

Equality, membership, and position are different results.

Q3 · Search semantics

Deck 5 | 19

[P2]

Use in for “is it present?” Do not use if text.find(...): as an existence test.

For label = "Campus East"

Question

Result

label == "Campus"

Whole value equal?

False

"Campus" in label

Substring present?

True

label.find("Campus")

First position?

0

label.startswith("Campus")

At the beginning?

True

label.find("West")

Missing substring?

-1

20 of 60

Trim the edges; keep the name

strip() is not the same operation as removing every space.

Q3 · Cleanup policy

Deck 5 | 20

[P2]

This version explicitly changes edge whitespace; it does not change internal whitespace.

PYTHON

raw_label = " Campus East "

label = raw_label.strip()

print(repr(raw_label))

print(repr(label))

The permitted change

' Campus East '

↓

'Campus East'

​

Not 'CampusEast'.

21 of 60

Normalize a command comparison, not the whole record

The entire trimmed line must equal DONE after case conversion.

Q3 · Command recognition

Deck 5 | 21

[P2]

A command is determined by its whole-line role, not by a word appearing inside data.

FRAGMENT · INSIDE THE EXISTING while LOOP

line = raw_line.strip()

if line.upper() == "DONE":

break

# Otherwise, parse a trip record.

Which lines stop?

DONE → stop

dOnE → stop

Donegal,1,30 → record

DONE,1,30 → record

22 of 60

A text method returns a result; use the result

Creating another value is different from modifying the existing string.

Q3 · Transformation and immutability

Deck 5 | 22

[P2] [P3] [P4]

s = s.replace(...) rebinds s. It does not mutate the object still referenced by t.

PYTHON

s = "Campus East"

t = s

s.replace("East", "West")

print(s)

s = s.replace("East", "West")

print(s)

print(t)

Output

Campus East

Campus West

Campus East

​

s[0] = "c" is not allowed.

23 of 60

Lab B: tolerant comparison, faithful display

Seven minutes: clean a name and search a comparison copy.

Q3 · Lab B · 7 minutes

Deck 5 | 23

Explain which transformations affect the stored label and which affect only a comparison.

raw_label = " Campus East "

01

Trim only the edges; keep raw_label for comparison.

02

Find campus without case sensitivity; keep display case unchanged.

03

Count ASCII digits in Route 007 with a loop.

04

Check DONE, padded done, Donegal,1,30, and DONE,1,30.

24 of 60

How do we turn one line into validated fields?

Q4 · A new text requirement creates a need for a new idea.

Q4 · Driving sub-question

Deck 5 | 24

Separate format, numeric conversion, and value validation.

Q4

“Campus East,12.5,45”

​

Where should we split? What must be

checked before we can calculate?

25 of 60

split(",") separates fields, not their meanings

The result is an ordered list; each item is still a string.

Q4 · Splitting a record

Deck 5 | 25

[P2]

Splitting does not convert "12.5" into 12.5. It only identifies pieces of text.

PYTHON

line = "Campus East, 12.5, 45"

fields = line.split(",")

print(fields)

print(len(fields))

['Campus East', ' 12.5', ' 45']

Three items — with whitespace still present in the numeric fields.

26 of 60

A small list bridge: count items, then select an item

Only len() and indexing are needed for this lesson’s list result.

Q4 · Required prerequisite bridge

Deck 5 | 26

[P12] [P2]

fields[0] selects a field. line[0] selects a character. Keep the two levels separate.

Expression

Value / role

len(fields)

3 items

fields[0]

"Campus East" — the label

fields[1]

" 12.5" — distance text

fields[2]

" 45" — duration text

fields[1].strip()

"12.5" — still text

27 of 60

Check the shape before indexing the fields

A missing item must not turn into an unexpected IndexError.

Q4 · Safe field extraction

Deck 5 | 27

[P2] [P12]

Do not discard an extra field or invent a missing value to make the input fit.

FRAGMENT · AFTER THE COMMAND / EMPTY / QUOTE CHECKS

fields = line.split(",")

if len(fields) != 3:

print("Error: expected route, km, minutes.")

continue

route_name = fields[0].strip()

distance_text = fields[1].strip()

duration_text = fields[2].strip()

28 of 60

One invalid line should fail at one clear stage

Apply the agreed first-error order; update no totals before acceptance.

Q4 · Validation pipeline

Deck 5 | 28

[U1]

Parsing asks “can this text become the required type?” Validation asks “is the value allowed?”

01

Recognize the whole-line stop command.

02

Check empty line, unsupported quotes, and exactly three fields.

03

Trim the fields; reject an empty label.

04

Convert distance and minutes; reject malformed numeric text.

05

Apply the old value rules; then report and update once.

29 of 60

Malformed numeric text needs a narrow recovery path

This small guard is supplied scaffolding; text processing remains today’s focus.

Q4 · Provided parsing guard

Deck 5 | 29

[P5] [P6]

Do not “repair” malformed data by silently rounding or truncating it.

PROVIDED FRAGMENT · INSIDE while, AFTER LABEL CHECK

try:

distance_km = float(distance_text)

duration_min = int(duration_text)

except ValueError:

print("Error: distance must be numeric "

"and minutes an integer.")

continue

30 of 60

A simple delimiter is not a complete CSV grammar

Our core format deliberately rejects double quotes and extra fields.

Q4 · Scope boundary

Deck 5 | 30

[P2] [P8]

A limitation stated and tested is safer than accidental support that corrupts records.

Input

What it means under v0.5

Campus,,45

3 fields; empty distance → conversion error

Campus,1,45,

4 fields → shape error

"Campus, East",1,45

Contains double quotes → unsupported-format error

Campus East,1,45

3 fields → ordinary valid record

31 of 60

Lab C: predict the first rejection stage

Five minutes: use the contract, not the current candidate’s output.

Q4 · Lab C · 5 minutes

Deck 5 | 31

An input can violate several rules. The specification decides which error appears first.

Input

Your first outcome

Campus,1

?

Campus,,30

?

,1,30

?

Campus,-1,0

?

Campus,1,30.0

?

done

?

32 of 60

New text handling must preserve old numerical decisions

The same parsed values must receive the same report and classification.

Q4 · Regression behavior

Deck 5 | 32

[U1] [P11]

The front end changes; the accepted-only invariant and formulas do not.

Existing rule

Still required

Distance must be finite

Reject nan and inf after conversion.

Zero distance is allowed

0 km / 30 min is valid.

Time bands

30 → Short; 60 → Medium; 61 → Long.

Session state

Only accepted trips change the count and totals.

Empty summary

No division when there are no accepted trips.

33 of 60

Test what a text cleanup is allowed to change

Use specific labels that reveal accidental transformations.

Q4 · Preservation tests

Deck 5 | 33

“Looks cleaner” is not evidence that the data still means the same thing.

Input line

Expected label / action

Campus East , 12.5 , 45

Campus East

West Gate ,1,30

West Gate (keep two internal spaces)

007,0,30

007 (not 7)

Donegal,1,30

Donegal — accept, do not stop

DONE,1,30

DONE — accept, do not stop

34 of 60

How do characters become bytes and persistent files?

Q5 · A new text requirement creates a need for a new idea.

Q5 · Driving sub-question

Deck 5 | 34

Separate text, encoding, program state, and persistent storage.

Q5

A string can contain more than English letters.

​

How does that text travel to a file —

and what remains after the program ends?

35 of 60

ASCII gives familiar characters numeric codes

Selected entries are enough to explain the mapping; no full-table memorization.

Q5 · Computer foundations · ASCII

Deck 5 | 35

[P5] [P7] [U3]

The character "0" has code 48; it is not the numeric value 0.

Character

Decimal code

Python expression

space

32

ord(" ")

"0"

48

ord("0")

"A"

65

ord("A")

"a"

97

ord("a")

chr(65) → "A" ord("A") → 65

36 of 60

Unicode identifies characters; UTF-8 encodes them

A code point and a byte are different units.

Q5 · Computer foundations · Encoding

Deck 5 | 36

[P7]

len(text) counts code points. len(text.encode("utf-8")) counts encoded bytes.

Text value

A + U+4E2D

2 Unicode code points

UTF-8

Byte sequence

41 E4 B8 AD

4 bytes (hexadecimal)

PYTHON · SAME VALUE AS A FOLLOWED BY U+4E2D

text = "A\u4e2d"

print(len(text), len(text.encode("utf-8"))) # 2 4

37 of 60

Visible symbols, code points, and bytes can differ

Two spellings can look alike without having the same sequence of code points.

Q5 · Computer foundations · Length

Deck 5 | 37

[P7] [P10]

Do not use a byte count or code-point count as a universal count of visible characters.

PYTHON

a = "\u00e9" # precomposed e-acute

b = "e\u0301" # e + combining acute

print(len(a), len(b))

print(len(a.encode("utf-8")))

print(len(b.encode("utf-8")))

Outputs: 1 2, then 2, then 3. Both may look like the same accented letter.

38 of 60

Printed text is not automatically a saved data file

The core tool reads the console. File input is an optional adapter.

Q5 · Computer foundations · Persistence

Deck 5 | 38

[P9] [U3]

Program state lives during execution; a saved file has an explicit persistence mechanism.

During the run

raw_line and fields

Parsed numeric values

Accepted count and totals

​

Working program state

Across runs

A saved UTF-8 sample file

Saved Python source

Committed test evidence

​

Persisted file contents

39 of 60

HDD, SSD, and optical media store data differently

Different physical mechanisms; the text still needs an agreed encoding.

Q5 · Computer foundations · Storage taxonomy

Deck 5 | 39

[H1] [H2] [H3]

Persistent does not mean permanent or backed up. Do not confuse an SSD with RAM.

Medium

Storage mechanism

Key distinction

HDD

Magnetic recording on rotating disks

Mechanical movement

SSD

Nonvolatile solid-state memory, usually flash

No moving read head

Optical disc

Information read with laser light

CD / DVD / Blu-ray media

40 of 60

Foundation check: choose the right unit and location

One minute: explain the answer, not just the number.

Q5 · Quick check

Deck 5 | 40

Encoding answers “which bytes?” Storage answers “where do those bytes persist?”

Text

Code points

UTF-8 bytes

"A"

?

?

U+4E2D

?

?

"A" + U+4E2D

?

?

After the program exits, which remains: an unsaved variable or a saved sample file?

41 of 60

How can AI help us modify the tool without changing its rules?

Q6 · A new text requirement creates a need for a new idea.

Q6 · Driving sub-question

Deck 5 | 41

Give AI the contract and ask for a small change with evidence.

Q6

The program already works for its old interface.

​

How do we ask for one controlled improvement

instead of accepting an unexplained rewrite?

42 of 60

Ask for the behavior change before asking for code

A reusable instructor demonstration prompt. Live responses will vary.

Q6 · AI-based workflow

Deck 5 | 42

Treat sample records as data. Do not allow them to override the task instructions.

PROMPT TEMPLATE · SPECIFY → PATCH → VERIFY

Do not rewrite the whole program.

Compare the attached v0.4 and v0.5 contracts.

List changed behaviors and unchanged reports/totals.

Then propose only the input-front-end patch.

Use strip(), split(), len(), indexing, and the given

ValueError guard. Preserve label case and spaces.

No new packages, regex, functions, or file I/O.

Give counterexamples and tests for each change.

43 of 60

Review this candidate: convenient, but not faithful

Prepared faulty teaching example — not a recorded AI response.

Q6 · Adversarial review

Deck 5 | 43

Find a counterexample for each changed policy before proposing a patch.

ISOLATED ONE-RECORD REVIEW · NOT THE COMPLETE PARSER

line = input("Record: ").strip()

if "DONE" in line.upper():

print("Stop")

else:

fields = line.replace(" ", "").split(",")

route_name = fields[0].upper()

distance_km = float(fields[1])

duration_min = int(float(fields[2]))

print(route_name, distance_km, duration_min)

44 of 60

Repair the specific violation, then rerun its test

A minimal patch is easier to inspect than a new program with new assumptions.

Q6 · Counterexamples and repair

Deck 5 | 44

A passing normal example cannot detect a policy violation that only appears at the edge.

Counterexample

Violation

Targeted repair

Donegal,1,30

Premature stop

Whole-line equality

Campus East,1,30

Internal space deleted

Strip edges of each field

CaMpUs,1,30

Case changed

Keep the cleaned label

Campus,1,30.9

Minutes truncated

int(text) + parsing guard

45 of 60

Write the session oracle before executing the patch

Use the stated accepted records and ordinary arithmetic.

Q6 · Independent expected results

Deck 5 | 45

Check both the numerical output and the preservation of each accepted label.

Quantity

Derivation

Expected display

Accepted trips

Campus East + Station

2

Total distance

12.5 + 3.5

16.00 km

Total duration

45 + 30

75 min

Mean duration

75 / 2

37.50 min

Overall speed

16 / (75 / 60)

12.80 km/h

46 of 60

Change one thing: what should stay the same?

These paired tests check the meaning of the modification.

Q6 · Verification beyond one example

Deck 5 | 46

AI can suggest useful transformations. The contract decides which invariants are valid.

01

Add field-edge whitespace → same cleaned label and numbers.

02

Change only label case → same numbers; preserve the new spelling.

03

Insert one rejected line → accepted count and totals unchanged.

04

Use DONE as a field value → a record, not the whole-line command.

05

End immediately → zero accepted trips and no unsafe averages.

47 of 60

Integrate a text front end with the loop you already trust

Continue the same project; keep the tested calculation and summary blocks.

Q6 · Integration · trip_text.py

Deck 5 | 47

One line is accepted, rejected, or a stop command. No partial record enters the totals.

01

Read a raw line and recognize the whole-line command.

02

Check the format; split and trim three fields.

03

Convert numeric text, then apply the previous value checks.

04

On acceptance: preserve the report and update totals once.

05

After DONE: produce the same guarded summary.

48 of 60

Lab D: finish the line-based trip tool

Twelve minutes to integrate a small front-end change and test three sessions.

Q6 · Build task · 12 minutes

Deck 5 | 48

Success means tested behavior you can explain, not just a script that starts.

01

Add trip_text.py in the existing repository; keep trip_log.py.

02

Complete TODO A–C: shape checks, fields, and clean label.

03

Reuse the supplied parsing guard and the old report/summary.

04

Run immediate DONE, the mixed session, and label-preservation cases.

05

Explain one slice, one field guard, and one preserved invariant.

49 of 60

Push a reviewed text-handling change with its evidence

Use the same local repository and GitHub Desktop workflow.

Q6 · Project continuity

Deck 5 | 49

[G1] [G2]

Commit message idea: “Add tested one-line trip input with preserved labels”.

01

Save and run trip_text.py from the existing project folder.

02

Record spec_deck5.md, tests_deck5.md, and ai_use_deck5.md.

03

Inspect the diff: were labels or formulas changed unintentionally?

04

Commit, Push origin, and verify the latest files online.

05

Exclude private route histories, secrets, and unreviewed AI transcripts.

50 of 60

A small text tool can solve a real nuisance

Choose one repeated task, a precise format, and a result worth checking.

Project motivation

Deck 5 | 50

Start with a narrow format you can explain. Expand it when a real requirement appears.

Study-session log

topic, minutes

​

Keep topic spelling.

Reject missing minutes.

Summarize accepted work.

Reading-log cleaner

title, pages

​

A title may contain commas.

Choose a grammar,

then choose a parser.

Your own utility

What is one line?

What may be normalized?

What must be preserved?

Which input should fail?

51 of 60

Can we answer today’s driving question?

Interpreting text requires a representation, a policy, and evidence.

Synthesis

Deck 5 | 51

Human responsibility today: preserve meaning while changing representation and behavior.

01

Treat text as an immutable sequence of code points.

02

Use positions and slices to extract a needed part.

03

Inspect and transform text according to an explicit policy.

04

Parse fields only after checking the record’s shape.

05

Distinguish text, encoded bytes, and persistent storage.

06

Ask AI for small changes; verify the old and new contracts.

52 of 60

Exit ticket: explain before pressing Run

Three-minute individual check. Answers are in the instructor notes.

Exit ticket · 3 minutes

Deck 5 | 52

You should be able to defend the transformations even when AI suggested the code.

01

s = "Campus"; t = s; s = "Station". What is t?

02

Why check find() for -1 before slicing at its result?

03

What does "Campus,,45".split(",") preserve?

04

How many code points and UTF-8 bytes are in A + U+4E2D?

05

Why compare an uppercase copy but keep the original label case?

53 of 60

Before next class: leave evidence of a faithful change

Complete the tests; do not submit an unreviewed AI rewrite.

After class

Deck 5 | 53

A limitation belongs in the specification, not hidden in an unexplained failure.

01

Complete the line parser and at least eight justified tests.

02

Retain old 30/60 boundaries, zero-distance, and rejected-final-record cases.

03

Record the input-policy changes and one counterexample you repaired.

04

Complete the encoding check; explain which files persist after exit.

05

Commit, push, verify online, and keep one idea for a personal utility.

54 of 60

Now it works. How do we keep it manageable?

Deck 6 · How do we organize a growing program into understandable components?

Next driving question

Deck 5 | 54

Next: functions, parameters, return values, interfaces, and AI-assisted integration.

Today’s single script

Read a line.

Parse the fields.

Validate the values.

Calculate and report.

Update and summarize.

Tomorrow’s design question

Can we name each job?

​

What data goes in?

What result comes out?

How do we test each part?

55 of 60

Optional: use a CSV parser when the grammar needs one

Quoted fields are a new requirement, not a secret feature of split(",").

Appendix · Quoted CSV

Deck 5 | 55

[P8]

A grammar change requires a new contract and tests for quotes, delimiters, and line breaks.

OPTIONAL · DIFFERENT FORMAT

import csv

line = '"Campus, East",12.5,45'

fields = next(csv.reader([line]))

print(fields)

# ['Campus, East', '12.5', '45']

The comma inside the quoted label is data, not a field boundary.

56 of 60

Optional: Unicode-aware comparison is a policy choice

Normalization and case folding solve specific comparison problems.

Appendix · Unicode comparison

Deck 5 | 56

[P7] [P10]

Keep a display value separate from a comparison key when the application needs both.

PYTHON

import unicodedata

a = "\u00e9"

b = "e\u0301"

print(a == b) # False

print(unicodedata.normalize("NFC", a) ==

unicodedata.normalize("NFC", b)) # True

57 of 60

Optional: read saved UTF-8 text with an explicit encoding

A new input adapter can supply lines to the same text-processing pipeline.

Appendix · File input

Deck 5 | 57

[P9]

Saving a sample in the editor persists it. The core console tool does not automatically do that.

PYTHON

with open("samples/mixed_session.txt",

"r", encoding="utf-8") as source:

for raw_line in source:

line = raw_line.strip()

if line.upper() == "DONE":

break

print(repr(line))

58 of 60

Reference: select the operation that answers the question

Do not memorize an API catalogue; connect each operation to its purpose.

Appendix · Compact text reference

Deck 5 | 58

[P1] [P2]

Remember the result type: Boolean, index, string, or list of strings.

Need

Operation / reminder

One position / a region

s[i] / s[start:stop:step]

Presence / prefix / suffix

part in s / s.startswith(p) / s.endswith(p)

First / last position

s.find(part) / s.rfind(part); missing → -1

Count occurrences

s.count(part); non-overlapping matches

Edge trim / case comparison

s.strip() / s.lower() / s.upper()

Replace / split / join

s.replace(a,b) / s.split(",") / ",".join(fields)

59 of 60

Technical references

Primary sources support the semantics; full links and scope notes are in the speaker notes.

Appendix · References

Deck 5 | 59

[P1] [P2] [P5] [P7] [P8] [H1] [H2] [H3]

Python documentation

[P1–P2] Text and string methods

[P3–P4] Objects and assignment

[P5–P6] Built-ins and exceptions

[P7, P10] Unicode and normalization

[P8–P9] CSV and file input

[P11–P12] Finite values and lists

Storage and workflow

[H1] Seagate: HDD mechanisms

[H2] IBM: solid-state drives

[H3] IBM: optical storage

​

[G1–G2] GitHub Desktop:

review → commit → push → verify

60 of 60

Course continuity and provenance

Earlier material, new classroom policies, and verified technical corrections are kept distinct.

Appendix · Sources and scope

Deck 5 | 60

[U1] [U2] [U3]

The core tool is a small line parser — not general CSV, natural-language understanding, or a database.

Retained and adapted

[U1] Deck 4: report and totals

[U2] Legacy String: topic sequence

[U3] Foundations map: text + storage

​

Corrected: immutability is not

“assignment always makes a copy.”

New in this deck

Versioned one-line contract

Explicit list / parsing bridges

Prepared bugs and independent tests

AI modification prompt templates

​

Functions remain for Deck 6.