#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
enum oflow { OFL_GOOD, OFL_OVER, OFL_UNDER };
int getnums(const char *str, int nums[], enum oflow oflow[], int n)
{
int i;
for (i = 0; *str; ) {
char *junk;
long val;
str += strcspn(str, "0123456789+-");
if (!*str)
break;
errno = 0;
val = strtol(str, &junk, 10);
if (junk > str) {
if (i < n) {
if (((val == LONG_MIN) && errno == ERANGE) || (val < INT_MIN)) {
nums[i] = 0;
oflow[i++] = OFL_UNDER;
} else if (((val == LONG_MAX) && errno == ERANGE) || (val > INT_MAX)) {
nums[i] = 0;
oflow[i++] = OFL_OVER;
} else {
oflow[i] = OFL_GOOD;
nums[i++] = val;
}
} else {
i++;
}
str = junk;
} else {
str++; /* no number was pulled out: skip one char and try again */
}
}
return i;
}
int main(int argc, char **argv)
{
int nums[256];
enum oflow oflow[256];
if (argc > 1) {
int n = getnums(argv[1], nums, oflow, 256);
int i;
if (n > 256) {
printf("array is too small: we need %d elements\n", n);
n = 256;
}
for (i = 0; i < n; i++) {
if (oflow[i])
printf("nums[%d] = %sflow\n", i, oflow[i] == OFL_OVER ? "over" : "under");
else
printf("nums[%d] = %d\n", i, nums[i]);
}
}
return 0;
}
测试:
$ ./nums ""
$ ./nums "0"
数字[0] = 0
$ ./nums "-"
$ ./nums "+"
$ ./nums "+1"
数字[0] = 1
$ ./nums "-1"
数字[0] = -1
$ ./nums "abc"
$ ./nums "asd+asdf+1 -0+1-3234abc-10zzz-"
数字[0] = 1
数字[1] = 0
数字[2] = 1
数字[3] = -3234
数字[4] = -10
$ ./nums "+++-1+++"
数字[0] = -1
$ ./nums "++"
$ ./nums "1+11111111111111111111111-111111111111111111111"
数字[0] = 1
nums[1] = 溢出
nums[2] = 下溢
$ ./nums "$(seq 1 300)" |头-5
数组太小:我们需要 300 个元素
数字[0] = 1
数字[1] = 2
数字[2] = 3
数字[3] = 4
$ ./nums "$(seq 1 300)" |尾-5
数字[251] = 252
数字[252] = 253
数字[253] = 254
数字[254] = 255
数字[255] = 256
作业练习:在什么情况下junk == str 在strtol 之后,以使str++ 案例执行?为什么我们需要这个逻辑?