0

I'm trying remove line break from input using strtok() and pass it to struct property using strcpy() but when i execute this the Visual Studio Code is returning this message:

enter image description here

My code:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <locale.h>

typedef struct
{
    char name[50];
    char document[50];
    char cep[50];
    char phone[50];
    char address[50];
    char birthdate[50];
    char email[50];
    char diagnosticDate[50];
    int age;
    char comorbidities[50];
} Ocurrence;

void insert_new_record()
{
    Ocurrence new_record;
    char comorbity_option[3];
    printf("Choose option number: ");
    fgets(&comorbity_option, sizeof(comorbity_option), stdin);
    switch (comorbity_option[0])
    {
    case '1':
        strcpy(new_record.comorbidities, "Diabetes");
        break;
    case '2':
        strcpy(new_record.comorbidities, "Obesidade");
        break;
    case '3':
        strcpy(new_record.comorbidities, "Hipertensão");
        break;
    case '4':
        strcpy(new_record.comorbidities, "Tuberculose");
        break;
    case '5':
        strcpy(new_record.comorbidities, "Outros");
        break;
    default:
        strcpy(new_record.comorbidities, "Nenhuma");
        break;
    }

    strcpy(new_record.name, strtok(new_record.name, "\n"));
    strcpy(new_record.cep, strtok(new_record.cep, "\n"));
    strcpy(new_record.address, strtok(new_record.address, "\n"));
    strcpy(new_record.phone, strtok(new_record.phone, "\n"));
    strcpy(new_record.birthdate, strtok(new_record.birthdate, "\n"));
    strcpy(new_record.diagnosticDate, strtok(new_record.diagnosticDate, "\n"));
    strcpy(new_record.document, strtok(new_record.document, "\n"));
    strcpy(new_record.email, strtok(new_record.email, "\n"));
}

int main()
{
    setlocale(LC_ALL, "Portuguese");
    show_login();
    show_menu();
    return 0;
}

On debug mode is possible verify that error is show after line: strcpy(new_record.name, strtok(new_record.name, "\n"));

I have search for this on StackOverflow, but anything help to solve this. Could someone help me?

  • 1
    `strcpy(new_record.name, strtok(new_record.name, "\n"));` Where do you suppose `new_record.name` is initialized, and if it's not what do you expect `strtok` to do? Besides, `strcpy` has undefined behavior when the source and destination strings overlap. – dxiv Nov 17 '20 at 00:42
  • Did you leave out the code that gets all the fields from the user? – Barmar Nov 17 '20 at 00:48
  • You should get an error message for `fgets(&comorbity_option, sizeof(comorbity_option), stdin);` (if not, adjust compiler settings) – M.M Nov 17 '20 at 00:52
  • the posted code does not compile! two of the main reasons it does not compile is the calling of the functions: `show_login()` and `show_menu()` – user3629249 Nov 17 '20 at 19:54
  • regarding: `strcpy(new_record.name, strtok(new_record.name, "\n"));` and similar statements: what are you trying to perform? Is it the removal of any trailing '\n' from `new_record.name[]`? If so, then suggest: `new_record.name[ strcspn( new_record.name, "\n" ) ] = '\0';` – user3629249 Nov 17 '20 at 19:59
  • regarding: `typedef struct {` most debuggers cannot display the individual fields in a struct unless the struct definition include a 'struct name', similar to: `typedef struct myStruct {` – user3629249 Nov 17 '20 at 20:03
  • regarding: `char comorbity_option[3]; printf("Choose option number: "); fgets(&comorbity_option, sizeof(comorbity_option), stdin); switch (comorbity_option[0])` this code contains lots of problems. Suggest: `char comorbity_option; comorbity_option = getchar();` `switch( comorbity_option )`.. – user3629249 Nov 17 '20 at 20:09
  • NOTE: the posted code fails to input any of the fields of the struct! So any statements that source those fields results in undefined behavior – user3629249 Nov 17 '20 at 20:12
  • OT: the posted code contains several 'magic' numbers. (3, 50). 'Magic' numbers are numbers with no basis. 'magic' numbers make the code much more difficult to understand, debug, etc. Suggest using an `enum` statement or `#define` statements to give those 'magic' numbers meaningful names, then use those meaningful names throughout the code – user3629249 Nov 17 '20 at 20:15

1 Answers1

1

It is a precondition for the strcpy() function that the source and target strings do not overlap. strtok() tokenizes by modifying the input string in-place, so all your strcpy() calls violate that precondition. But you don't need strcpy() here, anyway, because strtok() does modify the input string. It should be sufficient to just perform the strtok(). For example:

strtok(new_record.name, "\n");

But it would be clearer to use, say, strcspn(), as that makes it explicit that the intent is to modify the string:

new_record.name[strcspn(new_record.name, "\n")] = '\0';

As long as the input string is properly terminated, that's safe whether or not the input string contains a newline.

Speaking of string termination, however, that is a major problem with the code presented. More generally, failure to initialize your strings is a significant problem. Appearing at block scope as it does, this ...

    Ocurrence new_record;

... does not initialize new_record or any of its members. The code afterward does set a value in (the initial bytes of) new_record.comorbidities, but all the other members retain fully indeterminate values when the program reaches your strcpy() calls.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157