1

I know this seems a very easy problem but till I am not getting the required output. Please correct any mistakes on asking the question as i am posting question on this site for the first time.

The code I tried is as follows:

#include<stdio.h>
int main()
{
    int i, n;
    char name[20][80];
    printf("\nEnter the number of students: ");
    scanf("%d", &n);
    printf("\nEnter the name of the students: ");
    for(i=0; i<n; i++)
    {
        fgets(name[i], 80, stdin);
    }
    printf("\nThe name of the students are: \n");
    for(i=0; i<n; i++)
    {
        puts(name[i]);
    }
    return 0;
}

But the output is like:

Enter the number of students: 3
Enter the name of students: Park Jimin
Jeon Jungkook 

The name of the students are:
Park Jimin
Jeon Jungkook 

I can't understand why the number of students became 2 though I mentioned 3. Please help.

Ankita Pal
  • 121
  • 1
  • 7
  • 4
    Does this answer your question? [scanf() leaves the new line char in the buffer](https://stackoverflow.com/questions/5240789/scanf-leaves-the-new-line-char-in-the-buffer) – Stephen Newell Jul 01 '20 at 05:32
  • @StephenNewell I used fgets function to input names – Ankita Pal Jul 01 '20 at 05:50
  • 1
    @AnkitaPal Yes, you did, yet he is right. The solution you accepted only shadows your problem as it runs the loop the first time without doing anything. You can easily verify this by putting a printf into your first loop and let it print the value of i. For i=0 you will see that it does not accept any input, so your name[0] will just be an line ending. If you do the same in the second loop, you will see it printing the empty one. – BallisticTomato Jul 01 '20 at 07:17
  • @BallisticTomato Yes I knew that. I accepted that answer as I thought that there is no solution to my question and that change makes the desired output. Please add the correct solution. – Ankita Pal Jul 01 '20 at 07:23
  • The problem is that there are different solutions depending on what you consider the problem. I your case I assume, you consider the unneeded linefeed as the problem as it interferes with your expected programm result. Personally I would rather see the problem in not checking your inputs for the desired data. Anyway I added an answer with both options for you to choose from. – BallisticTomato Jul 01 '20 at 11:56

3 Answers3

1

Don't use the scanf family of functions - in my experience they cause more problems than they solve. In this case the issue is that scanf leaves the newline (\n) character in the buffer after you entered the number of students, so a blank line was read the first time your program tried to get a student name. The following should solve your homework problem successfully:

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

int main()
  {
  int i, n;
  char buf[20];
  char name[20][80];
  
  printf("Enter the number of students: ");
  fgets(buf, sizeof(buf), stdin);
  n = atoi(buf);

  for(i=0; i<n; i++)
    {
    printf("Enter student name #%d: ", i+1);
    fgets(name[i], 80, stdin);
    name[i][strlen(name[i])-1] = '\0';  /* overwrite the trailing \n */
    }

  printf("\nThe names of the students are:\n");
  for(i=0; i<n; i++)
    printf("name[%d] = \"%s\"\n", i, name[i]);
  return 0;
  }

OnlineGDB test here

0

Instead of using fgets and puts use scanf and printf as shown in below code. Below code is working I checked it. You can change it as you want show like with carriage return etc.

int i, n;
      char name[20][80];
      printf("\nEnter the number of students: ");
      scanf("%d", &n);
      printf("\nEnter the name of the students: ");
      for(i=0; i<n; i++)
      {
          //fgets(name[i], 80, stdin);
          scanf("%s",name[i]);
          printf("%d",i);
      }
      printf("\nThe name of the students are: \n");
      for(i=0; i<n; i++)
      {
          //puts(name[i]);
          printf("%d%s",i,name[i]);
      }
      return 0;
Imran
  • 775
  • 7
  • 19
  • Have you checked this code sent by me? Its working perfectly fine. – Imran Jul 01 '20 at 05:40
  • I don't know why but when I entered the first it stopped taking other names – Ankita Pal Jul 01 '20 at 05:41
  • After entering first name press enter. It is working perfectly fine with me – Imran Jul 01 '20 at 05:46
  • You should provide an explanation on why you want to use scanf and printf. The desired results can be achieved with fgets as well. You maybe should elaborate on what the buffers do in the background in order to foster a better understanding on why the code is behaving like it is. And please consider not begging for upvotes/acceptance as it is considered noise. See here: https://meta.stackoverflow.com/questions/271810/is-it-ok-to-ask-to-upvote-accept-my-own-answers/271815#271815 – BallisticTomato Jul 01 '20 at 07:24
0

From my pov, the issue here is an unexpected newline character in the input buffer. While this behaviour is known, there are two different approaches to resolve this.

1. Sanitize your inputs: Simply reading data and working on this data is often a bad idea. Therefore you may want to check, if the data you just got makes sense and is within your expectation. In your example you should never accept an empty name, no matter if comes from buffer artifacts or real user input.

int j = 0;
while(j<n)
{
    printf("Write to index: %d", j);
    fgets(name[j], 80, stdin);
    if (name[j][0] != '\n')
        {
            j++;
        }
}

https://onlinegdb.com/Hy5ZDWq0U

Restructuring your input loop to something like this already gets rid of empty entries. Yet it is not even close to a fully sanitized input as there are numbers, printable and non-printable special characters and length limitations to consider. The printf("Write to index: %d", j) easily shows you, that the evil newline is still there, but due to our input check it is overridden within the next loop execution. The output loop can remain unchanged and will not print any empty entries anymore.

2. Try to clear the buffer: Another approach is to clear the buffer in order to get known preconditions before calling fgets or similar functions. Within Using fflush(stdin) you can find a nice discussion on how this can go wrong and why it is rather brittle to do so.

Personally I would always prefer the first over the second solution, as your code should be responsible to handle unexpected inputs according to its needs. Relying on others easily goes wrong, if they do not exactly know, what your expectations are.

  • Thank you very much. But, I am just confused which answer I should accept as there are 2 correct answers(yours included). So, I upvoted both the answers and accepted one of them. – Ankita Pal Jul 01 '20 at 14:39
  • Perfectly fine, you decide, which answer fits your question best. Anyway consider not creating "Thank you" comments and instead use the Thanks flag on the left as stated here https://stackoverflow.com/help/someone-answers Even so I really appreciate your explenation and polite manners. ;) – BallisticTomato Jul 01 '20 at 14:47