Skip to content

← Errors step 4 of 4

Medium Primitives

Skip invalid fields without losing valid results

A handler should turn a failure into the behavior its caller expects. Returning a plausible-looking success value for every exception can hide what happened:

try {
    // Process several fields.
} catch (...) {
    return {0, 0};
}

This cannot distinguish a genuinely empty result from an interrupted operation. Here the intended recovery is narrower: skip one field that cannot be converted, count it, and continue processing the others.

Catch the failures this operation can handle

catch (...) matches C++ exceptions of any type. It does not generally turn undefined behavior, such as dereferencing a null pointer, into a catchable exception. A failed standard assert calls abort; it does not throw a C++ exception for a surrounding handler to catch.

Catch-all handlers can be useful at an application boundary or to translate errors into another API's failure representation. Their behavior needs an explicit contract. This function should catch the two expected conversion errors instead of reporting every possible exception as a skipped field.

Assertions document program assumptions and can be disabled by defining NDEBUG. They are not a replacement for validating external input. If continuing after a broken invariant is unsafe, the program needs an explicit failure policy; neither a catch-all nor an assertion guarantees a useful recovery or stack trace.

Your task

Implement:

std::vector<long long> tally(const std::vector<std::string>& fields);

Convert each field with std::stoll using its default base of 10. Add successful conversions to a long long total. On std::invalid_argument or std::out_of_range, skip that field and increment the skipped count. Continue with the next field. Return [total, skipped], in that order. Empty input returns [0, 0].

Put the conversion handler inside the loop so a rejected field does not abandon later fields. A handler outside a loop runs after that loop has been exited; it does not resume the failed iteration automatically.

Use stoll's prefix-parsing behavior

This task accepts a numeric prefix rather than requiring the entire string to be an integer. Leading whitespace and an optional sign are accepted. Parsing stops when the decimal digits end:

Field Outcome
"12abc" Add 12
" -4" Add -4
"+7" Add 7
"3.5" Add 3
"oops" or an empty string Skip: no conversion
"99999999999999999999999" Skip: outside long long's range in this runtime

Do not add a whole-string validation requirement. For ["10", "oops", "5"], return [15, 1]. For ["12abc", "", " -4", "+7"], return [15, 1]. All skipped fields produce [0, number_of_fields]. Valid zero is counted as a successful conversion, not as a skipped field.

Test inputs use ordinary decimal text and ASCII whitespace. Every running sum of successful conversions fits long long, and the number of fields fits int. A sum that overflows long long would be undefined behavior, not an out_of_range exception caught by these handlers. Do not wrap the sum or count as part of this exercise.

Catch the two parsing errors by const reference. Their common base, std::logic_error, also includes other errors, so explicit handlers better state the intended recovery. Let unrelated exceptions propagate. The starter catches around the whole loop and returns [0, 0] on its first error, discarding the accumulated total and skipping all remaining work.