Home > Software design >  C function swallows the first letter of user input string
C function swallows the first letter of user input string

Time:06-22

This function writes to a txt file 3 user inputs; namely the ID, category and description. The ID should be an integer while the others should be strings.

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

void addtask();
char menu();

int main() {
    char selection ;
   do {
    selection = menu() ;
    switch(selection) {
        case '1': addtask(); break;
        case '2': break;
        default: printf("\n\n\nInvalid key entered");
    }
   }while(selection != '2');
   return 0;
}

char menu() {
    char option;
    printf("\nWelcome to the task management system. Please enter a key to continue...\n");
    printf("\n1) Add new task");
    printf("\n2) Save and quit\n");
    scanf("%c[^\n]", &option);
    return option;
}

void addtask() {
    int id;char category[21];char description[101];
    printf("\nCreating new task...\n\n");
    FILE * f = fopen("tasklist.txt", "r ");
    if(f == NULL){
        printf("File does not exist. Creating new file...");
        f = fopen("tasklist.txt", "w");
    }
    else {
            fseek(f, 0, SEEK_END);  //move to end of cursor
            printf("\nENTER id:");
            scanf("%d", &id);
            printf("\nEnter category (max 20 characters): ");
            getchar();
            fgets(category, 21, stdin);
            printf("\nEnter description (max 100 characters): ");
            getchar();
            fgets(description, 101, stdin);
            printf("writing: %d \t %s \t %s \t", id, category, description);
            fprintf(f,"%d \t %s \t %s \t", id, category, description);
    }
    fclose(f);
}

When I run the program and input 2 sets of ID, category and description, I get in the txt file

1    Cat1
     esc1
    2    Cat2
     esc2

where I think I should expect

1    Cat1   Desc1
2    Cat2   Desc2

What's wrong?

CodePudding user response:

Due to the mix of scanf and fgets, you get some weird behavior.

The main issue is the user's "enter" (\n) press when writing input to the terminal. scanf leaves it be in the stdin's buffer, while fgets includes it in the string it puts the input into. Lets focus in your addtask function, inside the else brackets:

  • scanf("%d", &id); takes only the number the user entered, so stdin cleaned off the number, but it still has a\n character inside it. The next getchar() call discards it, which leaves u with a clean buffer.
  • fgets(category, 21, stdin); takes the next input the user writes, including the \n character. You probably want replace it with a \0 character to match your format. you can do it with a line like: category[strcspn(category, "\n")] = '\0'; as suggested here.
  • Now, the next getchr() call simply "swallows" the first letter of the input the user writes next, which explains your missing letters in the descriptions.
  • Finally, fgets(description, 101, stdin); takes the rest of the user input, including the newline (\n) character(which you should probably let be in this case, since you asked for a new line after each description).

Note: To fully match your requested format, you also need to remove the last tab char (\t) from the line: fprintf(f,"%d \t %s \t %s \t", id, category, description);. Since the last description string (%s) already has a new line in it, and you wouldn't want your next line to start with a tab.

  •  Tags:  
  • c
  • Related