Reputation: 11479
I have a function that should be passed a string with two numbers (as a regex: /-?[0-9]+ -?[0-9]+/
) and return the second.
I've decided that the program should do error checking. First, it should test if the string is actually of the desired form; second, it should ensure that the first numbers (the ones that are not returned) are sequential.
Now I've been programming for a long time and this is not a difficult task. (It's made slightly more difficult by the fact that the numbers need not fit into a machine word.) But my question is about how I should do this rather than how I can. All of the solutions I've come up with are somewhat ugly.
NULL
); this seems like The Wrong Thing.So any thoughts relating to the proper way to deal with error-checking of this sort in C would be welcome.
This is related to a much more theoretical question I asked on cstheory. For reference, here is the function:
char*
scanInput(char* line)
{
int start = 0;
while (line[start] == ' ' || line[start] == '\t')
start++;
if (line[start] == '#')
return NULL; // Comment
if (line[start] == '-')
start++;
while (line[start] >= '0' && line[start] <= '9')
start++;
while (line[start] == ' ' || line[start] == '\t')
start++;
int end = start;
if (line[end] == '-')
end++;
while (line[end] >= '0' && line[end] <= '9')
end++;
if (start == end)
return NULL; // Blank line, or no numbers found
line[end] = '\0';
return line + start;
}
and it is called like so:
while(fgets(line, MAX_LINELEN, f) != NULL) {
if (strlen(line) > MAX_LINELEN - 5)
throw_error(talker, "Maximum line length exceeded; file probably not valid");
char* kept = scanInput(line);
if (kept == NULL)
continue;
BIGNUM value = strtobignum(kept);
if (++i > MAX_VECLEN) {
warning("only %d terms used; file has unread terms", MAX_VECLEN);
break;
}
// values are used here
}
Upvotes: 2
Views: 113
Reputation: 753455
Ultimately, you are going to need to isolate and convert both big numbers in each line. To check that the first number on the line is the one that follows the previous, you will have to keep a record of the last such number found. So, you will probably need a structure such as:
BIGNUM old_value = 0; // See notes below
while (fgets(line, sizeof(line), f) != 0)
{
BIGNUM value1;
BIGNUM value2;
if (ScanDoubleBigNum(line, &value1, &value2) != 0)
...handle line format error...
if (old_value == 0 || are_consecutive(old_value, value1))
{
// OK - valid information found
// Release old_value
old_value = value1;
process(value2);
// Release value2
}
else
...handle non-consecutive error...
}
The are_consecutive()
function determines whether its second argument is one greater than its first. The process()
function does whatever you need to do with the second value. The ScanDoubleBigNum()
function is related to your ScanInput()
but it reads two values. The actual code will call another function (call it ScanBigNum()
) containing about half of ScanInput()
(since that contains essentially the same code twice), plus the conversion that currently occurs in your loop. The code in ScanDoubleBigNum()
will call ScanBigNum()
twice. Note that ScanBigNum()
will need to identify where the scan finishes so that the second call can continue where the first stopped.
I'm taking the liberty of assuming that a BIGNUM
is an allocated structure identified by a pointer, so the initialization BIGNUM old_value = 0;
is a way of indicating there is no value yet. There is presumably a function to release a BIGNUM
. If this is incorrect, then you need to adapt the proposed code to accommodate the actual behaviour of the BIGNUM
type. (Is this based on OpenSSL or SSLeay code?)
Upvotes: 1
Reputation: 69924
The traditional solution in C is to use pass by reference (pointers) to return the values your function computes and use the return value for error handling, just like how scanf does this.
int scanInput(char **line_p int *number){
char * line = *line_p;
...
if(something bad happens){
return 1;
}
...
*linep = line + start;
*number = ...;
return 0; //success
}
int main(){
char word[100]; strcpy(word, "10 17");
char *line = word;
int number;
switch(scanInput(&line, &number)){
case 1:
default:
}
}
Extra points:
Upvotes: 2