1

I wanted to write a program to generate student mark list. But in this one, i can only insert first part of the name. the rest is skipped. i looked most forums about this problem and it still happens. help if you can.

// mark list using struct

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

struct mlist { char name[30]; int cs; int maths; int eng; int total; float perc; };

void main() { int n, i;
printf("How many Students? : ");
scanf("%d", &n);

struct mlist std[n];
struct mlist *ptr = std;

printf("Marks out of 100");

for (i = 0; i < n; i++)
{
    printf("\n\nEnter details of Student %d ==>\n", i + 1);
    printf("Enter Name : ");
    scanf("%s", ptr->name);
    printf("Enter Computer Science Marks : ");
    scanf("%d", &ptr->cs);
    printf("Enter Mathematics Marks : ");
    scanf("%d", &ptr->maths);
    printf("Enter English Marks : ");
    scanf("%d", &ptr->eng);
    ptr++;
}

ptr = std;
for (i = 0; i < n; i++)
{
    printf("\n---------------------------------\n");
    printf("Name : %s\n", ptr->name);
    printf("Computer Science : %d\n", ptr->cs);
    printf("Mathematics : %d\n", ptr->maths);
    printf("English : %d\n", ptr->eng);
    ptr->total = ptr->cs + ptr->maths + ptr->eng;
    ptr->perc = (float)ptr->total / 300 * 100;
    printf("Total %d with %.2f%%\n", ptr->total, ptr->perc);
    ptr++;
}
}
  • What do you think a `%s` format means in `scanf()`? – Shawn Aug 08 '23 at 17:34
  • 1
    Read a line at a time with `fgets`. For the name, [remember to remove the newline character](https://stackoverflow.com/questions/2693776). For lines with numbers, use `strtol` or `sscanf` to convert the number. – user3386109 Aug 08 '23 at 17:40
  • @Ameen Aslam, stop using `scanf()` until you know why it is weak. Look to `fgets()` to read all user input. – chux - Reinstate Monica Aug 08 '23 at 19:41
  • This has nothing to to with your `struct`, but rather with how `scanf()` works. As the other comments already say, using `scanf()` for text input might not be the best option. `scanf()` with `%s` does not really care how long the input is or how big your buffer is and it only gets the input until the next whitespace. [This](https://stackoverflow.com/a/1248017/20785822) is a nice example of how you could use `fgets()` instead. – Joel Aug 08 '23 at 20:02

1 Answers1

0

scanf("%s", ...) reads a word. Here are some options to read a line instead:

  1. scanf("%42[^\n]", s); where s is an array of characters of 42 characters. Always include a maximum field width (here 42) when reading strings with scanf() and friends.

  2. fgets(s, sizeof s, stdin);.

  3. getline();. is another option if your struct contains a char pointer opposed to array. It will then dynamically allocate space for the array.

fgets() and getline() will include the '\n' so you may need to remove it with s[strcspn(s, "\n")] = '\0';.

Allan Wind
  • 23,068
  • 5
  • 28
  • 38
  • 1
    `getline(&(char *) { s }, &(size_t) { sizeof s }, stdin);`? Huh? [`getline()` requires its pointer to be able to be passed to `realloc()`](https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/functions/getline.html): "If `*lineptr` is a null pointer or if the object pointed to by `*lineptr` is of insufficient size, **an object shall be allocated as if by `malloc()` or the object shall be reallocated as if by `realloc()`**, ..." – Andrew Henle Aug 08 '23 at 23:04
  • @AndrewHenle Thanks a lot. I forgot it will reallocate on insufficient space. Revised answer. Let me know if we are not yet good. – Allan Wind Aug 09 '23 at 18:59