In the code below I am attempting to establish a method of inputing a year with digits (only digits) into the character array of year. It works, but now if the inputed non-digits are 4 or more (i.e. "abcd") the program runs the printf command more than once. I recommend you examining in a compiler so you know what I mean. Please if anybody knows why is the program doing this?

#define kYear       5


int main() {
    
    char year[kYear];
    short i;
    bool isYear;
    
    do{
        for(i=0;i!=(kYear-1);i++)
            year[i]=0;
    printf("Enter year introduced: ");
    fgets(year, kYear, stdin);
        
        for(i=0;i<kYear;i++){
            if(isdigit(year[i])){
                isYear=true;
            }
            else{
                isYear= false;
                break;
            }
        }
        
    }while(!isYear);    
}

Recommended Answers

All 14 Replies

Dude , you didnt print the output anywhere in the program .
By the way , the program seems not to meet the terminating condition of do-while loop , thats why its printing more than once.
I tried a different approach.And it works fine,although i don know what to do with the program.Also , you gotta use the stdin somewhere .

#include<stdio.h>
#include<stdbool.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
#define kYear       5

int main(void) {
    
    char year[kYear];
    short i;
    int isYear;
    do
      {
        for(i=0;i!=(kYear-1);i++)
            year[i]=0;
    printf("Enter year introduced: ");
    fgets(year, kYear, stdin);
        
        for(i=0;i<kYear;i++)
        {
            if(isdigit(year[i]))
            isYear=1;
            
        else{
                isYear = 0;
                break;
            }
        }
        
    }while(isYear==1);    
  return(0);
}
Input:
 
abcdefg

Output:
 
Enter year introduced:

The problem is extraneous characters in the stream, but you might consider using scanf() to do the heavy lifting of reading only digits:

#include <stdio.h>

int main(void)
{
    char year[5];
    int n;
    
    fputs("Enter year introduced: ", stdout);
    fflush(stdout);

    while (scanf("%4[0123456789]%n", year, &n) != 1 || n != 4) {
        fputs("Invalid input\n", stdout);
        fflush(stdout);
        
        if (!feof(stdin)) {
            int ch;
            
            /* Trim extraneous characters */
            while ((ch = getchar()) != '\n' && ch != EOF)
                ;
        }
    }
    
    puts(year);
    
    return 0;
}

Of course, the down side is the magic numbers. If you want to support say two and four digit years, or you don't want magic numbers, it becomes a less attractive approach due to the hoops in creating a format string for scanf():

#include <stdio.h>

#define FULL_YEAR 4
#define HALF_YEAR 2

int main(void)
{
    char year[FULL_YEAR + 1];
    char fmt[BUFSIZ];
    int n;
    
    sprintf(fmt, "%%%d[0123456789]%%n", FULL_YEAR);
    
    fputs("Enter year introduced: ", stdout);
    fflush(stdout);

    while (scanf(fmt, year, &n) != 1 || (n != FULL_YEAR && n != HALF_YEAR)) {
        fputs("Invalid input\n", stdout);
        fflush(stdout);
        
        if (!feof(stdin)) {
            int ch;
            
            /* Trim extraneous characters */
            while ((ch = getchar()) != '\n' && ch != EOF)
                ;
        }
    }
    
    puts(year);
    
    return 0;
}

Note that in all cases, even with fgets(), you need to decide what to do with extraneous characters after a valid year. The two most common options are leaving them for subsequent input requests and removing them up to a newline. The latter is fairly trivial with scanf():

#include <stdio.h>

#define FULL_YEAR 4
#define HALF_YEAR 2

int main(void)
{
    char year[FULL_YEAR + 1];
    char fmt[BUFSIZ];
    int ch;
    int n;
    
    sprintf(fmt, "%%%d[0123456789]%%n", FULL_YEAR);
    
    fputs("Enter year introduced: ", stdout);
    fflush(stdout);

    while (scanf(fmt, year, &n) != 1 || (n != FULL_YEAR && n != HALF_YEAR)) {
        fputs("Invalid input\n", stdout);
        fflush(stdout);
        
        if (!feof(stdin)) {
            /* Trim extraneous characters */
            while ((ch = getchar()) != '\n' && ch != EOF)
                ;
        }
    }
    
    /* Silently flush the rest of the line */
    while ((ch = getchar()) != '\n' && ch != EOF)
        ;
    
    puts(year);
    
    return 0;
}

But at this point, fgets() (or some function reading arbitrarily long lines) begins to look like the best option due to simplicity:

#include <stdio.h>
#include <string.h>

#define FULL_YEAR 4
#define HALF_YEAR 2

int main(void)
{
    char year[FULL_YEAR + 1] = {0};
    char buf[BUFSIZ];
    
    fputs("Enter year introduced: ", stdout);
    fflush(stdout);

    while (fgets(buf, sizeof buf, stdin) != NULL) {
        size_t len = strlen(buf);
        
        /* Trim the newline if present */
        if (buf[len - 1] == '\n')
            buf[--len] = '\0';
        
        /* Check for a validity */
        if ((len == FULL_YEAR || len == HALF_YEAR) && 
            strspn(buf, "0123456789") == len)
        {
            strcpy(year, buf);
            break;
        }
        
        fputs("Invalid input\n", stdout);
        fflush(stdout);
    }
    
    puts(year);
    
    return 0;
}

