Parsing code should return an explicit status instead of assuming text is valid.

parse status `strtol` can report where parsing stopped so the program can reject partial input.
range limit A valid number can still be outside the range accepted by the program.

Parse Integer Status

inputCase
parse_int_status.c
Replay: real traced execution (multi-file project)
#include <stdio.h>
#include <stdlib.h>

int parseInt(const char *text, int *outValue) {
    char *end = 0;
    long value = strtol(text, &end, 10);

    if (end == text || *end != '\0') {
        return 0;
    }
    if (value < -100 || value > 100) {
        return 0;
    }

    *outValue = (int)value;
    return 1;
}

int main(void) {
    int inputCase = 0;
    const char *text = "42";
    if (inputCase == 1) {
        text = "17x";
    } else if (inputCase == 2) {
        text = "150";
    }

    int value = 0;
    int ok = parseInt(text, &value);

    printf("inputCase=%d ok=%d value=%d\n", inputCase, ok, value);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>

int parseInt(const char *text, int *outValue) {
    char *end = 0;
    long value = strtol(text, &end, 10);

    if (end == text || *end != '\0') {
        return 0;
    }
    if (value < -100 || value > 100) {
        return 0;
    }

    *outValue = (int)value;
    return 1;
}

int main(void) {
    int inputCase = 1;
    const char *text = "42";
    if (inputCase == 1) {
        text = "17x";
    } else if (inputCase == 2) {
        text = "150";
    }

    int value = 0;
    int ok = parseInt(text, &value);

    printf("inputCase=%d ok=%d value=%d\n", inputCase, ok, value);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>

int parseInt(const char *text, int *outValue) {
    char *end = 0;
    long value = strtol(text, &end, 10);

    if (end == text || *end != '\0') {
        return 0;
    }
    if (value < -100 || value > 100) {
        return 0;
    }

    *outValue = (int)value;
    return 1;
}

int main(void) {
    int inputCase = 2;
    const char *text = "42";
    if (inputCase == 1) {
        text = "17x";
    } else if (inputCase == 2) {
        text = "150";
    }

    int value = 0;
    int ok = parseInt(text, &value);

    printf("inputCase=%d ok=%d value=%d\n", inputCase, ok, value);
    return 0;
}
  1. inputCase ← 0, text ← 42, value ← 0

    19int main(void) {20    int inputCase→ 0 = 0; //@inputCase=1, 221    const char *text→ 42 = "42";22    if (inputCase == 1) {23        text = "17x";24    } else if (inputCase == 2) {25        text = "150";26    }2728    int value→ 0 = 0;29    int ok = parseInt(text42, &value0);
  2. end ← (empty), value ← 42

    4int parseInt(const char *text42, int *outValue⟨addr A⟩) {5    char *end→ (empty) = 0;6    long value→ 42 = strtol(text42, &end(empty), 10);78    if (end == text || *end != '\0') {9        return 0;10    }11    if (value < -100 || value > 100) {12        return 0;13    }1415    *outValue⟨addr A⟩ = (int)value42;16    return 1;17}
  3. value ← 42, ok ← 1

    28    int value = 0;29    int ok→ 1 = parseInt(text42, &value→ 42);3031    printf("inputCase=%d ok=%d value=%d\n", inputCase0, ok1, value42);32    return 0;33}
    outputinputCase=0 ok=1 value=42
  1. inputCase ← 1, text ← 42

    19int main(void) {20    int inputCase→ 1 = 1;21    const char *text→ 42 = "42";22    if (inputCase == 1) {
  2. text ← 17x

    21const char *text = "42";22if (inputCase1 == 1) {23    text→ 17x = "17x";24} else if (inputCase == 2) {
  3. value ← 0

    28int value→ 0 = 0;29int ok = parseInt(text17x, &value0);
  4. end ← (empty), value ← 17

    4int parseInt(const char *text17x, int *outValue⟨addr A⟩) {5    char *end→ (empty) = 0;6    long value→ 17 = strtol(text17x, &end→ x, 10);
  5. if (end == text || *end != '\0')

    8if (endx == text17x || *end != '\0') {9    return 0;10}
  6. ok ← 0

    28    int value = 0;29    int ok→ 0 = parseInt(text17x, &value0);3031    printf("inputCase=%d ok=%d value=%d\n", inputCase1, ok0, value0);32    return 0;33}
    outputinputCase=1 ok=0 value=0
  1. inputCase ← 2, text ← 42

    19int main(void) {20    int inputCase→ 2 = 2;21    const char *text→ 42 = "42";22    if (inputCase == 1) {
  2. text ← 150

    23    text = "17x";24} else if (inputCase2 == 2) {25    text→ 150 = "150";26}
  3. value ← 0

    28int value→ 0 = 0;29int ok = parseInt(text150, &value0);
  4. end ← (empty), value ← 150

    4int parseInt(const char *text150, int *outValue⟨addr A⟩) {5    char *end→ (empty) = 0;6    long value→ 150 = strtol(text150, &end(empty), 10);
  5. if (value < -100 || value > 100)

    10}11if (value150 < -100 || value > 100) {12    return 0;13}
  6. ok ← 0

    28    int value = 0;29    int ok→ 0 = parseInt(text150, &value0);3031    printf("inputCase=%d ok=%d value=%d\n", inputCase2, ok0, value0);32    return 0;33}
    outputinputCase=2 ok=0 value=0

Exercise: parse_int_status.c

Reject empty, partial, and out-of-range integer input with distinct status codes