FLW_FTW

Challenge: Tag!

10 posts in this topic

So in a little project I'm working on, I found the need to be able to handle tags in a user inputed string. What I needed to do was parse a string for tags and translate them into ANSI escape sequences to emit the correct colors.

Ansi Escape Codes


Black: ESC [30m -->Sets foreground color to black
Red: ESC [31m -->Sets foreground color to red
Green: ESC [32m -->Sets foreground color to green
Orange: ESC [33m -->Sets foreground color to orange
Blue: ESC [34m -->Sets foreground color to blue
Purple: ESC [35m -->Sets foreground color to purple
Cyan: ESC [36m -->Sets foreground color to cyan
White: ESC [37m -->Sets foreground color to white

With tags of: "&x", "&r", "&g", "&o", "&b", "&p", "&c", and "&w", respectively.

Therefore, if a user typed in "&gHello!" the program would output "\033[0m\033[32mHello!". (\033 is escape, \033[0m is clear any previous color codes). Which would print "Hello!" in green.

My answer was this:


char *parse_color_codes( char *msg )
{
char result[MAX_BUFFER*2];
char *start;
char *orig;

start = result;
orig = msg;

for( ; *orig; orig++ )
{
if( *orig != '&' )
{
*start = *orig;
start++;
}
else
{
orig++;
switch( *orig )
{
case 'x':
start += sprintf( start, "\033[0m\033[30m" );
break;
case 'r':
start += sprintf( start, "\033[0m\033[31m" );
break;
case 'g':
start += sprintf( start, "\033[0m\033[32m" );
break;
case 'o':
start += sprintf( start, "\033[0m\033[33m" );
break;
case 'b':
start += sprintf( start, "\033[0m\033[34m" );
break;
case 'p':
start += sprintf( start, "\033[0m\033[35m" );
break;
case 'c':
start += sprintf( start, "\033[0m\033[36m" );
break;
case 'w':
start += sprintf( start, "\033[0m\033[37m" );
break;
default:
start += sprintf( start, "&%c", *orig );
break;
}
}
}
*start = '\0';
strcat( start, "\033[0m" );
return result;
}

What is your answer?

Edited by FLW_FTW
0

Share this post


Link to post
Share on other sites

Neat.

Here's my sloppy crack at it...


#include<stdio.h>
char colors[] = "xrgobpcw";
char x,y;
int loop;


int main (void)
{
while ((x = getchar()) != EOF)
{
if (x == '&')

{
y = getchar();
for (loop = 0; loop < sizeof(colors);loop++)
if (y == colors[loop])
{
printf("\\033[0m\\033[3%cm",(char)(loop+'0'));
break;
}
if (loop == sizeof(colors))
printf("%c%c",x,y);
continue;
}

printf("%c",x);
}

return 0;
}

EDIT:oops.

That first one is too litteral...

Here's one that actually changes the colors..

#include<stdio.h>
char colors[] = "xrgobpcw";
char x,y;
int loop;


int main (void)
{
while ((x = getchar()) != EOF)
{
if (x == '&')

{
y = getchar();
for (loop = 0; loop < sizeof(colors);loop++)
if (y == colors[loop])
{
printf("\033[0m\033[3%cm",(char)(loop+'0'));
break;
}
if (loop == sizeof(colors))
printf("%c%c",x,y);
continue;
}

printf("%c",x);
}

return 0;
}

Edited by PurpleJesus
1

Share this post


Link to post
Share on other sites

It was bothering me that I failed to actually return a string..

so here it is.. with my loopy style as usual...

/*
/*
colors4.c
FTW FTW programming challenge
Parse a color code into a string;
This one actually does do that. Makes a string.
PurpleJesus July 2nd, 2010
*/

#include <stdio.h>

char* parse (char* in, char* out)
{
char colors[] = "xrgobpcw";
int loop;
char* top = out;
while (*in != '\0')
{
*out = *in;

if (*in == '&')
{
for (loop = 0; loop < sizeof (colors); loop++)
if (*(in+1) == colors[loop])
{
out+= (sprintf(out,"\033[0m\033[3%cm",(char)(loop+'0')) -1);
in++;
break;
}
}
in++;
out++;

}
*out = '\0'; //just to be safe
return top;
}
int main (void)
{
char in[100] ="This is a &test &bblue&rred\0";
char out [1000]; //I'm paranoid.

parse (in,out);
printf("origional:\n%s\n\nparsed:\n%s\n",in,out);
printf("returned: %s\n",parse(in,out));
return 0;
}

edited to actually return a string too.. Couldn't make the compiler not throw warnings if I defined a temp buffer within the function though, so you still have to supply your source and working buffers.

Edited by PurpleJesus
0

Share this post


Link to post
Share on other sites

double post

Edited by PurpleJesus
0

Share this post


Link to post
Share on other sites

Here is my attempt, it works but I can tell that it is both sloppy and less than efficient. I am however so tired I can barely keep my eyes open let alone think properly (I've misspelled almost every word here, and if not for spell check it would look like I was drunk. That kind of bad tired =/)

I might revise later, until that time it at least works, and comments and criticisms are requested, but be kind =P

#!/usr/bin/env ruby
# TagColor by n3xg3n
# 7/3/2010

class TagColor
ESC = "\033"
CLR = ESC + '[0m'

def self.tagHash
tagHash = Hash.new
tagHash["x"] = CLR + ESC + '[30m'
tagHash["r"] = CLR + ESC + '[31m'
tagHash["g"] = CLR + ESC + '[32m'
tagHash["o"] = CLR + ESC + '[33m'
tagHash["b"] = CLR + ESC + '[34m'
tagHash["p"] = CLR + ESC + '[35m'
tagHash["c"] = CLR + ESC + '[36m'
tagHash["w"] = CLR + ESC + '[37m'

return tagHash
end

def self.translate( str )
string = str.clone

TagColor.tagHash.each do |key, value|
string.gsub!("{key}", value)
end

return string
end
end

puts TagColor.translate(ARGV.join(" "))

Edited by n3xg3n
0

Share this post


Link to post
Share on other sites

Looks awesome, both of you.

n3xg3n, I don't know Ruby, so I can't really comment; PurpleJesus, very clean way of doing it, seems much simpler than my version.

Thanks for the input, both of you!

0

Share this post


Link to post
Share on other sites

Thank you FLW_FTW.

n3xg3n,

The part,

TagColor.tagHash.each do |key, value|
string.gsub!("{key}", value)

I'm guessing that's what scans the string looking for the '&' symbol.. care to elaborate on how that works? It seems to read backwards to my eye.. I did get it to run though. Nice.

Edited by PurpleJesus
0

Share this post


Link to post
Share on other sites

n3xg3n,

The part,

TagColor.tagHash.each do |key, value|
string.gsub!("{key}", value)

I'm guessing that's what scans the string looking for the '&' symbol.. care to elaborate on how that works? It seems to read backwards to my eye.. I did get it to run though. Nice.

We have a key-value hash (defined in TagColor.tagHash) which maps a string (the color letter) to a string (the control sequence).

I call the 'each' method for this hash, which accepts a block, so that block is run for each key-value pair, and each time through the value of the variables "key" and "value" represent a key-value pair from the hash.

In ruby, to use a variable in a string, you use #{variableName}, so the if the variable 'key' equals 'x', the string "{key}" is interpreted as "&x".

For each key-value pair in the hash, we call the gsub! (global substitute, and in ruby the "!" implies that the method is 'destructive' in that it edits the object in place) method on the string, which will search for "{key}" and replace it with the value variable.

Once this is all done, what happens is that we have a k-v hash, and for each key in that hash, the string is globally searched for `'&' + key` and replaces it with value.

Hope that explains it pretty well. ( 1337th overall post, w00t! =] )

0

Share this post


Link to post
Share on other sites

n3xg3n,

The part,

TagColor.tagHash.each do |key, value|
string.gsub!("{key}", value)

I'm guessing that's what scans the string looking for the '&' symbol.. care to elaborate on how that works? It seems to read backwards to my eye.. I did get it to run though. Nice.

We have a key-value hash (defined in TagColor.tagHash) which maps a string (the color letter) to a string (the control sequence).

I call the 'each' method for this hash, which accepts a block, so that block is run for each key-value pair, and each time through the value of the variables "key" and "value" represent a key-value pair from the hash.

In ruby, to use a variable in a string, you use #{variableName}, so the if the variable 'key' equals 'x', the string "{key}" is interpreted as "&x".

For each key-value pair in the hash, we call the gsub! (global substitute, and in ruby the "!" implies that the method is 'destructive' in that it edits the object in place) method on the string, which will search for "{key}" and replace it with the value variable.

Once this is all done, what happens is that we have a k-v hash, and for each key in that hash, the string is globally searched for `'&' + key` and replaces it with value.

Hope that explains it pretty well. ( 1337th overall post, w00t! =] )

That explains it pretty well.. Now I just have to read a book on Ruby so I know what to ask ;) I bet it's pretty simple after you play with it for a while though..

thanks.

0

Share this post


Link to post
Share on other sites

Perl with a regular expression.


#!/usr/bin/perl
chomp($input = <STDIN>);
$input =~ s/\&r/\[31m/g;
$input =~ s/\&g/\[32m/g;
$input =~ s/\&o/\[33m/g;
$input =~ s/\&b/\[34m/g;
$input =~ s/\&p/\[35m/g;
$input =~ s/\&c/\[36m/g;
$input =~ s/\&w/\[37m/g;
print $input;

Edited by heisenbug
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now