4

I have defined a structure

struct subject
{
    char name[100];
    int year;
};

and since I need n of these and I have to use malloc I did the following in my main function:

int n, i;
scanf("%d", &n);
struct subject *ptr = malloc(n*sizeof(struct subject));

Unfortunately when I try to input something with this code:

for(i = 0; i < n; i++)
{
   gets((ptr + i)->name);
   scanf("%d", (ptr + i)->year);
}

It crashes after I type the first name. The task requires the use of malloc.

Here's the whole code (unfortunately it's in my native language so it's a little bit different)

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

#ifndef DEBUG
#define DEBUG(...)printf(_VA_ARGS_)
#endif

struct kolegij
{
    char naziv[100];
    int semestar;
};

int main(){
    int brPredmeta, i;

    scanf("%d", &brPredmeta);

    struct kolegij *ptr = malloc(brPredmeta*sizeof(struct kolegij));

    if(ptr == NULL)
    {
       printf("error\n");
       return 0;
    }

    for(i = 0; i < brPredmeta; i++)
    {
       //gets(ptr->naziv);
       gets((ptr + i)->naziv);
       scanf("%d", &(ptr + i)->semestar);
       getchar();
    }

    for(i = 0; i < brPredmeta; i++)
    {
       printf("%s\n", ptr[i].naziv);
       printf("%d\n", ptr[i].semestar);
    }

    return 0;
}

With regards to the duplicate issue. I believe this shouldn't be a duplicate since it's related to structs and pointers. I had issues with scanfs before and I haven't considered this as a solution so I think it shouldn't be flagged as a duplicate.

RidableCthulu
  • 471
  • 2
  • 17
  • 2
    Your second scanf needs a pointer to the variable you read into. Add a &. – Thomas Padron-McCarthy Apr 29 '15 at 19:31
  • Is being printed the second name? – Btc Sources Apr 29 '15 at 19:31
  • I added a & to the scanf but now it stops taking input after the first name and year and it prints out the following RANDOMNUMBER Subject Name Subject Year – RidableCthulu Apr 29 '15 at 19:34
  • The newline character from the ENTER key is in the input buffer. Simplest (but brittle) solution is to add a getchar(); after the scanf. – Thomas Padron-McCarthy Apr 29 '15 at 19:35
  • @ammoQ I have an if which checks that and it didn't return anything. – RidableCthulu Apr 29 '15 at 19:40
  • @ThomasPadron-McCarthy I tried getchar(); but it still doesn't work. It cuts the first letter of first name, I can input n-1 data and it still outputs a random number before everything. – RidableCthulu Apr 29 '15 at 19:40
  • `gets()`? You should be using `fgets()` instead, which is safer. – Jamal Apr 29 '15 at 19:41
  • @Jamal I tried with both functions, however in both cases it's the same. – RidableCthulu Apr 29 '15 at 19:41
  • It was a general note, which is why I didn't post it as an answer. – Jamal Apr 29 '15 at 19:43
  • You need to post a minimal, compilable program that still shows the problem. The code that prints your random number, etcetera, is missing, so we can only guess what's wrong. – Thomas Padron-McCarthy Apr 29 '15 at 19:43
  • @ThomasPadron-McCarthy I added the whole code now – RidableCthulu Apr 29 '15 at 19:48
  • @RidableCthulu Since you are allocating with `malloc` anyway, it would be simpler to just allocate `name` as well. Declare it as `char *name;` and then to fill it. just use `fgets (buf, BUFSIZE, stdin);`, then `ptr[i] = strdup (buf);`. Just don't forget to free it later. – David C. Rankin Apr 29 '15 at 19:52
  • You're missing a getchar(); after the first scanf too. The newline character from when you pressed the ENTER key after that number is left in the input buffer, and is read by gets as a (very short) line. – Thomas Padron-McCarthy Apr 29 '15 at 19:52
  • @ThomasPadron-McCarthy Thank you so much. I knew it had to be something with input. Did I mention I hate buffers in C? It is definitely the source of most of my problems in this subject. I never had any problems like this with C++. Thanks again! – RidableCthulu Apr 29 '15 at 19:54
  • 1
    possible duplicate of [C: Multiple scanf's, when I enter in a value for one scanf it skips the second scanf](http://stackoverflow.com/questions/9562218/c-multiple-scanfs-when-i-enter-in-a-value-for-one-scanf-it-skips-the-second-s) – Thomas Padron-McCarthy Apr 29 '15 at 19:57
  • @RidableCthulu, the use of buffers, dynamic or static, and a full understanding of pointers is one of the greatest strengths of C. While it may take a little effort learn, it is well worth the time spent. You want to change your outlook from **I hate buffers in C**, to **I love buffers in C**. You won't believe what a whole new world of programming will open up `:p` – David C. Rankin Apr 29 '15 at 20:20

2 Answers2

0

I believe the statement scanf("%d", (ptr + i)->year); to be responsible for your unstable behaviour, as you're passing an int where scanf expects an int *. Perhaps you meant something like scanf("%d", &(ptr + i)->year) (note the additional ampersand), though this also has perils associated. Namely, you're discarding the return value, so you can never be sure that the value stored will be sane. If the user enters invalid input, it might be best to re-prompt or exit:

int n;
do {
    puts("Enter year: ");
    n = scanf("%d", &(ptr + i)->year));
    scanf("%*[^\n]"); // more on this later
    getchar();
} while (n == 0);
if (n < 0) exit(EXIT_FAILURE);

As part of handling input is expecting the enter keystroke, we need to clear that before the next gets call, and I use scanf("%*[^\n]") followed by getchar() for that.

On the topic of the code which you presented near the end, that does indeed look very different. I notice you fixed the scanf type error (the additional ampersand), and you have getchar() after the scanf("%d", ...) so you won't usually get the trailing newline hanging around. I see no reason to be suspect of that (code at the end of your post); if you're concerned about a reason for closure, it appears that you don't have a problem anymore (we can't reproduce your crash)... I mean, aside from using gets; that's a minor problem, I guess (gets is deprecated; use fgets instead, trim the trailing '\n' and if there is none use scanf("%*[^\n]") followed by getchar() again to effectively truncate the input).

autistic
  • 1
  • 3
  • 35
  • 80
-6

Malloc returns a void pointer type. In order to use it as a pointer to your structure you have to cast it first. Try changing the line with malloc into:

int n, i;
scanf("%d", &n);
struct subject *ptr = (struct subject*) malloc(n*sizeof(struct subject));

You also have to change your input into:

for(i = 0; i < n; i++)
{
   gets((ptr + i)->name);
   scanf("%d", &((ptr + i)->year));
}
user2700896
  • 569
  • 1
  • 5
  • 14
  • 1
    This is double-wrong. First, it is not the cause of the problem, and second, this: http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – Thomas Padron-McCarthy Apr 29 '15 at 19:36