0

I implemented a C program where you enter a sequence of numbers separated with a space like 1 2 3 4 5. The program sees that the max time limit of entering each sequence is 15 seconds.

The code causes the output:

Kindly specify the length of the sequence: 3
Kindly specify the number of the colors in the sequence: 3
Input sequence: 
Sorry, I got tired waiting for your input. Good bye!
Input sequence:

instead of

Kindly specify the length of the sequence: 3
Kindly specify the number of the colors in the sequence: 3
Input sequence: 

I mean it does not let me enter the sequence on the line 3 of output but rather goes ahead and finishes one loop of timer and then lets me input the sequence. Why is that? This does not happen if i remove the printf and scanf functions in the following main() code.

Here is my code:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define INPUT_LEN 10

/* read a guess sequence from stdin and store the values in arr */
void readString(int *arr)
{
    fflush(stdout);
    time_t end = time(0) + 15; //15 seconds time limit.

    int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
    fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);

    char answer[INPUT_LEN];
    int pos = 0;

    while (time(0) < end)
    {
        int c = getchar();

        /* 10 is new line */
        if (c != EOF && c != 10 && pos < INPUT_LEN - 1)
        {
            answer[pos++] = c;
        }

        /* if new line entered we are ready */
        if (c == 10)
            break;
    }

    answer[pos] = '\0';

    if (pos > 0)
    {
        int x = 0;
        char *ptr = strtok(answer, " ");

        while (ptr != NULL)
        {
            sscanf(ptr, "%d", (arr + x++));
            ptr = strtok(NULL, " ");
        }
    }
    else
    {
        puts("\nSorry, I got tired waiting for your input. Good bye!");
        // exit(EXIT_FAILURE);
    }
}

int main()
{
    int seqlen = 0, colors = 0;

    printf("Kindly specify the length of the sequence: ");
    scanf("%d", &seqlen);
    printf("Kindly specify the number of the colors in the sequence: ");
    scanf("%d", &colors);

    int *guessSeq = (int *)malloc(sizeof(int) * 5);
    int found = 0, attempts = 0;

    while (!found)
    {
        if (++attempts > 10)
            break;
        /* IMPLEMENT the main game logic here */
        printf("Input sequence: ");
        readString(guessSeq);
    }

    return (0);
}
Criss Hills
  • 189
  • 1
  • 12
  • Use `'\n'` in place of `10` throughout. – Jonathan Leffler Mar 18 '21 at 18:07
  • There are better ways of implementing timeouts than the one you're using. You'd need to set alarms or timers, but you'd avoid the busy-loop that you have by setting the input to `O_NONBLOCK`. – Jonathan Leffler Mar 18 '21 at 18:09
  • an elaborated answer would really be appreciated as i am quite new to this stuff – Criss Hills Mar 18 '21 at 18:10
  • 1
    it should be because [c - scanf() leaves the new line char in the buffer - Stack Overflow](https://stackoverflow.com/questions/5240789/scanf-leaves-the-new-line-char-in-the-buffer) – MikeCAT Mar 18 '21 at 18:10
  • Those are comments, not answers. I'm still trying to work out why the code you've got, inefficient as it is, is not working. Are you on a Linux box, perchance, or something else (and if something else, what)? – Jonathan Leffler Mar 18 '21 at 18:11
  • I run and store all my .c file in VSCode on my WSL Ubuntu – Criss Hills Mar 18 '21 at 18:14
  • The problem is as @MikeCAT suggests — the `scanf()` for `colors` leaves the newline in the input buffer, which means that the `readString()` function gets the newline immediately, and the buffer is empty, so you report the (misleading) error message. Fix by reading the rest of the input line for `colors` before calling `readString()`: use `int c; while ((c = getchar()) != EOF && c != '\n') ;` to read the residue up to and including the newline. – Jonathan Leffler Mar 18 '21 at 18:16
  • The significance of the question about platform is that commentary suggesting the use of POSIX functions might or might not be useful. With WSL, you may be OK. You could look at the POSIX [`timer_gettime()`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_gettime.html) functions. Or you can look at various 'legacy' alternatives (`alarm()`, `setitimer()`, … and corresponding signal handling functions). – Jonathan Leffler Mar 18 '21 at 18:23
  • Thank you! The code works as expected now – Criss Hills Mar 18 '21 at 18:27
  • The behavior of `fflush(stdout)` is undefined. – anastaciu Mar 18 '21 at 18:30

0 Answers0