1

I am working in a function to create an email, but I do not know how to read an "enter" from the user using fgets, in the body part. My code is the following one:

void read_email_interactive(Email* email) {
printf("Subject: ");
fgets(email->subject,DEFAULT_MAX_FIELD,stdin);

printf("From: ");
fgets(email->from,DEFAULT_MAX_FIELD,stdin);

printf("To: ");
fgets(email->to,DEFAULT_MAX_FIELD,stdin);

printf("Body: ");
fgets(email->body,MAX_BODY,stdin);

printf("ID: ");
fgets(email->id,DEFAULT_MAX_FIELD,stdin);

Any Idea? Thank you!

JIAN CHEN
  • 33
  • 4
  • 1
    `fgets()` does read the new-line! – alk Feb 10 '18 at 13:01
  • Yes but in a body message the user usually press several "enters", but here if I press the enter it is going to the next instruction – JIAN CHEN Feb 10 '18 at 13:02
  • I see, the body part consists od multiple lines - and you want to read them as a chunk? – user2736738 Feb 10 '18 at 13:02
  • When the user hits the Enter key, that looks like `\n` to a C program. When `fgets` reads a line (that is, up to `\n`), it leaves the `\n` in the string it creates for you. So those strings like `email->subject` that you read will all have `\n` at the end. And if the user types nothing except just Enter, the string will be just `"\n"`. – Steve Summit Feb 10 '18 at 13:03
  • 1
    The idea is to consider reading the body and when user enters a blank line you will udnerstand that the body is complete let's move to the next section. This you can follow for other commands also. – user2736738 Feb 10 '18 at 13:04
  • @coderredoc Yes, any solution? ^^ – JIAN CHEN Feb 10 '18 at 13:04
  • 1
    @JIANCHEN.: Just said the solution. Redesign the code little bit to incorporate blank lines as end of sections. – user2736738 Feb 10 '18 at 13:05
  • @coderredoc Sorry the page didn't update the last message, thank you very much! – JIAN CHEN Feb 10 '18 at 13:06
  • But you need to make sure that the structure element `email->body` can actually store a multi-line input. You can concatenate any new input to it and use `\r` to store the actual line endings, but it takes some string shuffling and a temporary string for the actual input. – Jongware Feb 10 '18 at 13:08
  • Is it acceptable to have maximum message text size? – alk Feb 10 '18 at 13:17
  • @alk: ... umm, yeah `\r` is usually a ctrl+Return (which suggests another solution for OP), I did mean a single `\n`. But there is no need to mark end-of-string as it's already indicated by the terminating 0. – Jongware Feb 10 '18 at 13:17
  • You could use use `Ctrl+C` and catch the signal – gogaz Feb 10 '18 at 13:18
  • Delete my comment as it was BS in the end. Still using `\r` does not really make sense. – alk Feb 10 '18 at 13:19
  • Pressing Ctrl-D would also nicely indicate EOF as the last character read then is ***not*** a `\n`. – alk Feb 10 '18 at 13:20
  • Consider using [getline](https://stackoverflow.com/a/9171511/841108) – Basile Starynkevitch Feb 17 '18 at 08:35

2 Answers2

1

Assuming a maximum size of the text would be acceptable the following snippet would do:

#define BODY_MAX_LEN (1234)

struct Email
{
   char body[BODY_MAX_LEN + 1];
   ...
}

int main(void)
{
  struct Email email = {0};

  size_t s = 0;
  while ((BODY_MAX_LEN > s) && fgets(email.body + s, BODY_MAX_LEN + 1 - s, stdin))
  {
    s = strlen(email.body);
    if (!s || ('\n' != email.body[s - 1]))
    {
      break; /* EOF detected (user pressed Ctrl-D (UNIX)/Ctrl-Z  (Window). */
    }
  }

  if (ferror(stdin))
  {
    perror("fgets() failed");
    exit(EXIT_FAILURE);
  }

  ...
alk
  • 69,737
  • 10
  • 105
  • 255
1

After each

 printf("Subject: ");

Put in a

fflush(stdout);

So that the message appears

Ed Heal
  • 59,252
  • 17
  • 87
  • 127