Lexical Casting

Learning Objective
In this tutorial, you will learn about the lexical casting functionality in SeqAn. Lexical casting allows you to convert numbers stored as strings to their numeric values.
Difficulty
Basic
Duration
15 min
Prerequisites
A First Example, Sequences

Lexical Casting

When reading data from text files all data is usually first stored as strings. For example, a genomic location is often described as a pair of the chromosome name and the position on the chromosome, e.g. "chr1" and "1000". To really make use of the the "1000" we have to cast it to an integer.

For this purpose, SeqAn provides the lexicalCast and lexicalCast2 functions. These functions do not cast a value into a related type but convert a CharString into its numeric value.

The function is located in the stream module so we have to include <seqan/stream.h>.

#include <seqan/stream.h>

The function lexicalCast converts a string into the type given in the template argument and returns the value after conversion. In case of errors, the result is undefined. This is mainly useful if you know that the value can be converted (e.g. you accepted a sequence of 1-4 digits and want to cast it to int).

seqan::CharString valueAsStr = "1000";
int valueAsInt = lexicalCast<int>(valueAsStr);
// => valueAsInt == 1000

The function lexicalCast2 has two parameters. A reference to the numeric destination and the string source. The result is a bool and true indicates success.

seqan::CharString valueAsStr = "1000";
bool success = lexicalCast2<int>(valueAsInt, valueAsStr);
// => success == true
// => valueAsInt == 1000

Note

Strictness of Lexical Casting

A string such as "123XX" will be successfully cast into the int 123. The string -123 can be converted into an int using lexicalCast but it might not be converted correctly into an unsigned value.

Lexical casting in SeqAn uses the standard <sstring> library. The exact implementation of casting is library-dependent.

A Full Example

The following example program demonstrates the usage of both interfaces.

#include <iostream>

#include <seqan/stream.h>

int main(int, char const **)
{
    using namespace seqan;

    int resultI = 0;
    double resultD = 0;
    bool b = false;

    resultI = lexicalCast<int>("123");
    std::cerr << "lexicalCast<int>(\"123\")   --> " << resultI << std::endl;

    resultI = lexicalCast<int>("123XX");
    std::cerr << "lexicalCast<int>(\"123XX\") --> " << resultI << std::endl;

    b = lexicalCast2<int>(resultI, "-123");
    std::cerr << "lexicalCast2<int>(\"-123\") --> (" << b << ", " << resultI << ")" << std::endl;
    
    b = lexicalCast2<double>(resultD, "-123");
    std::cerr << "lexicalCast2<double>(\"-123\") --> (" << b << ", " << resultD << ")" << std::endl;
    
    return 0;
}

This is the program’s output.

lexicalCast<int>("123")   --> 123
lexicalCast<int>("123XX") --> 123
lexicalCast2<int>("-123") --> (1, -123)
lexicalCast2<double>("-123") --> (1, -123)

Assignment 1

Using Lexical Casting

Type
Application
Objective
Based on the example above, create a small program that takes one argument. This argument is then converted into an int, unsigned, and double. The program should display the results of lexicalCast and lexicalCast2 as in the example above.
Hints

The following shows an example session:

# tutorial_lexical_casting_solution1 10.3
lexicalCast<int>(10.3) ==      10
lexicalCast<unsinged>(10.3) == 10
lexicalCast<double>(10.3) ==   10
lexicalCast2<int>(10.3) ==      (1, 10)
lexicalCast2<unsigned>(10.3) == (1, 10)
lexicalCast2<double>(10.3) ==   (1, 10.3)
# tutorial_lexical_casting_solution1 10
lexicalCast<int>(10) ==      10
lexicalCast<unsinged>(10) == 10
lexicalCast<double>(10) ==   10
lexicalCast2<int>(10) ==      (1, 10)
lexicalCast2<unsigned>(10) == (1, 10)
lexicalCast2<double>(10) ==   (1, 10)
# tutorial_lexical_casting_solution1 TEXT
lexicalCast<int>(TEXT) ==      0
lexicalCast<unsinged>(TEXT) == 0
lexicalCast<double>(TEXT) ==   0
lexicalCast2<int>(TEXT) ==      (0, 0)
lexicalCast2<unsigned>(TEXT) == (0, 0)
lexicalCast2<double>(TEXT) ==   (0, 0)
Solution
#include <iostream>
#include <seqan/stream.h>

int main(int argc, char const ** argv)
{
    if (argc != 2)
    {
        std::cerr << "USAGE: tutorial_solution1 VALUE\n";
        return 1;
    }

    // Lexical casting with lexicalCast().
    {
        int      i = 0;
        unsigned u = 0;
        double   d = 0;
        
        i = seqan::lexicalCast<int>(argv[1]);
        u = seqan::lexicalCast<int>(argv[1]);
        d = seqan::lexicalCast<int>(argv[1]);
        std::cout << "lexicalCast<int>(" << argv[1] << ") ==      " << i << '\n';
        std::cout << "lexicalCast<unsinged>(" << argv[1] << ") == " << u << '\n';
        std::cout << "lexicalCast<double>(" << argv[1] << ") ==   " << d << '\n';
    }
    
    // Lexical casting with lexicalCast2().
    {
        int      i = 0;
        unsigned u = 0;
        double   d = 0;
        
        bool bi = seqan::lexicalCast2(i, argv[1]);
        bool bu = seqan::lexicalCast2(u, argv[1]);
        bool bd = seqan::lexicalCast2(d, argv[1]);

        std::cout << "lexicalCast2<int>(" << argv[1] << ") ==      (" << bi << ", " << i << ")\n";
        std::cout << "lexicalCast2<unsigned>(" << argv[1] << ") == (" << bu << ", " << u << ")\n";
        std::cout << "lexicalCast2<double>(" << argv[1] << ") ==   (" << bd << ", " << d << ")\n";
    }
    
    return 0;
}
comments powered by Disqus