1

I am trying to read students data (name, department, roll, sgpa, cgpa), I used fgets function to read name and department, but it skips to the department and can't read name. here is my code:

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

typedef struct {
    char name[100];
    char department[50];
    int roll;
    float sgpa[12];
    float cgpa;
} Student;

void add(FILE *fp);
void modify(FILE *fp);
void display(FILE *fp);
FILE * del(FILE * fp);

int main(int argc, char **argv) {
    int option;
    FILE *fp;
    fp = fopen("db.txt", "rb+");
    if (fp == NULL) {
        fp = fopen("db.txt", "wb+");
        if (fp == NULL) {
            printf("Can't open the database");
            return 0;
        }
    }
    printf("\t1. Add Student");
    printf("\n\t2. Modify Student");
    printf("\n\t3. Show All Student");
    printf("\n\t4. Remove Student");
    printf("\n\tEnter Your Option :--> ");
    scanf("%d",&option);
    switch(option)
    {
        case 1:
            add(fp);
            break;
        case 2:
            // modify(fp);
            break;
        case 3:
            // display(fp);
            break;
        case 4:
            // fp = del(fp);
            break;
        default:
            printf("Unkonw option\n");
    }
    return 0;
}

void add(FILE *fp) {
    Student std;
    int i;
    float cgpa;
    fseek(fp,0,SEEK_END);
    printf("\n\tEnter Full Name of Student: ");
    fflush(stdin);
    fgets(std.name,100,stdin);
    std.name[strlen(std.name)-1]='\0';
    printf("\n\tEnter Depertment Name: ");
    fflush(stdin);
    fgets(std.department,50,stdin);
    std.department[strlen(std.department)-1]='\0';
    printf("\n\tEnter Roll number: ");
    scanf("%d",&std.roll);
    printf("\n\tEnter SGPA for 12 semesters\n");
    for(i=0,cgpa=0; i<12; i++)
    {
        scanf("%f",&std.sgpa[i]);
        cgpa+=std.sgpa[i];
    }
    cgpa/=12.0;
    std.cgpa=cgpa;
    fwrite(&std,sizeof(std),1,fp);
}
  • 3
    `strlen` only works with strings and not with char arrays. The difference between a string and a char array is, that a string must have a `'\0'`, a char array needn't to have one. _"The C library function size_t strlen(const char *str) computes the length of the string str up to, but not including the terminating null character."_ So when you use `strlen` on a not `'\0'` terminated char array, you might get a buffer overflow. – paladin Apr 30 '21 at 10:48
  • 1
    Yes. Your debugger (e.g. [GDB](https://www.gnu.org/software/gdb/)) could tell you, if you compile your C code with [GCC](http://gcc.gnu.org/) invoked as `gcc -Wall -Wextra -g`. But before, **read [this C reference](https://en.cppreference.com/w/c) and [*Modern C*](http://modernc.gforge.inria.fr/)** – Basile Starynkevitch Apr 30 '21 at 14:20

1 Answers1

-1

Is there a way of limiting scanf in C?

I did this, if you're having that many problems with string input giving an eye on my other answer might help you

Here's a more specific answer to your problem on message you place what you wanna print before the input and StringInput you place the array you're using to hold the message I hope this works since you also use a array for it

also i see this:

fp = fopen("db.txt", "rb+");
    if (fp == NULL) {
        fp = fopen("db.txt", "wb+");
        if (fp == NULL) {
            printf("Can't open the database");
            return 0;
        }
    }

which may not be what you want because if it fails because of a sudden glitch by using wb+ you will overwrite it

“r+” – Searches file. Opens the file for both reading and writing. If opened successfully, fopen() loads it into memory and sets up a pointer which points to the first character in it. Returns NULL, if unable to open the file.

“w+” – Searches file. If the file exists, its contents are overwritten. If the file doesn’t exist, a new file is created. Returns NULL, if unable to open the file.

FUNCAUX_MAX_STRING is a macro and you define it like so:

#define FUNCAUX_MAX_STRING 100

This makes it so that the number or elements is 100 and you can easily change every number thats using the macro by simply changing the value once

void readString(char message[FUNCAUX_MAX_STRING], char StringInput[FUNCAUX_MAX_STRING], int maxChars)
{
    int sizeString;

    do          // Repete leitura caso sejam obtidas strings vazias
    {
        printf("%s", message);
        fgets(StringInput, maxChars, stdin);

        sizeString = strlen(StringInput);

        if (sizeString == 1)
        {
             printf("Nao foram introduzidos caracteres!!! . apenas carregou no ENTER \n\n");  
        }

    }
    while (sizeString == 1);

    if(StringInput[sizeString-1] != '\n') 
    {
        cleanBufferStdin(); 
    }
    else
    {
        StringInput[sizeString-1] = '\0';   
    }

}
void cleanBufferStdin(void)
{
    char chr;
    do
    {
        chr = getchar();
    }
    while (chr != '\n' && chr != EOF);
}
Imeguras
  • 436
  • 6
  • 18
  • Answers should answer. The answer to the question should be contained in the posted answer, not presented merely as a link to somewhere else. And, if a question is a duplicate that can be fully answered with just a link to somewhere else, it should be closed as a duplicate rather than answered. – Eric Postpischil Apr 30 '21 at 11:24
  • @EricPostpischil its not a complete duplicate but just using a slightly modified code would answer i think – Imeguras Apr 30 '21 at 14:10
  • @EricPostpischil what about now can you remove the downvote? or should i remove the link all together? – Imeguras May 04 '21 at 22:28