0

Currently stuck trying to break the for loop once all the space separated have been captured. I've spent over an hour on all sorts of pages and my code looks identical to what I've been finding on other articles however. scanf() != EOF never eventuates in my code.

int readInput(unsigned char input[], size_t inputMaxLength)
{
    int size = 0; // We want to return the length of the string

    for ( int i = 0; i < inputMaxLength ; i++) { // We only want to capture n amount of chars
        if (scanf("%hhu", (input + i)) != EOF) { // input + i to iterate through the input array
            printf("i = %d , Read %d\n", i , *(input + i)); 
            size++;
        } else {
            return size; // this never occurs which means scanf never == EOF
        }
    }
    return size;
}

output looks like so,

12 65 98 45 44
i = 0 , Read 12
i = 1 , Read 65
i = 2 , Read 98
i = 3 , Read 45
i = 4 , Read 44

Unfortunately, size is never returned by this function and the script is left waiting for further input. Also, it is a constraint that i must use scanf to capture inputs for this function.

Big D Daddy
  • 29
  • 1
  • 2
  • 6
    How are you running the program? If you're entering input on the terminal, you have to type a control character to send EOF. It's Control-d on Unix, Control-z on Windows. – Barmar Aug 07 '20 at 00:46
  • Isn't the `inputMaxLength` condition decides when the for loop should break rather than `scanf` returning EOF – Sourabh Choure Aug 07 '20 at 01:06
  • 1
    Post the calling code too. A [mcve] – chux - Reinstate Monica Aug 07 '20 at 01:06
  • 1
    Step 1: `scanf("%hhu", (input + i)) != EOF` --> `scanf("%hhu", (input + i)) == 1`. Exit the loop on invalid input too. – chux - Reinstate Monica Aug 07 '20 at 01:06
  • Tip to save time. Enable all warnings. `i < inputMaxLength` should warn about mixed sign-ness compare. – chux - Reinstate Monica Aug 07 '20 at 01:08
  • 2
    If you only want one line of input, use `fgets()` (or POSIX `getline()`) to read the line, and then [use `sscanf()` in a loop](https://stackoverflow.com/questions/3975236/how-to-use-sscanf-in-loops) to read the data from the string. Otherwise, you should test for the return value from `scanf() == 1` for success (not `scanf() != EOF`) because you can get 0 back if there's a non-numeric input, or EOF if you indicate EOF at the terminal (as others said). – Jonathan Leffler Aug 07 '20 at 05:59

2 Answers2

0

If you are taking the input from a file then it should work fine I guess, but if you are taking input from terminal, then after typing the numbers with whitespaces ( like 15 20 39), you press enter which is a newline character \n not EOF.

For the terminal you have follow some logic like this

  • Since the last thing will always be a <char><newline> so if do scanf like scanf("%hhu%c", (input + i), &temp).
  • Then we can mark an ending condition like
if (temp == '\n')
{
    // add the last character in the array then break
}

I have followed the logic as mentioned above and tested the code on onlinegdb.com ( it is a little redundant, you can clean it later )

/******************************************************************************

Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, Java, PHP, Ruby, Perl,
C#, VB, Swift, Pascal, Fortran, Haskell, Objective-C, Assembly, HTML, CSS, JS, SQLite, Prolog.
Code, Compile, Run and Debug online from anywhere in world.

*******************************************************************************/
#include <stdio.h>
#include<malloc.h>

int readInput(unsigned char input[], size_t inputMaxLength)
{
    int size = 0; // We want to return the length of the string

    for ( int i = 0; i < inputMaxLength; i++) { // We only want to capture n amount of chars
        char c, d;
        scanf("%hhu%c", &c, &d);
        if (d != '\n') { // input + i to iterate through the input array
            *(input + i) = c;
            printf("i = %d , Read %d\n", i , *(input + i)); 
            size++;
        } else {
            *(input + i) = c;
            printf("i = %d , Read %d\n", i , *(input + i)); 
            size++;
            printf("Returning size\n");
            return size; // this never occurs which means scanf never == EOF
        }
    }
    return size;
}

int main()
{
    size_t a = 5;
    unsigned char *input = (char *)malloc(a*sizeof(char));
    printf("%d", readInput(input, a));
    return 0;
}

Here is my output for a test case

12 34 5                                                                                                                                                                       
i = 0 , Read 12                                                                                                                                                               
i = 1 , Read 34                                                                                                                                                               
i = 2 , Read 5                                                                                                                                                                
Returning size                                                                                                                                                                
3
0

This if block

if (scanf("%hhu", (input + i)) != EOF) 
{ 
  // input + i to iterate through the input array
  printf("i = %d , Read %d\n", i , *(input + i)); 
  size++;
}

will always be true for the iteration i = 0 to i = inputMaxLength. Because scanf("%hhu", input+i) will return 1 which is not equal to EOF(-1). That's why script is still waiting for further input, I assume if you've pressed CTRL+Z on windows or CTRL+D on linux at somewhere between 0<=i<inputMaxLength.

You can modify this snippet to something like this:

int readInput(unsigned char input[], size_t inputMaxLength)
{
    int size = 0;
    for ( int i = 0; i < inputMaxLength ; i++)
    {
        scanf(" %c", input+i);
        if ( *(input+i) != '\n' )
        {
            printf("i = %d , Read %d\n", i , *(input + i));
            size++;
        }
        else
        {
            return size;
        }
    }
    return size;
}
Shubham
  • 1,153
  • 8
  • 20
  • 1
    You should test the return value from `scanf()`. It is not clear that the user wants to read single digits; the sample input shows double-digit values being read, and `%c` precludes from working simply. – Jonathan Leffler Aug 07 '20 at 06:01
  • @JonathanLeffler Then it'll always return 1 for a successful read and `else` block will be executed at `i = inputMazLength-1`. What if user wants to exit from the loop earlier. And yeah I just put that `%c` for simplicity and also to remove the warning by the gcc compiler. – Shubham Aug 07 '20 at 18:37
  • Yes, it'll return 1 on a successful read and either 0 or EOF if there's a problem — non-numeric data or no more data available. The user can indicate EOF by typing control-D (Unix) or control-Z (Windows). – Jonathan Leffler Aug 07 '20 at 22:13