#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// int alpha_range(char c) { return 0 != strchr("abcdefghijklmnopqrstuvwxyz", c); }
// int digit_range(char c) { return 0 != strchr("0123456789", c); }
int alpha_range( char c) { return ( c>= 'a' ) && ( c<= 'z' ) ; }
int digit_range( char c) { return ( c>= '0' ) && ( c<= '9' ) ; }
char * expand( const char * s)
{
char buf[ 2048 ] ;
const char * in = s;
char * out = buf;
// parser state
int ( * predicate) ( char ) = 0 ; // either: NULL (free state), alpha_range (in alphabetic range), digit_range (in digit range)
char lower= 0 , upper= 0 ; // tracks lower and upper bound of character ranges in the range parsing states
// init
* out = 0 ;
while ( * in)
{
if ( ! predicate)
{
// free parsing state
if ( alpha_range( * in) && ( in[ 1 ] == '-' ) && alpha_range( in[ 2 ] ) )
{
lower = upper = * in++;
predicate = & alpha_range;
}
else if ( digit_range( * in) && ( in[ 1 ] == '-' ) && digit_range( in[ 2 ] ) )
{
lower = upper = * in++;
predicate = & digit_range;
}
else * out++ = * in;
} else
{
// in a range
if ( * in < lower) lower = * in;
if ( * in > upper) upper = * in;
if ( in[ 1 ] == '-' && predicate( in[ 2 ] ) )
in++; // more coming
else
{
// end of range mode, dump expansion
char c;
for ( c= lower; c<= upper; * out++ = c++ ) ;
predicate = 0 ;
}
}
in++;
}
* out = 0 ; // null-terminate buf
return strdup( buf) ;
}
void dotest( const char * const input)
{
char * ex = expand( input) ;
printf ( "input : '%s'\n output: '%s'\n \n " , input
, ex
) ;
if ( ex)
}
int main ( int argc, char * argv[ ] )
{
dotest( "a-z or 0-9 or a-b-c or a-z0-9" ) ; // from the original post
dotest( "This is some e-z test in 5-7 steps; this works: a-b-c. This works too: b-k-c-e. Likewise 8-4-6" ) ; // from my C++ answer
dotest( "-x-s a-9 9- a-k-9 9-a-c-7-3" ) ; // assorted torture tests
return 0 ;
}
I2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHN0cmluZy5oPgoKLy8gaW50IGFscGhhX3JhbmdlKGNoYXIgYykgeyByZXR1cm4gMCAhPSBzdHJjaHIoImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6IiwgYyk7IH0KLy8gaW50IGRpZ2l0X3JhbmdlKGNoYXIgYykgeyByZXR1cm4gMCAhPSBzdHJjaHIoIjAxMjM0NTY3ODkiLCBjKTsgfQoKaW50IGFscGhhX3JhbmdlKGNoYXIgYykgeyByZXR1cm4gKGM+PSdhJykgJiYgKGM8PSd6Jyk7IH0KaW50IGRpZ2l0X3JhbmdlKGNoYXIgYykgeyByZXR1cm4gKGM+PScwJykgJiYgKGM8PSc5Jyk7IH0KCmNoYXIqIGV4cGFuZChjb25zdCBjaGFyKiBzKQp7CiAgICBjaGFyIGJ1ZlsyMDQ4XTsKCiAgICBjb25zdCBjaGFyKiBpbiAgPSBzOwogICAgICAgICAgY2hhciogb3V0ID0gYnVmOwoKICAgIC8vIHBhcnNlciBzdGF0ZQogICAgaW50ICgqcHJlZGljYXRlKShjaGFyKSA9IDA7IC8vIGVpdGhlcjogTlVMTCAoZnJlZSBzdGF0ZSksIGFscGhhX3JhbmdlIChpbiBhbHBoYWJldGljIHJhbmdlKSwgZGlnaXRfcmFuZ2UgKGluIGRpZ2l0IHJhbmdlKQogICAgY2hhciBsb3dlcj0wLHVwcGVyPTA7ICAgICAgIC8vIHRyYWNrcyBsb3dlciBhbmQgdXBwZXIgYm91bmQgb2YgY2hhcmFjdGVyIHJhbmdlcyBpbiB0aGUgcmFuZ2UgcGFyc2luZyBzdGF0ZXMKCiAgICAvLyBpbml0CiAgICAqb3V0ID0gMDsKCiAgICB3aGlsZSAoKmluKQogICAgewogICAgICAgIGlmICghcHJlZGljYXRlKQogICAgICAgIHsKICAgICAgICAgICAgLy8gZnJlZSBwYXJzaW5nIHN0YXRlCiAgICAgICAgICAgIGlmIChhbHBoYV9yYW5nZSgqaW4pICYmIChpblsxXSA9PSAnLScpICYmIGFscGhhX3JhbmdlKGluWzJdKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgbG93ZXIgPSB1cHBlciA9ICppbisrOwogICAgICAgICAgICAgICAgcHJlZGljYXRlID0gJmFscGhhX3JhbmdlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgaWYgKGRpZ2l0X3JhbmdlKCppbikgJiYgKGluWzFdID09ICctJykgJiYgZGlnaXRfcmFuZ2UoaW5bMl0pKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBsb3dlciA9IHVwcGVyID0gKmluKys7CiAgICAgICAgICAgICAgICBwcmVkaWNhdGUgPSAmZGlnaXRfcmFuZ2U7CiAgICAgICAgICAgIH0gCiAgICAgICAgICAgIGVsc2UgKm91dCsrID0gKmluOwogICAgICAgIH0gZWxzZQogICAgICAgIHsgCiAgICAgICAgICAgIC8vIGluIGEgcmFuZ2UKICAgICAgICAgICAgaWYgKCppbiA8IGxvd2VyKSBsb3dlciA9ICppbjsKICAgICAgICAgICAgaWYgKCppbiA+IHVwcGVyKSB1cHBlciA9ICppbjsKCiAgICAgICAgICAgIGlmIChpblsxXSA9PSAnLScgJiYgcHJlZGljYXRlKGluWzJdKSkgCiAgICAgICAgICAgICAgICBpbisrOyAvLyBtb3JlIGNvbWluZwogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIGVuZCBvZiByYW5nZSBtb2RlLCBkdW1wIGV4cGFuc2lvbgogICAgICAgICAgICAgICAgY2hhciBjOwogICAgICAgICAgICAgICAgZm9yIChjPWxvd2VyOyBjPD11cHBlcjsgKm91dCsrID0gYysrKTsKICAgICAgICAgICAgICAgIHByZWRpY2F0ZSA9IDA7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaW4rKzsKICAgIH0KCiAgICAqb3V0ID0gMDsgLy8gbnVsbC10ZXJtaW5hdGUgYnVmCiAgICByZXR1cm4gc3RyZHVwKGJ1Zik7Cn0KCnZvaWQgZG90ZXN0KGNvbnN0IGNoYXIqIGNvbnN0IGlucHV0KQp7CiAgICBjaGFyKiBleCA9IGV4cGFuZChpbnB1dCk7CiAgICBwcmludGYoImlucHV0IDogJyVzJ1xub3V0cHV0OiAnJXMnXG5cbiIsIGlucHV0LCBleCk7CgogICAgaWYgKGV4KQogICAgICAgIGZyZWUoZXgpOwp9CgppbnQgbWFpbiAoaW50IGFyZ2MsIGNoYXIgKmFyZ3ZbXSkKewogICAgZG90ZXN0KCJhLXogb3IgMC05IG9yIGEtYi1jIG9yIGEtejAtOSIpOyAvLyBmcm9tIHRoZSBvcmlnaW5hbCBwb3N0CiAgICBkb3Rlc3QoIlRoaXMgaXMgc29tZSBlLXogdGVzdCBpbiA1LTcgc3RlcHM7IHRoaXMgd29ya3M6IGEtYi1jLiBUaGlzIHdvcmtzIHRvbzogYi1rLWMtZS4gTGlrZXdpc2UgOC00LTYiKTsgLy8gZnJvbSBteSBDKysgYW5zd2VyCiAgICBkb3Rlc3QoIi14LXMgYS05IDktIGEtay05IDktYS1jLTctMyIpOyAvLyBhc3NvcnRlZCB0b3J0dXJlIHRlc3RzCgogICAgcmV0dXJuIDA7Cn0K