Here’s the program:

rna_transcription.c

#include "rna_transcription.h"
#include <malloc.h>
#include <string.h>

static const char lookup[] = {
    ['A'] = 'U',
    ['C'] = 'G',
    ['G'] = 'C',
    ['T'] = 'A'
};

char *to_rna(const char *dna)
{
    if (!dna)
        return NULL;

    char *rna = calloc(strlen(dna) + 1, 1), *start_rna = rna;
    if (rna)
    {
        for (; *dna; dna++, rna++)
        {
            if (!(*rna = lookup[(int)*dna]))
            {
                free(rna);
                return NULL;
            }
        }
    }
    return start_rna;
}

rna_transcription.h

#ifndef RNA_TRANSCRIPTION_H
#define RNA_TRANSCRIPTION_H

char *to_rna(const char *dna);

#endif

I can’t help but wonder how much of a waste of space the array would be. Surely, using a map is better, right?