1

well I have a buffer of I'm assuming 10 characters. I notice when I enter 9 characters though it will skip prompt EX.

Enter a p value:
123456789
Enter a q value:
Enter a k value:

But if I put in 8 or less it will accept it normally as the program is intended, even if the user inputs letters or special characters.

My code:

#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <ctype.h>
int main()
{
   char pbuffer[10], qbuffer[10], kbuffer[10];
   int p=0, q=0, k=0;
   int r, i, Q, c, count, sum;
   char a[3];
   a[0]='y';
   while(a[0]=='y' || a[0]=='Y')
   {
      printf("Enter a p value: \n");
      fgets(pbuffer, sizeof(pbuffer), stdin);
      p = strtol(pbuffer, (char **)NULL, 10);

      printf("Enter a q value: \n");
      fgets(qbuffer, sizeof(qbuffer), stdin);
      q = strtol(qbuffer, (char **)NULL, 10);

      printf("Enter a k value: \n");
      fgets(kbuffer, sizeof(kbuffer), stdin);
      k = strtol(kbuffer, (char **)NULL, 10);

      while(p<q+1)
      {
         Q=p;
         sum=0;
         count=0;
         while(Q>0)
         {
            count++;
            r = Q%10;
            sum = sum + pow(r,k);
            Q = Q/10;
         }

         if ( p == sum && i>1 && count==k )
         {
            printf("%d\n",p);

         }
         p++;
         a[0]='z';
      }
      while((a[0]!='y') && (a[0]!='Y') && (a[0]!='n') && (a[0]!='N'))
      {
         printf("Would you like to run again? (y/n) ");
         fgets(a, sizeof(a), stdin);
      }
   }
   return 0;
}
Andrew Ricci
  • 475
  • 5
  • 21
  • possible duplicate of [Why scanf("%d", \[...\]) does not consume '\n'? while scanf("%c") does?](http://stackoverflow.com/questions/13275417/why-scanfd-does-not-consume-n-while-scanfc-does) – ThisaruG Oct 01 '14 at 16:53

5 Answers5

3

fgets will read in as many characters as it can until it hits either a newline, EOF, or the size of the buffer. It also saves one extra character for a string-terminating \0. So, if you type in 123456789\n and have a 10-character buffer, fgets knows that it can only fit 9 characters in that buffer, so it reads in the first 9 and appends a NULL, giving you 123456789\0 in your buffer, and \n still in STDIN. Then, you call fgets a second time. It doesn't wait for input, because there is already a \n in STDIN, so it reads up to that \n, which happens to be only one character. So, your second buffer is now \n\0, and STDIN is now empty.

Either make your buffers large enough to store the strings that you're going to input, or flush STDIN after every fgets. Likely something like:

while((c = getchar()) != '\n' && c != EOF)
/* Ignore the character */                ;
Dan
  • 10,531
  • 2
  • 36
  • 55
  • Could you recommend how to do about clearing the STDIN buffer. I've tried many ways and the only way that I've seen work is fflush(stdin) but I know that's bad to use. – Andrew Ricci Sep 24 '14 at 14:32
  • Sweet that worked!. Although now, when I enter 8 or less characters it brings me to the next line waiting for ANY input that seems to have zero relevance and THEN prompts me for the proper input. Aside form that 9+ characters work solid. – Andrew Ricci Sep 24 '14 at 15:09
  • @AndrewRicci Ah, right, I didn't realize that. What you could do is check to see if there's a `\n` in `pbuffer`, and only execute the above while loop if there is not one. – Dan Sep 24 '14 at 15:36
  • I'm so sorry to ask this but how would that look code-wise. As this is for an assignment, I don't believe in writing code I don't understand, I'm truly trying to write secure code. – Andrew Ricci Sep 24 '14 at 15:52
  • @AndrewRicci , `if(pbuffer[9]=='\0')` ,clear the `stdin` – Spikatrix Sep 24 '14 at 15:57
  • You'd have to make it more like `if(pbuffer[9] == '\0' && pbuffer[8] != '\n') {while(...);}`. Otherwise, `12345678\n\0` behaves the same as `123456789\0`. – Dan Sep 24 '14 at 16:00
0

Add this line after the fgets

scanf("\n");

ThisaruG
  • 3,222
  • 7
  • 38
  • 60
0

Instead of reading into a char buffer first, you could use scanf(), e.g. scanf("%d", &p) could replace both fgets() and strtol().

Sebastian
  • 1
  • 1
0

Flush the stdin after to the calls to fgets using

int c;
while((c = getchar()) != '\n' && c != EOF);

The reason why fgets dosen't wait for the user to enter data is because fgets knows that the buffer is full (9 chars and one space for \0) and appends a \0 in the end of the string and leaves the \n in the stdin which is taken by the next fgets

Spikatrix
  • 20,225
  • 7
  • 37
  • 83
0

Actually fgets retains the \n character when the size argument provided to it is less than the characters entered. In your case you provided value 10 as size to fgets.

so When you enter 9 characters, it fills the buffer with them and waits for an enter from you to stop reading. And when you press the enter it just puts the null character in the end of it and forward the enter to next prompt and hence skipping it.

check the examples in the answer to a question https://stackoverflow.com/a/11180652/1386897.

Community
  • 1
  • 1
Sami
  • 155
  • 3