Im having a bit of trouble understanding the purpose of the fflush function. Is there any example that could demonstrate a visible effect? I've spent these last 4 days researching it and the only lead I have is that every type FILE has a buffer.
Also I've searched my entire C reference book (written by Herbert Schildt) and I can't seem to find any reference to multiple modulus operators like you did with sprintf: "%%%d[0123456789]%%n". What does this piece of code do? sprintf(fmt, "%%%d[0123456789]%%n", FULL_YEAR);

Here is a rough example of why you would want to use it.

If you comment out fflush(stdin); then it skips asking for input every second one, but with it you get asked every time.

#include <stdio.h>
#include <stdlib.h>

int main()
{
	int i = 1;
	char input;
	while(1)
	{
		printf("\n\nLoop number %d - input 'Y' or 'y' to stop\n", i);
		fflush(stdin);
		scanf("%c", &input);
		if( input == 'y' || input == 'Y' )
			break;
		i++;
	}

	return 0;
}
commented: Flushing stdin is undefined. Do NOT do it. -4

I just ran the code and it skips every second one either fflush is present or not

fflush() on any input stream, is undefined. It may work on some compilers and operating systems, but is not standard, and you'd be wise to use fflush() ONLY on output streams, not input streams.

Think of it like the plumbing in your house. You can flush the toilet, but flushing the kitchen sink is just goofy, and not likely to work.

One way to handle the extra newline that scanf() always leaves behind, is to put this:

getchar();

right after the scanf(). That will pull off ONE newline char, from the input buffer.

Always good to have this, whenever you are using scanf() to obtain a char. It probably will not bother a scanf() for integers, floats, or strings.

This:

while((ch=getchar()) != '\n');

will remove all the char's in the input stream up to and including the first newline char. Which is normally all you'd ever want, at any time.

A good example of that is this:

#include <stdio.h>

int main(void) {
  int num;
  do {
     scanf("%d", &num);
  }while(num != 1);

  return 0;
}

But enter a letter, instead of a number, into the above, and watch it go nuts!

Now try the same loop with a getchar added:

#include <stdio.h>

int main(void) {
  int num;
  do {
     scanf("%d", &num);
     getchar();
  }while(num != 1);

  return 0;
}

And see how much better the loop behaves, now! Pretty amazing, imo.

There are scanf() formats that can also handle this newline problem char. Look them up, sometime - there is a lot there.

Here is a rough example of why you would want to use it.

If you comment out fflush(stdin); then it skips asking for input every second one, but with it you get asked every time.

Completely wrong! fflush() is defined only for output streams. stdin is not an output stream, therefore fflush() is not defined and therefore not guaranteed to work. And since it's undefined for input streams, it potentially could crash the program in some compilers. fflush() is used to make sure all the output is sent to the output device. Since C uses buffered I/O, the output goes into an internal system buffer and when this buffer is full, the data is finally sent to the physical device. fflush() is used to force the buffer to be output data whether full or not.

Good to know. It works with MinGW in Code::Blocks.

Good to know. It works with MinGW in Code::Blocks.

Maybe so. But 3 years from now when you move to a new compiler and the code you've been using for the past 7 years suddenly doesn't work anymore, are you going to remember it might be because if fflush()? What's the chance your reaction will be "but it's always worked before!"

Stop using it now and get a jump on good habits.

Quote originally posted by sfuo ...

Good to know. It works with MinGW in Code::Blocks.

Maybe so. But 3 years from now when you move to a new compiler and the code you've been using for the past 7 years suddenly doesn't work anymore, are you going to remember it might be because if fflush()? What's the chance your reaction will be "but it's always worked before!"

Stop using it now and get a jump on good habits.

I meant good to know not to use it.

When I was looking for something to clear the input stream I came across fflush() on http://www.cplusplus.com/reference/clibrary/cstdio/fflush/ and just tested it rather than reading what they had written about the function.

WaltP is there any example of code that you know that shows fflush in action. I believe if you use it with files it doesn't flush the buffer instead it prints the buffers information onto the file

WaltP is there any example of code that you know that shows fflush in action. I believe if you use it with files it doesn't flush the buffer instead it prints the buffers information onto the file

"flush the buffer" means "it prints the buffers information onto the file".

What is your real question? You don't need an example code, you already know it's syntax. What is does is invisible anyway.

WaltP is there any example of code that you know that shows fflush in action. I believe if you use it with files it doesn't flush the buffer instead it prints the buffers information onto the file

For performance reasons, output streams in C cache characters in memory and then write them to the destination en masse on the assumption that writing to the destination is time consuming, such as by accessing the hard disk. fflush() lets the programmer explicitly force the cache to be written. There are three times the cache might be flushed:

  1. The cache is full
  2. A newline ('\n') is printed
  3. fflush() is called

Of those three, #1 is completely out of your control, and #2 requires a visible character to be printed. fflush() is the only way to force a flush without printing anything, so it's convenient for same-line prompts.

As for examples of usage, take a look at my code in this thread. Specifically, this:

fputs("Enter year introduced: ", stdout);
fflush(stdout);

while (scanf("%4[0123456789]%n", year, &n) != 1 || n != 4) {

On some systems you might encounter a bug where scanf() blocks for input before the prompt is displayed (because no newline is printed). The user would have no clue what to type, and calling fflush() ensures that the prompt is displayed correctly while still keeping the behavior of having the prompt and user input on the same line.

fflush() works the same way for all output streams, so further examples should be unnecessary.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.