Reputation: 21
So I'm trying to store int values that have been read from the keyboard into an array of integers in C. Sample user input:
8 99 5 7 8
variable declarations:
int k;
int size;
char buf[100];
The above is my buffer and other variables for the array. The below is to read the ints into the buffer.
printf("Please enter in the numbers for the array:\n");
fgets(buf, 100, stdin);
buf[strlen(buf) - 1] = '\0';
size = (strlen(buf)/2)+1;
int *array = (int *)malloc(sizeof(int)*size);
So that correctly allocates my array.
int i, j;
for(i = 0, j = 0; i < size; i++, j = j+2)
{
array[i] = buf[j] - '0';
}
The above code actually works, but not for numbers that have double digits, only for numbers below 10 and above 0. How can I fix my code so that I correctly read in the integers?
I have tried to do a for
loop with sscanf
, but that just leads to an array with only the first integer entered in all elements.
Upvotes: 1
Views: 3564
Reputation: 34839
You can use sscanf
or strtol
to extract the numbers from the input string. In either case, you will be given three pieces of information from each call:
With sscanf
, the return value indicates success or failure. For the sscanf
in the sample code (see below), the return value is 1 for success, anything else is a failure. If successful, the value of the number is placed at the address specified, e.g. &temp
in the sample code.
And here's the tricky part: you need the location in the array to start the search for the next number. sscanf
has a special conversion for that, the %n
conversion. The output from %n
is the number of characters that were consumed while performing the conversion(s).
In the sample code below, I use a pointer ptr
that initially points to the beginning of the input string. On each pass through the loop, %n
is used in the sscanf
to update variable n
, which indicates how many characters were consumed converting the current number. By adding n
to ptr
in the for
loop, the pointer is advanced to the next number.
int *array = malloc(sizeof(int) * size);
int n = 0;
int i = 0;
for ( char *ptr = buf; *ptr; ptr += n )
{
int temp;
if ( sscanf(ptr, "%d %n", &temp, &n) != 1 ) {
// error: not a number
break;
}
array[i++] = temp;
}
As mentioned by @chux in the comments, adding a space to the format string "%d %n"
will consume trailing whitespace after each number and set the value of n
accordingly. Thus, if the input line contains only numbers, the loop will end when the for
statement detects that *ptr
has reached the NUL terminator. But if the input contains a non-number, then the loop will break
when the sscanf
fails. This can be used for error checking.
Upvotes: 1
Reputation: 95355
If the numbers are coming from stdin
, it's more effort to read them in as a string and convert them yourself than it is to have the standard library do it for you. Here I've hardcoded a maximum number of 100 integers. After the loop, i
will represent the number of valid integers in array
.
int array[100] = {0};
int i = 0;
while (i < 100)
{
int input;
int scanresult = scanf("%d", &input);
if (scanresult == 1)
{
// 1 item was successfully scanned
array[i] = input;
i++;
}
else
{
// either EOF was reached or the input was not scannable as an integer
}
}
Upvotes: 0
Reputation: 154315
How can I fix my code so that I correctly read in the integers?
Use strtol()
to parse the string as suggested by @EOF. It provides an end pointer where it left off.
long *array = malloc(sizeof *array * size);
if (array == NULL) Handle_OutOfMemory();
char *p = buf;
size_t i;
for(i = 0; i<size; i++) {
// Cope with white space with nothing after it.
while (isspace((unsigned char) *p)) p++;
if (*p == '\0') break;
char *end;
errno = 0;
long num = strtol(p, &end, 10);
// If no conversion or out of range ...
if (p == end || errno) {
fprintf(stderr, "trouble converting `%s` into an integer.\n", p);
break;
}
array[i] = num;
p = end;
}
// Use array[0] ... array[i-1]
Upvotes: 1
Reputation: 1399
unsigned int len=0,tmp=0;
char j,isnumber=0;
for(char*i=buf;j=*i;i++)
{
if(j>='0'&&j<='9')
{
tmp=tmp*10+j-'0';
isnumber=1;
}
else
{
if(isnumber)
array[len++]=tmp;
tmp=0;
isnumber=0;
}
}
Also, you don't need
buf[strlen(buf) - 1] = '\0';
size = (strlen(buf)/2)+1;
Upvotes: 0