2

here is my current code:

int num = 0;
char c = '#';

scanf("%d",&num);
do{
    for (int i=0;i<num;i++){
        printf("%c",c);
    }
    printf("\n");
}
while (scanf("%d", &num) == 1);

How would I have it so that if the user doesn't enter anything, that the program won't spit out a newline?

Any help is appreciated, thank you!

Immortal
  • 61
  • 1
  • 6
  • 1
    Possible duplicate of [Get scanf to quit when it reads a newline?](http://stackoverflow.com/questions/3723044/get-scanf-to-quit-when-it-reads-a-newline) – Martin Zabel Jan 24 '16 at 21:29
  • Hmmm, what you call "empty", I would call input of only `"\n"` and save the idea of _empty_ input for `""`. – chux - Reinstate Monica Jan 24 '16 at 21:31
  • 1
    `%d` of `scanf` will ignore(skip) the preceding newline(white-spaces). – BLUEPIXY Jan 24 '16 at 22:09
  • If the user hits `^D` (or `^Z` on Windows) before any number, the above program prints a newline. The OP wants no output. Replace the `do` / `while` logic with a simple `while` loop. – chqrlie Jan 24 '16 at 22:17
  • @WorldSEnder: your answer was perfect. MartinZabel ignores the end of file case, his comment does not point to a real issue. – chqrlie Jan 24 '16 at 22:20

3 Answers3

2

This code should work for what you want to do :

#include <stdio.h>

int main()
{
    int num = 0;
    char c = '#';
    char readLine[50];

    while ((fgets(readLine, sizeof readLine, stdin) != NULL) && sscanf(readLine, "%d", &num) == 1)
    {
        for (int i=0;i<num;i++){
                printf("%c",c);
        }
        printf("\n");
        fflush(stdout);
    }
    return 0;
}

The behaviour of this code is the following : fgets will read anything you enter in the standard stream (stdin), and put it in the readLine array. The program will then try to read the number which is in your readLine variable and put it in your num variable with the sscanf function. If a number is read, the program will execute the behaviour you did present in your question (writing a # character "num" times), and go back to the beginning of the loop. If anything else than a number has been read, the loop is stopped.

Izuka
  • 2,572
  • 5
  • 29
  • 34
  • You are not ignoring blank lines, you stop the program on blank lines. Removing the `&& (readLine[0] != '\n')` would fix this. It is not needed anyway. – chqrlie Jan 24 '16 at 22:15
0

In general, avoid scanf. It's very easy to leave yourself with unprocessed cruft on the input stream. Instead, read the whole line and then use sscanf (or something else) to process it. This guarantees that you won't get stuck with a partially read line, those are hard to debug.

I prefer getline to fgets to read lines. fgets requires you to guess how long the input might be, and input might get truncated. getline will allocate the memory to read the line for you avoiding buffer overflow or truncation problems.

NOTE: getline is it's not a C standard function, but a POSIX one and fairly recent (2008), though it was a GNU extension well before that. Some older compilers may not have it.

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

int main()
{
    char c = '#';
    char *line = NULL;
    size_t linelen = 0;

    /* First read the whole line */
    while( getline(&line, &linelen, stdin) > 0 ) {
        /* Then figure out what's in it */
        long num = 0;
        if( sscanf(line, "%ld", &num) > 0 ) {
            for( int i = 0; i < num; i++ ) {
                printf("%c", c);
            }
            printf("\n");
        }
    }

    free(line);

    return 0;
}

if( sscanf(line, "%ld", &num) > 0 ) { will ignore any line that does not match any part of the pattern, such as a blank line or a line full of words, by checking how many things matched. Yet it will still handle 0 as a valid input.

$ ./test
foo
bar
foo123
12
############

1
#
0

2
##

I also moved num inside the loop to guarantee it's reinitialized each iteration, and on the general principle of putting your variables in minimum scopes to avoid interference. And I upgraded it to a long int better able to handle the unpredictably large numbers users might type in.

Community
  • 1
  • 1
Schwern
  • 153,029
  • 25
  • 195
  • 336
0

Here is how I have done input parsing over the years using the fgets() and sscanf() functions. I don't write c++ much, and if I can I keep code within old style ansi C then I do. The fgets and sscanf functions from the stdio.h library are universal and are always available on any platform.

For a character array used to read in anything, I generally set LINE_SIZE to 256 or 512 even if I know typically the line to be read is 80 characters or less. With any computer today having over 1GB of RAM, not worth worrying about allocating an extra 500 or so bytes. Obviously, if you have no idea how long the input line is then you either have to:

guess at what LINE_SIZE should be set to and not worry about it

or verify a newline character is present in line[] prior to a null character after calling fgets().

# include <stdio.h>

# define LINE_SIZE  256

int main ( int argc, char *argv[] )
{
    FILE *fp;
    char line[LINE_SIZE];
    int nn;
    int value;

    fp = fopen( "somefile", "r" );

    fgets( line, LINE_SIZE, fp );

    /*
        this way to read from standard input (i.e. the keyboard)
        using fgets with stdin prevents compiler warning when using
        deprecated gets function

        fgets( line, LINE_SIZE, stdin );
    */

    if ( line[0] != '\n' )
    {
        /* definitely not a blank line */

        nn = sscanf( line, "%d", &num );

        if ( nn == 1 )
        {
            /* some number placed into num variable that met the
               %d conversion for the sscanf function
            */
        }
    }
    return 0;
ron
  • 967
  • 6
  • 23