1

My program skips the next input after 1 pass through it. I have read the threads on removing the newline character that fgets has, but nothing that was suggested worked. Is there anything that would work with microsoft visual studio? The best suggestion was "words[strcspn(words, "\r\n")] = 0;" and this did not remove the new line, unless I am formatting it incorrectly. I am not allowed to use the strtok function.

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

#define SIZE 50
#define STOP "quit\n"

char *copywords(char *dest, const char *source, size_t n);

int main(void) 
{

    char words[50];
    char newwords[50];
    size_t num;

    for (;;) {

        printf("\nType a word, or type 'quit' to quit: ");
        (fgets(words, SIZE, stdin));


        if (strcmp(words, STOP) == 0) {
            printf("Good bye!\n");
            return 0;
        }

        printf("Type the # of chars to copy: ");
        scanf_s("%d", &num);

        copywords(newwords, words, num);
        printf("The word was %s\n", words);
        printf("and the copied word is %s", newwords);


    }
}

char *copywords(char *dest, const char *source, size_t n) {
    size_t i;
    for (i = 0; i < n && source[i] != '\0'; i++) {
        dest[i] = source[i];
    }
    dest[i] = '\0';
    return dest;
}
Community
  • 1
  • 1
Markovnikov
  • 41
  • 4
  • 13
  • run your program in a debugger (and by run I mean single step) – KevinDTimm Nov 29 '16 at 20:55
  • `scanf_s("%d", &num);` leaves a `newline` in the input buffer, which is collected as the empty string by the next `fgets`. Please do not mix your input methods: use `fgets` followed by `sscanf` for the `int`, instead of `scanf_s("%d", &num);`. BTW the MSVC `scanf_s` is really no better than the `scanf`, just as easy to fall foul of. – Weather Vane Nov 29 '16 at 21:01
  • Also `size_t num;` --> `int num;` (because for `scanf_s("%d", &num);` ) – BLUEPIXY Nov 29 '16 at 21:09
  • Using sscanf messes up the code, even after I convert size_t num to int num. – Markovnikov Nov 29 '16 at 21:18
  • case of using gcc, `%zu`with `__USE_MINGW_ANSI_STDIO` macro for `size_t`. case of using MSVC `%I`. see [Size Specification](https://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx) – BLUEPIXY Nov 29 '16 at 21:25

3 Answers3

0

The problem is that you leave the \n on the input when you call scanf. i.e. the user types number[return]. You read the number. When you loop around and call fgets agains the return is still waiting to be read so thats what fgets gets and it returns immediately.

I would probably just call fgets the second time you want to read input as well and then use sscanf to read from the string. i.e.

printf("Type the # of chars to copy: ");
fgets(buffer, ...)
sscanf(buffer, "%d", ...)

As an aside I would also say to check return values as it is easy for fgets or *scanf to fail.

user133831
  • 590
  • 5
  • 13
0

My program skips the next input after 1 pass through it.

If I understand you correctly, the problem is that scanf_s (which I assume is like the C standard's scanf) will read the digits into num, but scanf won't remove the following newline from stdin, and so in the next iteration of the loop fgets will see that newline and behave as if it had seen a blank line. I have usually avoided scanf for this reason and instead read a line into a buffer and then parse it. For example:

char buf[50];
...
fgets(buf,sizeof(buf),stdin);
sscanf(buf,"%d",&num);

(I'd also recommend adding a whole lot more error checking throughout.)

Waxrat
  • 2,075
  • 15
  • 13
0

Here's a straightforward solution.

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

#define SIZE 50
#define STOP "quit\n"

char *copywords(char *dest, const char *source, size_t n);

int main(void) 
{

    char words[50];
    char newwords[50];
    size_t num, run = 0;

    for (;;) {

        printf("\nType a word, or type 'quit' to quit: ");
        if(run)
            getchar();
        (fgets(words, SIZE, stdin));

        if (strcmp(words, STOP) == 0) {
            printf("Good bye!\n");
            return 0;
        }

        printf("Type the # of chars to copy: ");
        scanf("%d", &num);

        copywords(newwords, words, num);
        printf("The word was %s\n", words);
        printf("and the copied word is %s", newwords);
        run = 1;
    }
}

char *copywords(char *dest, const char *source, size_t n) {
    size_t i;
    for (i = 0; i < n && source[i] != '\0'; i++) {
        dest[i] = source[i];
    }
    dest[i] = '\0';
    return dest;
}

Since we know there will be an extra '\n' character left in the stream due to the scanf, just take it out.

SenselessCoder
  • 1,139
  • 12
  • 27