1

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?

  • You should never use `fgets()` when you depend on input from outside of the program (like user input) because then your program can very easily be infected. – Kolodez Jun 21 '22 at 07:11
  • Are the outputs of the `printf` and the `fprintf` which follow each other equal? – Kolodez Jun 21 '22 at 07:13
  • 2
    The format string for `scanf(”%c[^\n]”, &option);` is implausible. It will read a character because of the `%c`, but the user has to be extraordinarily prescient to enter an open square bracket and a caret and possibly white space and a close square bracket. A scan set uses `%[…]` or `%[^…]`. – Jonathan Leffler Jun 21 '22 at 07:23
  • 1
    The `fgets()` for the category reads the newline too. The `getchar()` before the next `fgets()` reads and discards the first letter of the description. Remove it. – Jonathan Leffler Jun 21 '22 at 07:26
  • 1
    Don't mix `scanf()` and (`fgets()` or `getchar()`). Use exclusively `fgets()` for user input ... possibly followed by `sscanf()` (notice two 's') for lazy parsing. – pmg Jun 21 '22 at 07:56

1 Answers1

0

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.

Wadite RK
  • 133
  • 1
  • 5