Doubt in exercise in C - reading with fgets

Asked

Viewed 957 times

0

Good evening, I am learning C language through Luis Damas' book. There is an exercise of it that the program is not ending in condition.

I’m using linux so I had to change the function gets() for fgets(), I don’t know if the code needs any more modification to work on Linux. As the code shows, if I did not enter with some character the program should end, but it is not ending.

Another thing is that the output is skipping a line, is not writing the Name,Surname in one line.

Code I have:

#include <stdio.h>
#include <string.h>
#define DIM 20
#define SEP_NOME ","

int main()
{
    char Nome[DIM+1], Sobrenome[DIM+1],Completo[2*DIM+1];
    while (1)
    {
        printf("Nome: "); fgets(Nome, DIM+1, stdin);
        if(strlen(Nome)==0) break; /* Terminar o programa */
        /* Colocar o Sobrenome, Nome na string Completo */
        printf("Sobrenome: "); fgets(Sobrenome, DIM+1, stdin);
        strcpy(Completo,Sobrenome); /* Copiar sobrenome */
        strcat(Completo,SEP_NOME); /* Juntar separador */
        strcat(Completo,Nome); /* Juntar o prim. Nome */
        puts(Completo);
    }
}
  • I own this book, very good by the way. Could you tell me where the exercise is?

  • It’s prog0705 I’m reading through the college’s online system, here’s page 163.In Chapter 7.

  • Look, I tested the program exactly as in the book, it just includes the header string. h (which was not in the book) and it worked perfectly. Except that I am using Windows 7 x64 a few days ago, I removed Linux from the PC, so there is no way I can test it. But on Windows, I am using GCC 8.1.0.

  • The gets and fgets functions are a little different. Although it is not recommended to use the gets function, for simple exercises like this you can use it. fgets will consider as valid character of the string the character ' n' that signals the end of the input and can limit the number of characters read. In your case you need to eliminate this 'n' end that is forcing the line break.

1 answer

0

The two problems are actually the same, which is the fact of the fgets leave the line break in the read string. For this reason, the if that tests if it has size 0 will never work because it always has at least one character, the line break, and consequently will break between the two names when trying to show on the screen.

It has several ways to solve the problem, but one of the most direct is through the function strspn looking for a string inside another. In case you want to search for the \n to put the terminator in its place and if there is no end.

Code with line breaks removed:

#include <stdio.h>
#include <string.h>
#define DIM 20
#define SEP_NOME ","

int main()
{
    char Nome[DIM+1], Sobrenome[DIM+1],Completo[2*DIM+1];
    while (1)
    {
        printf("Nome: "); 
        fgets(Nome, DIM+1, stdin);
        Nome[strcspn(Nome, "\n")] = '\0'; /* Remover quebra no nome*/
        if(strlen(Nome)==0) break; 

        printf("Sobrenome: "); 
        fgets(Sobrenome, DIM+1, stdin);
        Sobrenome[strcspn(Sobrenome, "\n")] = '\0'; /* Remover quebra no sobrenome */
        strcpy(Completo,Sobrenome); 
        strcat(Completo,SEP_NOME); 
        strcat(Completo,Nome); 
        puts(Completo);
    }
}

See in Ideone working

If you use gets instead of fgets does not have the same problem, because the gets does not leave the line break inside the string, but gets is not recommended because it only finishes the reading when it finds line break. This makes the user can put more characters than the size of the string you set and thus create a buffer overflow Attack.

As a final note, the code will run on both windows and linux without having to make any adjustments.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.