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

typedef struct Details{
    int num;
    char message[100];
}Notes;

void write(FILE*,Notes);
void read(FILE*);

int main()
{
    int c;
    FILE *fp = fopen("Notes.txt","w+");
    Notes txt;
    printf("Select choice\n1.Write\n2.Read\n");
    scanf("%d",&c);
    if(fp == NULL)
        printf("Could not able to open the file\n");
    else
    switch(c){
        case 1:
            write(fp,txt);
        case 2:
            read(fp);
    }
    return 0;
}

void write(FILE* fp,Notes msg)
{
    puts("Enter text\n");
    fgets(msg.message,20,stdin);
    fputs(msg.message,fp);
    fclose(fp);
}

void read(FILE* fp)
{
    char ch;
    do{
        ch=fgetc(fp);
        printf("%c",ch);
      }while(ch != EOF);
    fclose(fp);
}

When I run the above code on write case (case 1) fgets() is not taking any inputs from the user via keyboard.

I need the user contents which the user types on the keyboard should be stored in a file and to be read when required.

Clifford
  • 88,407
  • 13
  • 85
  • 165
IndyRose
  • 37
  • 7
  • `scanf()` leaves `\n` in the input buffer. `fgets()` finds that character and returns a very, very short line... Good luck... – Fe2O3 Aug 22 '23 at 10:19
  • @Fe2O3 but I didn't use any scanf() inside write() function – IndyRose Aug 22 '23 at 10:22
  • "_but I didn't_" The code executes a `scanf()` getting some input. The next input uses `fgets()`... There is only one "standard input" used for the entire execution of this program. – Fe2O3 Aug 22 '23 at 10:24
  • @Fe2O3 So how to fix it ? – IndyRose Aug 22 '23 at 10:26
  • "_So how to fix it _" You could refer to the documentation for `scanf()` to see how to read and immediately trash characters from the input stream... (Hint: asterisks are involved.) While you're there, you might investigate the "return value" from this system call. Users can be an unpredictable bunch, entering text when your program wants to read a numeric value. Since `c` is uninitialised, rejected input may lead to unexpected results... – Fe2O3 Aug 22 '23 at 10:31
  • @Oka On that post the user didn't use fgets() or fgetc() – IndyRose Aug 22 '23 at 10:32
  • @Fe2O3 I have tried flushing the FILE *fp using fflush(fp) function before fgets() but then also it behaves the same – IndyRose Aug 22 '23 at 10:37
  • Why don't you consider replacing the neophyte's `scanf()` with another `fgets()`... Once you've got the first entry as a string, you could use `sscanf()` to try to convert the string to a number... (PS: `flushing` `fp` is flushing the **output** file, not the **input** file...) – Fe2O3 Aug 22 '23 at 10:45
  • @IndyRose Re: "*On that post the user didn't use fgets() or fgetc()*" - you are missing the point of the duplicate. When you use `scanf("%d", ...) `, if encountered, the newline character is left in the input buffer (`stdin`). The next time you go to read from the input buffer in any way (`fgets`, `fgetc`, `getchar`, or even another `scanf`) that newline will still be there, and must be consumed in some way. `fgets` consumes this newline by seeing it for the end-of-line marker that it is, and immediately returns after populating *your* buffer with nothing but the newline. – Oka Aug 22 '23 at 10:53
  • @Oka when I flush the stdin before entering the function write() by fflush(stdin) then also it behaves the same. – IndyRose Aug 22 '23 at 11:00
  • That's because `fflush(stdin)` is [undefined behaviour](https://en.cppreference.com/w/c/language/behavior). See: [Using fflush(stdin)](https://stackoverflow.com/q/2979209/2505965) – Oka Aug 22 '23 at 11:03
  • 1
    Instead of pressing ENTER immediately after typing your choice, try typing `1 hello world`, and then pressing ENTER. Observe the results of the `scanf` being delimited by a space, and `fgets` not encountering the newline immediately. – Oka Aug 22 '23 at 11:04
  • 1
    If you want the quickest fix, then `scanf("%d%*c",&c);`. If you want to actually learn, then properly sit down and read the information contained in the [duplicate](https://stackoverflow.com/q/5240789/2505965), and [How can I clear an input buffer in C?](https://stackoverflow.com/q/7898215/2505965) – Oka Aug 22 '23 at 11:08
  • Note that your example actually does not compile (not a [mre]) because `fgets(msg.message,20s,stdin);` contains an invalidly suffixed integer constant (`20s`), and `do { ... }` is missing the trailing `while` clause. This code cannot replicate the behaviour you've described, so it is actually unclear if we're looking at the same problem. Please post a proper [mre] by precisely copying your code to the question (as text, use copy and paste). – Oka Aug 22 '23 at 11:13
  • @Oka I have made the required changes by removing "s" in fgets() and adding while condition after do and inserted scanf("%d%*c",&c); as you have mentioned. Its working properly now. Thank you :) – IndyRose Aug 22 '23 at 11:20
  • @Oka but after entering the text I couldn't able to read it again. Its blank when I tried to read it – IndyRose Aug 22 '23 at 11:24
  • @Oka I didn't make any mistakes on reading the file again but why I cannot red the file back again ? – IndyRose Aug 22 '23 at 11:28
  • See: [`fopen`](https://en.cppreference.com/w/c/io/fopen) for the effects of a `"w+"` mode. You are truncating (resetting / destroying the contents of) your file every time you open it. Try separately opening your file for writing (`"w"`) in one function, and reading (`"r"`) in the other. – Oka Aug 22 '23 at 11:31

1 Answers1

0

The problem with the code is that the fgets function reads the newline character \n from the previous scanf input and does not wait for the user to enter the message. To fix this, you can either use scanf with a format specifier %[^\n]s to read the message, or add a getchar function after the scanf to consume the newline character.

Here is the modified code:

#include <stdio.h>
#include <stdlib.h>
typedef struct Details {
  int num;
  char message[20];
} Notes;
void write(FILE *, Notes);
void read(FILE *);
int main() {
  int c;
  FILE *fp = fopen("Notes.txt", "w+");
  Notes txt;
  printf("Select choice\n1.Write\n2.Read\n");
  scanf("%d", &c);
  if (fp == NULL)
    printf("Could not able to open the file\n");
  else
    switch (c) {
    case 1:
      write(fp, txt);
    case 2:
      read(fp);
    }
  return 0;
}
void write(FILE *fp, Notes msg) {
  puts("Enter text\n");
  getchar(); // added this line
  fgets(msg.message, 20, stdin);
  fputs(msg.message, fp);
  fclose(fp);
}
void read(FILE *fp) {
  char ch;
  do {
    ch = fgetc(fp);
    printf("%c", ch);
  } while (ch != EOF);
  fclose(fp);
}

Try this!!