Educational Blog

How to Convert String to Number in C

Practical C string-to-number parsing with validation, examples, and common pitfalls.

Converting a string to a number in C is one of those tasks that looks simple until you hit the details: whitespace, signs, invalid characters, overflow, and whether the string contains an integer or a floating-point value. C gives you several ways to do it, and the right choice depends on how strict you want parsing to be and how much error handling you need.

The short version is this:

  • Use strtol, strtoul, strtod, or related functions when you want real validation.
  • Use sscanf only for small, controlled inputs where convenience matters more than precision.
  • Avoid atoi and friends in new code because they do not report parsing errors cleanly.
  • If you need to understand exactly where conversion stopped, prefer the endptr pattern.

The main conversion options

C does not have a single universal string_to_number() function. Instead, the standard library gives you families of functions for different numeric types. The most useful ones live in <stdlib.h>.

Input typeRecommended functionNotes
Signed integerstrtolBest default for validated integer parsing
Unsigned integerstrtoulUse for non-negative values only
Long long integerstrtollUse when values may exceed long
Unsigned long long integerstrtoullFor large unsigned ranges
Floating-pointstrtodBest general-purpose float parser
Float/long doublestrtof, strtoldMore specific floating-point variants

If you only remember one idea, remember this: parse with a function that lets you check whether conversion succeeded.

Why atoi is usually a bad choice

atoi is easy to type, and that is exactly why it is tempting. But it has a major flaw: it cannot tell you whether the conversion failed.

For example, these all become ambiguous with atoi:

  • The string is actually "0"
  • The string is invalid, like "abc"
  • The number is out of range
  • The string starts with digits and then contains garbage, like "12xyz"

If you care about correctness, ambiguity is a problem. atoi gives you a number, but not enough information to know whether that number is trustworthy.

Use strtol or strtod instead. They give you enough context to validate the input properly.

Converting strings to integers with strtol

strtol is the most practical default for integer parsing.

Typical signature:

long strtol(const char *nptr, char **endptr, int base);

The third argument, base, controls how the parser interprets the number:

  • 10 for decimal
  • 16 for hexadecimal
  • 8 for octal
  • 0 to let the function detect prefixes like 0x

A common pattern looks like this:

#include <stdlib.h>
#include <errno.h>
#include <limits.h>

int main(void) {
    const char *text = "  42";
    char *end;
    errno = 0;

    long value = strtol(text, &end, 10);

    if (end == text) {
        printf("No digits were found
");
        return 1;
    }

    if (errno == ERANGE || value < LONG_MIN || value > LONG_MAX) {
        printf("Value out of range
");
        return 1;
    }

    while (*end == ' ' || *end == '	' || *end == '
') {
        end++;
    }

    if (*end != '�') {
        printf("Trailing characters found: %s
", end);
        return 1;
    }

    printf("Parsed value: %ld
", value);
    return 0;
}

That is more code than atoi, but it gives you a much better result. You know whether parsing succeeded, whether anything remained after the number, and whether range errors occurred.

Why the endptr matters

The endptr parameter is the main reason strtol is useful. It points to the first character that was not consumed during parsing.

This lets you distinguish between these cases:

  • "123" -> clean parse
  • "123abc" -> partial parse, trailing junk present
  • "abc" -> no digits at all

That is extremely helpful when you are reading user input, config files, CSV fields, or command-line arguments.

A simple validation pattern is:

  1. Call the conversion function.
  2. Check whether endptr == input.
  3. Check errno for range errors.
  4. Confirm the rest of the string contains only acceptable trailing whitespace or nothing at all.

Converting strings to floating-point numbers

For decimals like 3.14, use strtod.

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main(void) {
    const char *text = "3.14159";
    char *end;
    errno = 0;

    double value = strtod(text, &end);

    if (end == text) {
        printf("No numeric input
");
        return 1;
    }

    if (errno == ERANGE) {
        printf("Floating-point overflow or underflow
");
        return 1;
    }

    if (*end != '�') {
        printf("Trailing characters: %s
", end);
        return 1;
    }

    printf("Parsed double: %f
", value);
    return 0;
}

strtod is often the right answer for:

  • scientific notation like 1.2e6
  • decimals with fractional parts
  • precise validation of user-entered numeric values

If you need float or long double, there are specialized variants, but the validation pattern stays the same.

sscanf can work, but know the tradeoff

You can also parse numbers with sscanf.

int value;
if (sscanf(text, "%d", &value) == 1) {
    /* success */
}

This is easy to read in tiny examples, and sometimes it is good enough. But sscanf is usually not the best tool for strict conversion because:

  • It is less explicit about trailing characters
  • Error handling is less precise than strtol
  • It becomes awkward for robust validation logic

Use it when the input format is tightly controlled. For general-purpose parsing, strtol and strtod are better.

Choosing the right function

Here is a practical way to decide:

  • If the input should become an integer, start with strtol.
  • If the input might exceed long, use strtoll.
  • If the input is decimal, use strtod.
  • If you need unsigned values, use strtoul or strtoull.
  • If you only need a quick demo and the input is trusted, sscanf may be acceptable.

A good rule is to choose the most specific function that still gives you enough validation.

Common mistakes to avoid

When people first convert strings to numbers in C, they often make the same mistakes.

  • Ignoring trailing characters after a numeric prefix
  • Not checking for range errors
  • Assuming atoi can report failures
  • Forgetting to clear errno before a conversion
  • Parsing user input without validating the entire string
  • Using the wrong base for hex or octal input

A small amount of defensive code prevents subtle bugs later.

A reusable integer parser

If you want a clean pattern for production code, wrap strtol in a helper. This keeps validation consistent across your program.

#include <stdlib.h>
#include <errno.h>
#include <limits.h>

int parse_int(const char *text, int *out) {
    char *end;
    long value;

    if (text == NULL || out == NULL) {
        return 0;
    }

    errno = 0;
    value = strtol(text, &end, 10);

    if (end == text) {
        return 0;
    }

    while (*end == ' ' || *end == '	' || *end == '
') {
        end++;
    }

    if (*end != '�') {
        return 0;
    }

    if (errno == ERANGE || value < INT_MIN || value > INT_MAX) {
        return 0;
    }

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

This helper does a few important things:

  • Rejects null pointers
  • Requires at least one digit
  • Rejects trailing junk
  • Checks range before casting to int

That is the kind of utility that pays off quickly in real code.

When base detection helps

Sometimes you want to let users type values in different bases. In that case, strtol with base 0 can be useful.

Examples:

  • 123 is treated as decimal
  • 0x7B is treated as hexadecimal
  • 077 may be treated as octal

This can be convenient, but it can also surprise users. If your interface expects decimal input, specify 10 explicitly. That keeps behavior predictable.

Practical recommendations

If you are writing C code today, a safe default looks like this:

  1. Use strtol for integers.
  2. Use strtod for floating-point values.
  3. Always inspect endptr.
  4. Always handle errno for range errors.
  5. Reject strings with unexpected trailing characters.

That pattern is reliable, readable, and easy to maintain.

Final takeaway

The best way to convert a string to a number in C is not just to get a result, but to verify that the result is valid. strtol and strtod give you the control you need for real parsing, while atoi hides too much and sscanf is less precise for validation-heavy code.

If you remember the endptr and errno pattern, you can safely handle most numeric input problems in C without guesswork.

Written by

c-double.com Editorial Team

Editorial team

c-double.com publishes practical how-to guides and educational articles with clear steps and useful context.