Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

a function which read integers using scanf but crash if enter letters

Tags:

c

I am new to C and I want to write a function that reads a sequence of whitespace-separated integers from standard input until the maximum count is reached or EOF occurs or a non-integer is encountered. maxNumInts is the maximum number of integers to be read, nums is an array of at least maxNumInts integers, into which the integers are read. The return value of readInts() is the number of integers read into the array nums.

#include <stdio.h>

int readInts(int maxNumInts, int nums[]) {
    int count = 0;

    while (scanf("%d", &nums[count++]) != EOF && count < maxNumInts) {
    }   
    return count;   
}

int main() {
    int nums[5] = { -1, -1, -1, -1, -1 };
    int n = readInts(4, nums);
    printf("n = %d\n", n);
    for (int i = 0; i < 5; i++) {
        printf("nums[%d] = %d\n", i, nums[i]);
    }
}

I tested by entering numbers and it worked but when I tried to test it by entering:

10 100 1000 Oops -999
It returns:n = 4
nums[0] = 10
nums[1] = 100
nums[2] = 1000
nums[3] = -1
nums[4] = -1

n is supposed to be 3. How could I fix it? I prefer to use scanf().

like image 424
Chris Avatar asked Nov 24 '25 05:11

Chris


2 Answers

int readInts(int maxNumInts, int nums[])
{
    int count = 0;

    while(scanf("%d",&nums[count++]) != EOF && count < maxNumInts) {
        }   
    return count;   
}

you are incrementing count even on the call which fails. Also scanf returns the number of items read and thus will return zero not EOF when it doesn't read anything.

Try

int readInts(int maxNumInts, int nums[])
{
    int count = 0;

    while((1 == scanf("%d",&nums[count])) && (count < maxNumInts)) {
           count++;
    }   
    return count;   
}

I strongly recommend that you get an IDE, such as Eclipse, Code::Blocks, Microsoft Visual Studio or some other which you like.

Then learn about the debugger

  • how to set breakpoints
  • how to examine variables
  • how to step though your code line by line
  • how to examine the call stack
  • etc

enter image description here

Since you seem to be new, be aware of https://codereview.stackexchange.com/ When your code is working, post it there and you will get advice on how to improve it (such a n is not a very meaningful variable name)

When you can do that, you will never again have to wait for out help for issues like this, because you can find them easily in the debugger.

like image 60
Mawg says reinstate Monica Avatar answered Nov 25 '25 21:11

Mawg says reinstate Monica


Problems with code

Key issue: Wrong success checking

scanf("%d",&nums[count++]) returns 1 on success, 0 with invalid input and EOF for end of file or input error.

scanf("%d",&nums[count++]) != EOF is true with valid and invalid input.

scanf("%d",&nums[count++]) == 1 is true with valid numeric input.

Wrong count

Code increments count even when scanf() failed to read a valid int.

// while(scanf("%d",&nums[count++]) == 1 ...) {
while(scanf("%d",&nums[count]) == 1 ...) {
  count++;  // Increment here
}

Checking size too late

OP's code can access nums[count] when count is already too high. Better to check count < maxNumInts before attempting to read data. @user3629249 This has a side benefit of leaving un-read data in stdin for other code to process versus reading it here and then not saving it.

// re-order to
while(count < maxNumInts && scanf("%d",&nums[count]) == 1) {
  count++;
}

No overflow protection

When the integer as text does not convert to a value in the int range, code increments count even when scanf() failed to read a valid int, scanf("%d"... is undefined behavior when overflow occurs.

Confusing magic number 4

readInts(4, nums) uses 4 for the maxNumInts when 5 would make more sense. Best to derive the number from nums than code a naked value like 4 or 5.

int readInts(int maxNumInts, int nums[])
  ... 

int nums[5] = {-1, -1, -1, -1, -1};
// int n = readInts(4, nums);
ElementCount = sizeof nums/sizeof nums[0];
int n = readInts(4, ElementCount);

Example fix

int readInts(int maxNumInts, int nums[]) {
  int count = 0;
  while(count < maxNumInts && scanf("%d", &nums[count]) == 1) {
    count++;
    }   
  return count;   
}

Note: overflow protect not yet implemented.

like image 27
chux - Reinstate Monica Avatar answered Nov 25 '25 20:11

chux - Reinstate Monica



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!