If my program is going to have large lists of numbers passed in through stdin
, what would be the most efficient way of reading this in?
The input I'm going to be passing into the program is going to be of the following format:
3,5;6,7;8,9;11,4;;
I need to process the input so that I can use the numbers between the colons (i.e I want to be able to use 3 and 5, 6 and 7 etc etc). The ;;
indicates that it is the end of the line.
I was thinking of using a buffered reader to read entire lines and then using parseInt.
Would this be the most efficient way of doing it?
This is a working solution
One way to do this is to use strtok() and store the values in an array. Ideally, dynamically allocated.
Using strtok by passing ',' and ';' as deleminator.
Finally you have to account for the double ";;" by reducing the count by 1, because atoi(token) will return 0 for that case and store it in the nth index. Which you don't want.
I would read in the command args, then parse using the
strtok()
library methodhttp://man7.org/linux/man-pages/man3/strtok.3.html
(The web page referenced by the URL above even has a code sample of how to use it.)
I'm a little rusty at C, but could this work for you?
getchar_unlocked()
is what you are looking for.Here is the code:
For input
1;2;2;;3;;4;;;;;54;;;;
the code above produces1 2 2 3 4 54
.I guarantee, this solution is a lot faster than others presented in this topic. It is not only using
getchar_unlocked()
, but also usesregister
,inline
as well as multiplying by 10 tricky way:(*x<<1) + (*x<<3)
.I wish you good luck in finding better solution.
One other fairly elegant way to handle this is to allow
strtol
to parse the input by advancing the string to be read toendptr
as returned bystrtol
. Combined with an array allocated/reallocated as needed, you should be able to handle lines of any length (up to memory exhaustion). The example below uses a single array for the data. If you want to store multiple lines, each as a separate array, you can use the same approach, but start with a pointer to array of pointers to int. (i.e.int **numbers
and allocate the pointers and then each array). Let me know if you have questions:Output
Also works where the string is stored in a file as:
Using
fgets
and withoutsize_t
It took a little reworking to come up with a revision I was happy with that eliminated
getline
and substitutedfgets
.getline
is far more flexible, handling the allocation of space for you, withfgets
it is up to you. (not to mentiongetline
returning the actual number of chars read without having to callstrlen
).My goal here was to preserve the ability to read any length line to meet your requirement. That either meant initially allocating some huge line buffer (wasteful) or coming up with a scheme that would reallocate the input line buffer as needed in the event it was longer than the space initially allocate to
ln
. (this is whatgetline
does so well). I'm reasonably happy with the results. Note: I put the reallocation code in functions to keepmain
reasonably clean. footnote 2Take a look at the following code. Note, I have left the
DEBUG
preprocessor directives in the code allowing you to compile with the-DDEBUG
flag if you want to have it spit out each time it allocates. [footnote 1] You can compile the code with:or if you want the debugging output (e.g. set LMAX to
2
or something less than the line length), use the following:Let me know if you have questions:
footnote 1
nothing special about the choice of the word
DEBUG
(it could have beenDOG
, etc..), the point to take away is if you want to conditionally include/exclude code, you can simply use preprocessor flags to do that. You just add-Dflagname
to passflagname
to the compiler.footnote 2
you can combine the reallocation functions into a single
void*
function that accepts a void pointer as its argument along with thesize
of the type to be reallocated and returns a void pointer to the reallocated space -- but we will leave that for a later date.What you could do is read in from stdin using fgets or fgetc. You could also use getline() since you're reading in from stdin.
Once you read in the line you can use strtok() with the delimiter for ";" to split the string into pieces at the semicolons. You can loop through until strok() is null, or in this case, ';'. Also in C you should use atoi() to convert strings to integers.
For Example: