🔒 Locked
A Small Programming Challenge
Advertisement
Original Post
by pre-existing function do you mean like strtok or even atoi ?? if you can use atoi then its pretty easy cause atoi will convert to an integer up to the first non-numeric so just atoi increase your pointer by 2 and atoi again rinse and repeat :)
Depends on how you define elegant.
Do we want to handle non-base-10? Non-latin?
Do we want to handle signed numbers?
Do we want to handle N != 4 for number of numbers?
What kind of error checking should we perform?
The "hard code everything, checks be damned" approach:
Language is C++.
Do we want to handle non-base-10? Non-latin?
Do we want to handle signed numbers?
Do we want to handle N != 4 for number of numbers?
What kind of error checking should we perform?
The "hard code everything, checks be damned" approach:
int n_array[4] = {0,0,0,0}, *n = n_array;const char *string = "0,0,0,0", *c = string;for ( const char *c = string ; *c != '\0' ; ++c ) { assert( n != end(n_array) ); /* for the unenlightened: end(n_array) returns (n_array+4) here -- one past * the last element in the array -- I refuse to do without this function in * my example ;-) */ if( '0' <= *c && *c <= '9' ) *n = (*n * 10) + (*c - '0'); else if ( *c == ',' ) ++n; else if ( *c == ' ' ); //do nothing else assert(!"reached"); //to be noted in function preconditions: string must be valid.}Language is C++.
This is a solution i just came up with, has limitations but serves the purpose:
Dave
GUIVector4 GUIXmlLoader::StringToGUIVector4( const String& dims ) { GUIVector4 temp; UnsignedInt count = 0; UnsignedInt i, j; i = j = 0; for ( UnsignedInt i = 0; i < dims.length(); ++i ) { for ( j = i; j < dims.length(); ++j ) { if ( dims[j] == ',' ) break; } temp[count] = ATOF( dims.substr( i, j ).c_str() ); ++count; i = j; } return temp; }Dave
Quote:
Original post by Dave
What is the most elegant solution that you can come up with for tokenising the following string without using any pre-existing function:
"0,0,0,0"
into four integers.
I have done this many a time and can never remember how i did it. How do you do it?
Dave
int tokens[] = { 0, 0, 0, 0 };I've applied some constant folding.
It all depends on your definition of pre-existing function. I generally consider standard library definitions to be language constructs, and not pre-existing functions. All of this runs without checks, which should obviously be added to the mix.
The most elegant in my opinion would be:
PHP
A less beautiful version would be:
C++
And, while we're at it, some fun with generated lexers:
OCaml
The most elegant in my opinion would be:
PHP
list($i1,$i2,$i3,$i4) = explode(",",$str);A less beautiful version would be:
C++
std::stringstream conversion;int i1, i2, i3, i4;char comma;conversion << str;conversion >> i1 >> comma >> i2 >> comma >> i3 >> comma >> i4;And, while we're at it, some fun with generated lexers:
OCaml
let (i1,i2,i3,i4) = begin parser | [< 'Int i1; 'Key ","; 'Int i2; 'Key ","; 'Int i3; 'Key ","; 'Int i4 >] -> (i1,i2,i3,i4) | _ -> failwith "Syntax error" end ( (Genlex.make_lexer [","]) (Stream.of_string str) );;
// Tokenize the integer list `string` into the array `list`.// Returns the number of tokens in the string, but only elements// `list[0 .. max-1]` are filled in, even if there are more// tokens. If `list` is null, no tokens are stored.int parse_int_list (const char *string, int *list, int max){ int c, count = 0; if (list) for (int i = 0; i < max; ++i) list = 0; while (c = *string++) if (c >= '0' && c <= '9' && count < max && list) list[count] = list[count] * 10 + (c - '0'); else if (c == ',') ++count; return ++count;}Quote:
Original post by Dave
without using any pre-existing function
Quote:
Original post by Dave
This is a solution i just came up with, has limitations but serves the purpose:GUIVector4 GUIXmlLoader::StringToGUIVector4( const String& dims ) { GUIVector4 temp; UnsignedInt count = 0; UnsignedInt i, j; i = j = 0; for ( UnsignedInt i = 0; i < dims.length(); ++i ) { for ( j = i; j < dims.length(); ++j ) { if ( dims[j] == ',' ) break; } temp[count] = ATOF( dims.substr( i, j ).c_str() ); ++count; i = j; } return temp; }
Dave
Isn't that using a whole bunch of preexisting functions?
This code is plain garden-variety C++, and could be translated to strict C by replacing //...\n comments with /*...*/ comments, and moving all variable declarations to the beginning of the code.
Fully commented version:
More compact version (same code but less lines - harder to understand)
And if you really want to obfuscate your code:
Fully commented version:
//This is our input dataconst char in_str[]="0,0,0,0";//Do a strlen without calling any library functionsint len=0;while(in_str[len]!='\0') len++;//Now tokenize the stringint output[4]; //Must output four integersint pos=0;for(int i=0;i<len;i++){ //Skip commas if(in_str==',') continue; //Read in the integer //Note that this doesn't handle 2-digit numbers like "27", //but that could be done with a bit more code. output[pos++]=in_str - '0';}More compact version (same code but less lines - harder to understand)
const char in_str[]="0,0,0,0";int len=0;while(in_str[len]!='\0') len++;int output[4];int pos=0;for(int i=0;i<len;i++) if(in_str!=',') output[pos++]=in_str - '0';And if you really want to obfuscate your code:
const char in_str[]="0,0,0,0";int len=0,i=0,pos=0;int output[4];while(in_str[len]!='\0'){len++;}for(;i<len;i++){if(in_str!=','){ output[pos++]=in_str - '0';}}Quote:
The purpose of this was to see how people would go about writing an algorithm without using a string tokenizing function.
I wouldn't. I have better things to do with my time. But, y'know... each to their own.
Quote:
I have done this many a time and can never remember how i did it.
I wonder how much time you've wasted doing that? It is your time, though, I suppose, and you may do with it as you wish...
Quote:
Original post by eq
My C/C++ contribution:
*** Source Snippet Removed ***
Boom, instant crash.
sscanf's parameters need to be pointers to the variables you want to fill in... which is part of why it's such a bad idea to use the C string functions when C++ library code is available. (Incidentally, that post is also a good illustration of why mucking about with raw string parsing is not really wise when library code is available to do the same job.)
In any case, I think this violates the OP's (rather silly) requirement of not using library code.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement