How to read a line character by character?

Hello,
I have a file as follows:

1 2 3 4 5 6 7 8 9 10

I want to calculate the sum of the above numbers. With a command like below I read a whole line and not individual numbers:

inn = open("input.txt", "r")
inp = readline(inn)

How can I separate numbers on a line?

Thank you.

  • If you want to read the file Character by character, you can use c = read(inn, Char).
  • If you want to read the line, but split it into characters afterwards, you could just index the inp in your code (inp[2]), loop over it (for c in inp), or collect it.
  • If you want to get a Vector{Int} (which is presumably what you’re after), use parse.(Int, split(inp)) (with default ' ' for the second argument dlm (delimiter) of split).
3 Likes

I would probably use sum on eachmatch directly so I don’t have to allocate a vector of strings with split or a vector of ints (eachline is also not the most performant because it allocates a string per line I think, but it depends on what you need whether more effort is worth it)

input.txt

1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10 11
1 2 3 4 5 6 7 8 9 10 11 12
1 2 3 4 5 6 7 8 9 10 11 12 13
julia> map(eachline("input.txt")) do line
           sum(match -> parse(Int, match.match), eachmatch(r"\d+", line))
       end
4-element Vector{Int64}:
 55
 66
 78
 91
2 Likes

Using eachsplit() seems to be more performant in this case:

map(eachline("input.txt")) do line
    sum(x -> parse(Int, x), eachsplit(line))
end
4 Likes

Ah right that one was added in 1.8! Nice

here a related question

In case the series of values ​​includes multi-digit elements

function sumchars(data)
    tot = 0
    lcv=0
    for e in data 
        if (e == ' ') 
            tot=tot+lcv
            lcv=0
        else
            lcv = lcv*10+codepoint(e)-0x30
        end
        
    end
    return tot+lcv
end

2 Likes

Only for the parsing part the line of numbers


julia> s4
"1 2 3 4 5 6 7 8 9 10 11 12 13"

julia> @btime sum(x -> parse(Int, x), eachsplit(s4))
  739.683 ns (3 allocations: 96 bytes)
91

julia> @btime sumchars(s4)
  38.143 ns (0 allocations: 0 bytes)
91

Simple and fast, if no negative integer or integer power such as 2^8 is provided.

ok for the first point. But why should powers of 2 cause problems?

I meant that the string “2^8”, or “2*10^9”, is a valid input integer that would not be parsed.
Edit: my bad, parse(Int, "2^8") errors too :frowning:

1 Like

Hi,
Thank you so much.
Which part of this code is wrong?

function summer()
    inn = open("input.txt","r")
    c = 0 
    sum = 0
    while !eof(inn)
        c = parse(Int, read(inn, Char))
        sum += c
    end
    println(sum)
end
summer()

Since you read character by character, you would read a line just containing 10
as "1" and "0" so your sum would be 1 not 10.

You have to follow the hints atop, real the whole line, split it at the spaces and then parse the individual numbers, which are often strings longer than one character.

2 Likes

Apart from the problem of summing digits vs. summing numbers @kellertuer highlights, there’s also the issue that you are trying to convert a space to an integer.

ERROR: ArgumentError: invalid digit: ' '

If you really want to obtain the sum while reading the file character by character, you can use an approach similar to @rocco_sprmnt21 's sumchars, though you might want to change codepoint(e) - 0x30 into parse(Int, e) for clarity.

1 Like

or

UInt8(e)-0x30

Well, my point was mainly that for educational purposes it’s best to not use a ‘magic’ hexadecimal number :slight_smile: . (Int(e) - Int('0') would be clearer, but also that still requires a little bit of knowledge on character encoding.)

1 Like