Reputation: 27
so i am confused as to why the inbuilt strtol
is returning 0. From the manual it says it will return 0 if no conversion is possible. Though too me it should convert properly. This is the function.
struct coin * addCoins(char *val){
char *ptr =NULL;
long int denomination = strtol(val, &ptr,10);
long int count = strtol( &ptr,NULL, 10);
printf("%d",count);
struct coin *k;
k = malloc(sizeof(struct coin));
k->denom = denomination;
k->count = count;
return k;
}
This returns long integers for the denomination of the coin, and how many of the coin's there are which are then stored in a struct of type coin. Which has the following typedef
.
/* Each coin in the coins array will have a denomination (20 cents,
* 50 cents, etc) and a count - how many of that coin do we have on hand
*/
struct coin
{
enum denomination denom;
unsigned count;
};
The format of the file being read in is as follows. The first column is the denomination, and the second is the count.
1000,3
500,4
200,20
100,30
50,5
20,3
10,40
5,20
the delimiter being the comma. We where specifically told to use strtol, otherwise i would use strtok_r
.
Upvotes: 1
Views: 5220
Reputation: 34829
Your code
long int denomination = strtol(val, &ptr,10);
long int count = strtol( &ptr,NULL, 10);
The second line has some problems.
The first argument &ptr
should simply be ptr
. That's because strtol
wants a simple pointer-to-char as its first argument. So although the ampersand was correct in the first call to strtol
, it is not correct in the second call.
Problem number two is that the endptr
returned from strtol
points to the first character that's not part of the first number. In other words, it points to the comma. It's up to you to advance the pointer past the comma.
Which then introduces another problem. Before advancing the pointer past the comma, you have to make sure that it actually does point to a comma. If it doesn't, then something's amiss, and you have to fail gracefully. Since your function returns a pointer, you should return NULL
to indicate that an error occurred.
Hence, your function should be
struct coin * addCoins(char *val)
{
char *ptr;
long int denomination = strtol( val, &ptr, 10 );
if ( ptr == val || *ptr != ',' ) // verify that we found the comma
return NULL;
ptr++; // advance the pointer past the comma
char *endptr;
long int count = strtol( ptr, &endptr, 10 );
if ( endptr == ptr || *endptr != '\0' ) // verify that the second conversion succeeded
return NULL;
struct coin *k;
k = malloc(sizeof(struct coin));
k->denom = denomination;
k->count = count;
return k;
}
Upvotes: 1
Reputation: 27
The solution i came up with was the to tokenise the string before passing to strtol, but imagine there is a more elegant way to perform this operation.
char *ptr =NULL;
char *ptrs =NULL;
const char *deli = ",";
char *denominations = strtok_r(val, deli, &ptrs);
char *counts = strtok_r(NULL, deli, &ptrs);
long int denomination = strtol(denominations, &ptr,10);
long int count = strtol( counts,NULL, 10);
Upvotes: 0