Hello all,
I have a program that creates an array of structs. It is consistently exhibiting 1 of 2 problems and I can't figure out exactly what is wrong, but the problems seem related to each other.
Problem 1: For some reason the category member of the mediaItem struct fails to get assigned a value. Everytime I run the program, call the add function using the prompts, then call the list function -- all of the members display their value except category (which displays "null"). This is confusing because the other integer shows up fine and it is assigned using the same function.
Problem 2: Sometimes after adding an item, the program crashes with a segmentation fault when I call the list function, and it crashes on the line where it would display the category member of the mediaItem struct.
The program will usually exhibit one problem or the other if only 1 struct is in the array; if multiple structs are in the array it may produce both problems (showing null for the first item's category then crashing with a segmentation fault right before printing the second item's category).
Could someone look at my code and let me know what I'm doing wrong here? since it is a segmentation fault I am assuming I an not allocating memory correctly somehow, but I'm at a loss.
Thanks
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HLIMIT 120
#define MLIMIT 50
#define LLIMIT 6
#define DATE_SIZE 18
#define OPTIONS 4
#define NUM_CATS 7
//Media Map
//Author: KM
//
//Project 1
typedef struct mediaItem_ {
char doc[DATE_SIZE]; //date of creation
int size;
char desc[MLIMIT];
int category;
char location[HLIMIT];
char creator[MLIMIT];
} mediaItem;
mediaItem *items = NULL;
int num_items = 0;
int num_allocated = 0;
char *catArray[] ={"OS", "APP", "FILM", "MUSIC", "MUSIC VIDEO", "VIDEO GAME", "OTHER"};
//helper functions
//----------------
//void bad_selection(char *input); //declaration
void bad_selection(char *value){
if(value[0] == '\n')
printf("No selection detected. Please try again.\n");
else
printf("\n\'%s\' is not a valid response. Please try again.\n", value);
}
// addItems is an adaptation of the AddToArray function
// found at http://fydo.net/gamedev/dynamic-arrays
int addItems (mediaItem item){
if(num_items == num_allocated){
if(num_allocated == 0)
num_allocated = 8;
else
num_allocated += num_allocated/2;
void *_tmp = realloc(items, (num_allocated * sizeof(mediaItem)));
//error case
if(!_tmp){
fprintf(stderr,
"ERROR: Unable to allocate more memory for additonal items\n");
return(-1);
}
//success case
items = (mediaItem*)_tmp;
}
items[num_items++] = item;
return num_items;
}
int remItems(int itemNum){
if(num_items == 0 || itemNum >= num_items || itemNum < 0)
return -1;
if(itemNum < num_items -1){
int i = itemNum;
for(;i < num_items; ++i){
if(i < num_items - 1)
items[i] = items[i+1];
}
}
return --num_items;
}
void intro(){
printf("Hello and welcome to Media Map\n\n");
}
void bye(){
printf("\nThank you for using Media Map!\n\n");
}
void show_menu(){
printf("\nPlease select from the following choices:\n");
printf("1. List Media\n");
printf("2. Add Media\n");
printf("3. Delete Media\n");
printf("4. Exit\n");
}
void show_cats(){
int i;
printf("Choose number matching the category of the media\n");
for(i = 0; i < NUM_CATS; ++i)
printf("%d = %s\n", i, catArray[i]);
}
char* getString(char *string, int length){
fgets(string, length, stdin);
if (string[strlen(string) - 1] == '\n')
string[strlen(string) - 1] = '\0';
}
//set val < 0 to allow user to enter arbitrary positive int value
//set val = 0 to constrain user input to available OPTIONS
//set val = NUM_CATS to constrain user input to available categories
int getInt(int val){
int length = (val < 0 ? LLIMIT + 2: 3);
int num = -1;
char *input;
do{
if(val >= 0){
if(val > 0) show_cats();
else show_menu();
}
input = (char *) malloc(length);
getline(&input, &length, stdin);
if (input[strlen(input) - 1] == '\n')
input[strlen(input) - 1] = '\0';
if(sscanf(input, "%d", &num) == 1){
if(val > 0){
if(num >= val || num < 0)
bad_selection(input);
} else if(val == 0) {
if(num > OPTIONS || num < 1)
bad_selection(input);
}
} else {bad_selection(input);}
} while (val > 0 ? (num < 0 || num >= val) :
(val == 0 ? (num > OPTIONS || num < 1) : num < 0));
return num;
}
//selection functions
//-------------------
void list(){
printf("\nList Selected\n\n");
printf("########## LIST START ##########\n");
int i;
if(num_items == 0)
printf("There are no media items to list\n");
else {
for(i=0; i < num_items; ++i){
if(i == num_items){ break; }
mediaItem temp = items[i];
printf("***** START RECORD %d *****\n", i);
printf("Descript: %s\n", temp.desc);
printf("Location: %s\n", temp.location);
printf("Creator: %s\n", temp.creator);
printf("Category: %s\n", temp.category);
printf("Size: %dMB\n", temp.size);
printf("Created: %s\n", temp.doc);
printf("***** END RECORD %d *****\n", i);
}
}
printf("########## LIST END ##########\n");
}
void add(){
mediaItem *item;
if((item = (mediaItem *) malloc(sizeof(mediaItem))) == NULL){
printf("ERROR ALLOCATING MEMORY FOR NEW ITEM\n");
exit;
}
printf("\nAdd Selected\n\n");
printf("Enter the description of the media\n");
getString(item->desc, HLIMIT);
printf("Enter the location of the media\n");
getString(item->location, MLIMIT);
printf("Enter a creator for the media\n");
getString(item->creator, MLIMIT);
printf("Enter the size of the media (in MB)\n");
item->size = -1;
do{
item->size = getInt(-1);
if(item->size < 0)
printf("Size must be entered as an integer. Please try again.\n");
} while(item->size < 0);
printf("Enter the creation time of the media\n");
printf("YYYY/MM/DD HH:MM): ");
getString(item->doc, DATE_SIZE);
//get category info
item->category = getInt(NUM_CATS);
printf("\n");
addItems(*item);
free(item);
}
void del(){
int itemNum, result;
printf("\nDelete Selected\n\n");
printf("Enter the number of the item you wish to remove\n");
itemNum = getInt(-1);
if(remItems(itemNum) < 0)
printf("Invalid index selected.\n");
else
printf("Item deleted.\n");
printf("\n");
}
void exit_func(){
printf("\nExit Selected\n");
free(items);
}
//program
//-------
int main(){
int selection = 0;
while(selection != OPTIONS){
selection = getInt(0);
switch(selection){
case 1:
list(); break;
case 2:
add(); break;
case 3:
del(); break;
case OPTIONS:
exit_func(); break;
default:
printf("If you're seeing this, something went wrong!"); break;
}
}
bye();
return 0;
}