As Richard has already correctly pointed out, this line does not work:
gets(category);
Here you want to read in several lines. But the command obviously always overwrites the same place, and one that is not intended for that.
The gets() function has since been removed from C and C++ for good reason. There are almost the same problems as with scanf() with %s, since the string length cannot be limited. An alternative that reads only to the end of the line and at the same time respects the buffer size does not exist under C. If it absolutely must be C it becomes somewhat more complex, since one must write the desired function.
As said before, a function to read in a line with a limited buffer would have to be written by yourself if necessary:
int mygetline(char *buf, size_t len)
{
char ch;
for (int k = 0; (k <= len); ) {
ch = getchar();
if ((ch != '\r') && (ch != '\n')) {
buf[k] = ch;
k++;
}
else if (k>0) break;
}
if (ch != '\n') {
while (ch = getchar() != '\n'); return 1;
}
else
return 0;
}
Note: With C++ you could use getline() as an alternative.
When inserted into the (corrected) original program, it looks like this:
printf("Please mention the %d categories:\n", types);
for (i=0; i<types; i++) {
category[i] = (char*)calloc(types, (MAX_LINELEN + 1) * sizeof(char));
if (category[i] == NULL)
break;
printf("CATEGORY #%d:\n", i + 1);
mygetline(category[i], MAX_LINELEN);
}