0

I want to write functions to get and print data entered by a user. Idea is to to have name and a last name as pointers, pointers to variable size strings. What is wrong with code? What am I doing wrong? Alternatives?

#include <stdio.h>
#include <stdlib.h>
typedef struct {
   char *name;
   char *lastname;
   int marks[5];
} Student;
void setS(Student *s);
void getS(Student *s);

int main()
{
   Student st;
   getS(&st);
   setS(&st);
   return 0;
 }

 void setS(Student *s){
    int i;
    printf("Name: %s\t", s->name);
    printf("last Name: %s\t", s->lastname);
    for(i=0; i<5; i++)
        printf("%3d", s->marks[i]);
    printf("\n");
 }
 void getS(Student *s){
    int i;
    printf("Enter name\n");
    gets(s->name);
    printf("Enter last name\n");
    gets(s->lastname);
    printf("Enter marks\n");
    for(i=0; i<5; i++)    
       scanf("%d", &s->marks[i]);
    printf("\n");
  }
nnidza
  • 1
  • 3
    You never initialize either pointer to point at valid, sufficient memory. Your `gets` calls invoked *undefined behavior* – UnholySheep Jan 03 '19 at 20:14
  • 2
    Also, [don't use `gets`](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used) – UnholySheep Jan 03 '19 at 20:15
  • Soooo, I should do...!? – nnidza Jan 03 '19 at 20:17
  • 1
    Either allocate sufficient memory and limit user input to not be more than what you have or do something like in https://stackoverflow.com/questions/16870485/how-can-i-read-an-input-string-of-unknown-length – UnholySheep Jan 03 '19 at 20:23
  • I understand, i think. Using malloc to allocate the memory, adding function for collectiing chars from the input and removing unwanted characters... All have to be in one... – nnidza Jan 03 '19 at 20:48
  • This is semantics, but `getS()` is a setter function and `setS()` is a getter function. Usually (at least in English) those function names would be switched around. – Reticulated Spline Jan 03 '19 at 20:59

1 Answers1

0

What is wrong with code? What am I doing wrong?

gets(s->name); attempts to read user input into s->name. s->name is a char * that has not yet been assigned. gets() attempts to save data to who-knows-where? Result: undefined behavior (UB).

Alternatives?

Read into a buffer and then allocated memory for a copy.

Tip: As you can, avoid scanf(), gets() for user input and use fgets(). C - scanf() vs gets() vs fgets().


Some code to provide an idea.

#define NAME_N 100

// return 1 on success
// return EOF on end-of-file
// return 0 other errors
int getS(Student *s) {
  *s = (Student) {NULL, NULL, {0}}; // pre-fill with default values.

  char buffer[NAME_N];
  printf("Enter name\n");
  if (fgets(buffer, sizeof buffer, stdin) == NULL) {
    return EOF;
  }
  trim(buffer);
  if (!validate_name(buffer)) {
    return 0;
  }
  s->name = strdup(buffer);

  printf("Enter last name\n");
  if (fgets(buffer, sizeof buffer, stdin) == NULL) {
    return EOF;
  }
  trim(buffer);
  if (!validate_name(buffer)) {
    return 0;
  }
  s->lastname = strdup(buffer);

  printf("Enter marks\n");
  for (int i = 0; i < 5; i++) {
    if (fgets(buffer, sizeof buffer, stdin) == NULL) {
      return EOF;
    }
    if (sscanf(buffer, "%d", &s->marks[i]) != 1) {
      return 0;
    }
  }
  return 1;
}

trim() is your function to trim leading/trailing/excessive white-spaces. See also How do I trim leading/trailing whitespace in a standard way?.

strdup() is not C standard yet very commonly available string duplication function that allocated memory and copies. Sample code

validate_name() is placeholder code to insure some sanity in the name. Be generous in what is acceptable. Commonly acceptable characters in a name include [A-Z, a-z, '-', ''', ' ', '.'] and many others: What are all of the allowable characters for people's names?.

Example:

// Fail a zero length name or one with controls characters in it.
bool validate_name(const char *name) {
  if (*name == '\0') return false;
  while (*name) {
    if (iscntrl((unsigned char) *name)) return false;
    name++;
  }
  return true;
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • Thanks a lot. I tried using a tmp string of a fixed size (buffer in your case) but I used strcpy function, plus gets... I like your way of handling data. I will try it out tommorow. Thanks a lot! – nnidza Jan 03 '19 at 22:22