I am trying to make a C program to take in a list of movies and add to it with memory alloction and able to retrieve movies from the list as well using a txt file.
movies.txt
5
Mission Impossible
Action
4
2008
Up
Action
3
2012
I keep running into an error after running in the command line and when the menu comes up, whenever I input something it runs a seg fault. I don't have access to a debugger right now and I'm not exactly sure what's wrong although I assume its a problem with my pointers or memory alloc.
Can someone point me in the right direction?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// limit definition
#define LIMIT 999
//movie structure
struct movie
{
char name[100];
char type[30];
int rating;
int releaseDate;
};
//reads file
void readFile(FILE *fp,struct movie* movieList[],int *noOfReviews)
{
char buffer[100];
int counter = 0;
struct movie* newNode;
fgets(buffer,LIMIT,fp);
*noOfReviews = atoi(buffer); // number of reviews in buffer
printf("%d",*noOfReviews); //prints reviews
while((fgets(buffer,LIMIT,fp)!=NULL) || (*noOfReviews > 0)) //if null or reviews greater than zero
{
if(counter % 4 == 0)
{
struct movie* tmpNode = (struct movie*)malloc(sizeof(struct movie)); //allocates memory
movieList[counter] = tmpNode;
newNode = tmpNode;
*noOfReviews--; // --#ofreviews
}
//copys struc into buffer
switch(counter % 4 )
{
case 0:
strcpy(newNode->name,buffer);
break;
case 1:
strcpy(newNode->type,buffer);
break;
case 2:
newNode->rating = atoi(buffer);
break;
case 3:
newNode->releaseDate = atoi(buffer);
break;
default:
printf("Exception\n");
break;
}
counter++;
}
}
//searches list
int searchList(struct movie* movielist[],char movieName[],int noOfMovies)
{
int counter = 0;
while(noOfMovies--)
{
if(strcmp(movielist[counter]->name,movieName) == 0) // if string compares to name
{
return counter;
}
counter++;
}
return -1;
}
//compares strings of name
int nameStrCmp(const void *a, const void *b)
{
return (strcmp(((struct movie*)a)->name,((struct movie*)b)->name));
}
// compares rating strings
int ratingStrCmp(const void * a, const void * b)
{
return (((struct movie*)a)->rating - ((struct movie*)b)->rating);
}
//displays the structure
void display(struct movie* movieList[],int n)
{
int i;
struct movie* searchRslt;
for(i = 0; i < n; i++)
{
searchRslt = movieList[i];// search result index of movies list
//prints struct information
printf("name:%s\n type:%s\n rating:%d\n releaseDate:%d\n",searchRslt->name,searchRslt->type,searchRslt->rating,searchRslt->releaseDate);
}
}
//main function
int main(int argc, char *argv[])
{
char buffer[100];
int noOfReviews;
struct movie* movieList[1000];
struct movie *searchRslt;
char mName[100];
if(argc <= 1)
{
printf("invalid");
return 0;
}
FILE *fp = fopen(argv[1],"r");
readFile(fp,movieList,&noOfReviews);
while(1)
{
//case selection menu
int input;
printf("Enter 1 to search for a movie.\n");
printf("Enter 2 to display the list of movies by name.\n");
printf("Enter 3 to display the list of movies by rating.\n");
scanf("%d",&input);
switch(input)
{
case 1:
printf("Enter movie name to search:");
scanf("%s",mName);
int index = searchList(movieList,mName,noOfReviews);
if(index < 0)
printf("Not found!!\n"); // if movie not found
else // gets movies
{
searchRslt = movieList[index];
printf("name:%s\n type:%s\n rating:%d\n releaseDate:%d\n",searchRslt->name,searchRslt->type,searchRslt->rating,searchRslt->releaseDate);
}
break;
case 2:
qsort(movieList,noOfReviews,sizeof(struct movie),nameStrCmp);
display(movieList,noOfReviews);
break;
case 3:
qsort(movieList,noOfReviews,sizeof(struct movie),ratingStrCmp);
display(movieList,noOfReviews);
break;
default:
break;
}
}
}
A few formatting/readability/coding suggestions: (Some are just suggestions, others actually eliminate warnings.)
format. (mainly indention)
replace 'struct movie' with MOVIE everywhere. (see struct definition below)
initialize variables before use.
pay attention to buffer size in declaration and usage (fgets errors)
Compile with warnings on. (eg, with gcc use -Wall)
The following is limited to addressing each of these items, including new struct definition. The following compiles and builds without warnings or errors. It does not include debugging your code. (If can do a Beyond Compare (its free), between your original post and the edited version below, you can easily find where the edits are.)
(At the time of this post, there was no information provided about your input file, so further efforts were not made.)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// limit definition
#define LIMIT 999
//movie structure
typedef struct {
char name[100];
char type[30];
int rating;
int releaseDate;
}MOVIE;
//reads file
void readFile(FILE *fp,MOVIE* movieList[],int *noOfReviews)
{
char buffer[LIMIT];
int counter = 0;
MOVIE* newNode = {0};
fgets(buffer,LIMIT,fp);
*noOfReviews = atoi(buffer); // number of reviews in buffer
printf("%d",*noOfReviews); //prints reviews
while((fgets(buffer,LIMIT,fp)!=NULL) || (*noOfReviews > 0)) //if null or reviews greater than zero
{
if(counter % 4 == 0)
{
MOVIE* tmpNode = (MOVIE *)malloc(sizeof(MOVIE)); //allocates memory
movieList[counter] = tmpNode;
newNode = tmpNode;
*noOfReviews--; // --#ofreviews
}
//copys struc into buffer
switch(counter % 4 ) {
case 0:
strcpy(newNode->name,buffer);
break;
case 1:
strcpy(newNode->type,buffer);
break;
case 2:
newNode->rating = atoi(buffer);
break;
case 3:
newNode->releaseDate = atoi(buffer);
break;
default:
printf("Exception\n");
break;
}
counter++;
}
}
//searches list
int searchList(MOVIE* movielist[],char movieName[],int noOfMovies)
{
int counter = 0;
while(noOfMovies--)
{
if(strcmp(movielist[counter]->name,movieName) == 0) // if string compares to name
{
return counter;
}
counter++;
}
return -1;
}
//compares strings of name
int nameStrCmp(const void *a, const void *b)
{
return (strcmp(((MOVIE*)a)->name,((MOVIE*)b)->name));
}
// compares rating strings
int ratingStrCmp(const void * a, const void * b)
{
return (((MOVIE*)a)->rating - ((MOVIE*)b)->rating);
}
//displays the structure
void display(MOVIE* movieList[],int n)
{
int i;
MOVIE* searchRslt;
for(i = 0; i < n; i++)
{
searchRslt = movieList[i];// search result index of movies list
//prints struct information
printf("name:%s\n type:%s\n rating:%d\n releaseDate:%d\n",searchRslt->name,searchRslt->type,searchRslt->rating,searchRslt->releaseDate);
}
}
//main function
int main(int argc, char *argv[])
{
int noOfReviews;
MOVIE* movieList[1000];
MOVIE *searchRslt;
char mName[100];
if(argc <= 1)
{
printf("invalid");
return 0;
}
FILE *fp = fopen(argv[1],"r");
readFile(fp,movieList,&noOfReviews);
while(1)
{
//case selection menu
int input;
printf("Enter 1 to search for a movie.\n");
printf("Enter 2 to display the list of movies by name.\n");
printf("Enter 3 to display the list of movies by rating.\n");
scanf("%d",&input);
switch(input)
{
case 1:
printf("Enter movie name to search:");
scanf("%s",mName);
int index = searchList(movieList,mName,noOfReviews);
if(index < 0)
printf("Not found!!\n"); // if movie not found
else // gets movies
{
searchRslt = movieList[index];
printf("name:%s\n type:%s\n rating:%d\n releaseDate:%d\n",searchRslt->name,searchRslt->type,searchRslt->rating,searchRslt->releaseDate);
}
break;
case 2:
qsort(movieList,noOfReviews,sizeof(MOVIE),nameStrCmp);
display(movieList,noOfReviews);
break;
case 3:
qsort(movieList,noOfReviews,sizeof(MOVIE),ratingStrCmp);
display(movieList,noOfReviews);
break;
default:
break;
}
}
}
Related
I'm learning about disjoint dynamic memory, so I'm trying to make my own program. I need someone to help me see my problems and show me how to fix them.
I'm almost done with my program, but still have some problems in my program.
My problem:
my saveData() function and reload() function do not work correctly.
I'm not sure whether the saveData() function does get all the data I need
my reload() function just output it has brought back data from the bin file (in saveData() function) and then exit program with some weird code (ex: 8500241654)
Without the above problem, my program works well. Please check the 3 problems in my program in .h file and .c file
C Program Description:
"You will write a program that will store the information about automobiles. The information is about make, mode, yearBuilt, and cost (use struct). The user will choose from menu what they want to do (add auto, display auto with orders of cost or make, use switch).
When the program begins, if there was a previous data file of automobile information it will be loaded automatically. The program will begin where the user last left off. If there is no previous data file, then the program will ask the user how many automobiles record will be needed and the program will start fresh.
When the program ends, all data will be saved to a bin file. All memory will be released from the heap. "
P/s: thank you so much, and appreciate your help.
<Here is my .h file>
// FUNCTION PROTOTYPES
typedef struct {
char make[50]; // ex: Ford, Honda, Toyota
char model[50]; // ex: Corolla, Camry
int yearBuilt; // ex: 2001, 2022
int cost; // ex: 20500, 8999, 15000
} AUTOMOBILE; // 108 bytes
void addAuto(AUTOMOBILE* a[], int* eSize, int size);
int compareChars(const void* a, const void* b);
void displayAuto(AUTOMOBILE* autos[], int eSize);
void displayMenu();
void freeMemory(AUTOMOBILE* autos[], int size);
int getInt(char m[]);
int getCh(char m[]);
void quitProgram(int* temp);
AUTOMOBILE** reload(AUTOMOBILE* a[], int* eSize, int* size);
void saveData(AUTOMOBILE *a[], int eSize, int size);
void sortByCost(AUTOMOBILE* autos[], int eSize);
void sortByMake(AUTOMOBILE* autos[], int eSize);
// FUNCTIONS
void addAuto (AUTOMOBILE *a[], int* eSize, int size) {
char again = 'N';
char autoMake[50];
char autoModel[50];
do {
if (*eSize == size) {
printf("No room to add more automobile...it is full!\n");
system("pause");
return;
}
printf("\nAdding a new automobile to the array of items\n");
// add make
printf("What is the automobile's make (uppercase first letter, ex: Honda)? ");
scanf("%s", a[*eSize]->make);
// add model
printf("What is the automobile's model (uppercase first letter, ex: Camry)? ");
scanf("%s", a[*eSize]->model);
// add year built
a[*eSize]->yearBuilt = getInt("When was the automobile built (ex: 2022)? ");
// add cost
a[*eSize]->cost = getInt("How much does the automobile cost (ex: 45500)? ");
*eSize += 1;
printf("\nWould you like to add another item? [Y/N]: ");
scanf(" %c", &again);
} while (toupper(again) == 'Y');
} // end addAuto
int compareChars(const void* a, const void* b) {
const char* arg1 = *(const char**) a;
const char* arg2 = *(const char**) b;
return strcmp(arg1, arg2);
} // end compareChars
void displayAuto(AUTOMOBILE *autos[], int eSize) {
char option;
printf("\nChoose your desired order");
printf("\n[C]ost low to high");
printf("\n[M]ake ascending order");
option = getCh("\nEnter option: ");
if (option == 'C' || option == 'c')
sortByCost(autos, eSize);
else if (option == 'M' || option == 'm')
sortByMake(autos, eSize);
} // end displayAuto
void displayMenu() {
printf("\n[A]dd one automobile");
printf("\n[D]isplay all automobiles by");
printf("\n\t[C]ost low to high");
printf("\n\t[M]ake ascending order"); // ascending order: A-Z
printf("\n[Q]uit program\n");
} // end displayMenu
void freeMemory(AUTOMOBILE* autos[], int size) {
for (int i = 0; i < size; i++) {
free(autos[i]);
}
free(autos);
} // end freeMemory
int getCh(char m[]) {
char result;
char badValue = 'F';
// loop until get integer value
do {
badValue = 'F';
printf("%s", m);
scanf(" %c", &result);
// if "result" isn't an alphabet, do the loop again
if (isalpha(result) == 0) {
printf("\nYou must enter a valid character!\n");
badValue = 'T';
} // end If
} while (badValue == 'T');
return result;
} // end getCh
int getInt(char m[]) {
int result = 0;
char badValue = 'F';
// loop until get integer value
do {
badValue = 'F';
printf("%s", m);
if (scanf("%i", &result) != 1) {
printf("\nYou must enter a valid real numeric value!\n");
badValue = 'T';
} // end If
} while (badValue == 'T');
return result;
} // end getInt
void quitProgram(int *temp) {
printf("\nThank you for using program!\n");
*temp = 1;
} // end quitProgram
AUTOMOBILE** reload(AUTOMOBILE* a[], int* eSize, int* size) {
*eSize = 0;
FILE* fp = fopen("binaryDocument.bin", "rb");
if (fp == NULL) {
printf("\nNo information has been reload!\n");
system("pause");
return a;
} // end if
printf("\nI have brought back the previous saved data into the array!\n");
system("pause");
// get the size
fread(size, sizeof(int), 1, fp);
// memory allocation for [size] pointers, [size] * 4 bytes of space
// use the size to allocate the space for the pointer array
a = calloc(*size, sizeof(AUTOMOBILE*));
if (a == NULL) {
printf("Allocation of memory failed...\n");
exit(-1);
}
// go through each one of them, and allocate 108 bytes each and allow these pointers to refer to it
for (int i = 0; i < size; i++) {
a[i] = calloc(1, sizeof(AUTOMOBILE));
if (a[i] == NULL) {
printf("Allocation of memory at autos[%i] failed...\n", i);
exit(-1);
}
}
// get the eSize and use the eSize to reload the array
fread(eSize, sizeof(int), 1, fp);
fread(a, sizeof(AUTOMOBILE*), *eSize, fp);
fclose(fp);
return a;
} // end reload
void saveData(AUTOMOBILE *a[], int eSize, int size) { // PROBLEM HERE
FILE* fp = fopen("binaryDocument.bin", "wb");
if (fp == NULL) {
printf("\nCould not save the information to a binary file\n");
system("pause");
return;
} // end if
fwrite(&size, sizeof(int), 1, fp);
fwrite(&eSize, sizeof(int), 1, fp);
fwrite(a, sizeof(AUTOMOBILE*), eSize, fp);
fclose(fp);
} // end saveData
void sortByCost(AUTOMOBILE *autos[], int eSize) {
int temp = 0;
int autoCost[1000];
for (int i = 0; i < eSize; i++) {
autoCost[i] = autos[i]->cost;
}
for (int i = 0; i < eSize; ++i) {
for (int j = i + 1; j < eSize; ++j) {
if (autoCost[i] > autoCost[j]) {
temp = autoCost[i];
autoCost[i] = autoCost[j];
autoCost[j] = temp;
}
}
}
printf("\nAutomobiles are displayed from low to high in term of cost: \n");
for (int l = 0; l < eSize; l++) {
for (int k = 0; k < eSize; k++) {
if(autoCost[l] == autos[k]->cost)
printf("%i\t%s\t%s\t%i\n", autoCost[l], autos[k]->make, autos[k]->model, autos[k]->yearBuilt);
}
}
} // end sortByCost
void sortByMake(AUTOMOBILE *autos[], int eSize) {
qsort(autos, eSize, sizeof(AUTOMOBILE*), compareChars);
printf("\nAutomobiles are displayed A-Z: \n");
for (int i = 0; i < eSize; i++) {
printf("%s\t%s\t%i\t%i\n", autos[i]->make, autos[i]->model, autos[i]->yearBuilt, autos[i]->cost);
}
} // end sortByMake
<Here is my .c file>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "DJDMHeader.h"
//****************************************************
// MAIN FUNCTION
int main() {
int size = 0;
int eSize = 0;
AUTOMOBILE** autos = NULL; // create the variable to make the array of automobile pointers
int i, temp = 0;
char choice;
// reload data
autos = reload(autos, &eSize, &size);
// case: nothing to reload, start fresh
if (size == 0) {
// get integer value for variable size
size = getInt("How many automobiles will you have at the most: ");
// memory allocation for [size] pointers, [size] * 4 bytes of space
autos = calloc(size, sizeof(AUTOMOBILE*));
if (autos == NULL) {
printf("Allocation of memory failed...\n");
exit(-1);
}
// go through each one of them, and allocate 108 bytes each and allow these pointers to refer to it
for (i = 0; i < size; i++) {
autos[i] = calloc(1, sizeof(AUTOMOBILE));
if (autos[i] == NULL) {
printf("Allocation of memory at autos[%i] failed...\n", i);
exit(-1);
}
}
}
while (temp == 0) {
displayMenu();
choice = getCh("What is your choice?: ");
// switch
switch (choice) {
case 'a':
case 'A':
addAuto(autos, &eSize, size);
break;
case 'd':
case 'D':
displayAuto(autos, eSize);
break;
case 'q':
case 'Q':
quitProgram(&temp);
break;
default:
printf("\nPlease choose the existed choices!\n");
}
}
// Save data
saveData(autos, eSize, size);
// Free memory
freeMemory(autos, size);
return 0;
}
If anything about my program or my question make you unhappy (or something like that), please tell me, I will edit again. So much thanks.
You either operate on an array:
#include <stdio.h>
typedef struct {
char make[50]; // ex: Ford, Honda, Toyota
char model[50]; // ex: Corolla, Camry
int yearBuilt; // ex: 2001, 2022
int cost; // ex: 20500, 8999, 15000
} AUTOMOBILE;
// array
void saveData(AUTOMOBILE *a, int eSize, int size) {
FILE *fp = fopen("binaryDocument.bin", "wb");
if (!fp) {
printf("\nCould not save the information to a binary file\n");
return;
}
fwrite(&size, sizeof(int), 1, fp);
fwrite(&eSize, sizeof(int), 1, fp);
fwrite(a, sizeof(*a), eSize, fp);
fclose(fp);
}
int main() {
AUTOMOBILE a[] = {
{ "Ford", "Model T", 1908, 1000 },
{ "Honda", "Accord", 2022, 20000 }
};
saveData(a, sizeof(a) / sizeof(*a), 42);
}
or as an array of pointers:
#include <stdio.h>
typedef struct {
char make[50]; // ex: Ford, Honda, Toyota
char model[50]; // ex: Corolla, Camry
int yearBuilt; // ex: 2001, 2022
int cost; // ex: 20500, 8999, 15000
} AUTOMOBILE; // 108 bytes
// array of pointers
void saveData(AUTOMOBILE *a[], int eSize, int size) {
FILE *fp = fopen("binaryDocument.bin", "wb");
if (!fp) {
printf("\nCould not save the information to a binary file\n");
return;
}
fwrite(&size, sizeof(int), 1, fp);
fwrite(&eSize, sizeof(int), 1, fp);
for(unsigned i = 0; i < eSize; i++) {
fwrite(a[i], sizeof(**a), 1, fp);
}
fclose(fp);
}
int main() {
AUTOMOBILE *a[] = {
&(AUTOMOBILE) { "Ford", "Model T", 1908, 1000 },
&(AUTOMOBILE) { "Honda", "Accord", 2022, 20000 }
};
saveData(a, sizeof(a) / sizeof(*a), 42);
}
What you call size is usually referred to as max_size or capacity. eSize vs size is confusing. In either case, size is an artifact of your in memory representation so you don't need to persist that.
Prefer unsigned types when the value cannot be negative.
Types (AUTOMOBILE) are not by convention upper case (which is used for constants like enums and defined symbols).
I am new to programming and would like some help in for File in C.
This is my code
#include <stdio.h>
#include <string.h>
void read_file();
void write_fil();
void add();
void display();
void search();
#define NAME_CHRS 30
struct employee_rec
{ char name[NAME_CHRS];
int dependents;
float pay_rate;
};
struct employee_rec employee;
struct employee_rec emp_array[];
FILE *employ;
int count=-1;
void read_file(void)
{
int idx;
employ = fopen("EMPLOYEE.DAT", "a+");//i add
//for (idx=0; idx <= count; idx++)
fread(&emp_array[idx], sizeof emp_array[idx], 1, employ);
fclose(employ);
}
void write_file()
{
int x;
employ = fopen("EMPLOYEE.DAT", "a+");
for (x=0; x <= count; x++)
fwrite(&emp_array[x], sizeof emp_array[x], 1, employ);
fclose(employ);
}
void add()
{
count+=1;
printf("Enter name: ");
scanf("%s", emp_array[count].name);
printf("Pay rate, other dependents: ");
scanf("%f %i", &emp_array[count].pay_rate, &emp_array[count].dependents);
}
void display()
{
int idx;
read_file();
printf("Name\t\tPay Rate\tDependents\n");
printf("----\t\t--------\t----------\n");
for (idx=0; idx <= count; idx++)
{
printf("%-10s\t%-8g\t%-8d\n", emp_array[idx].name, emp_array[idx].pay_rate, emp_array[idx].dependents);
}
}
void search()
{
char target[20];
int idx, found=0;
printf("Enter a name to search: ");
scanf("%s", target);
for (idx=0; idx <= count; idx++){
if(strcmp(emp_array[idx].name, target) == 0)
{
found = 1;
break;
}
}
if(found == 1)
{
printf("Name: %s\n", emp_array[idx].name);
printf("Pay rate: %g\n", emp_array[idx].pay_rate);
printf("Dependents: %d\n", emp_array[idx].dependents);
}
else
printf("Not found!\n");
}
int main(void)
{
int i;
//for (i=0; i < 3; i++)
// add();
// write_file();
display();
search();
return 0;
}
The original program would ask the user to key in data and then display it for the user.
So when another user runs the program and has the file it doesnt need to add more data but just read from the file
I have commented the for loop, display and search in my main because i just want to retrieve the data from my file.
Im not sure what to do with
fread(&emp_array[idx], sizeof emp_array[idx], 1, employ);
fclose(employ);
Since right now im using the counter from the insert to get the size, it will say size is 0 as the current run did not enter the data into the file (file already has data).
Is there any other way I can get all my data from the file without inserting it in the same run?
EDIT: So as some of the comments have mentioned the size of emp_arry is empty. I would like to get the size from a file. Since the file as a array inside which i want to transfer the data to emp_array.
One simple solution is to design a file header which includes the number of data in this file. Then, you can first read file header to get the number and then dynamically allocate memory to read data from file.
int main(int argc, char *argv[])
{
MYAPP MyApp;
MyApp = (struct MyApp*)malloc(sizeof(struct MyApp));
MyApp->maxMovieYear = 0;
MyApp->maxMovieNum = 0;
MyApp->myYearTree = CreateTreeYear();
MyApp->myTree = CreateTree();
MyApp = read_data(argv,MyApp);
int exit=FALSE;
int command;
char title[256];
int year;
int imdbID;
char posterlink[512];
printf(">>>Welcome to Movie Analysis at IMDB<<< \n");
while (!exit)
{
printf("\n-Menu-\n\
1. Display the full index of movies\n\
2. Display the movies where their title contains a specific keyword\n\
3. Display the year with maximum number of movies\n\
4. Exit\n\
Option:");
if(MyApp == NULL){
exit = TRUE;
printf("\nCannot locate the file!");
break;
}
YearWithMostMovies(MyApp->myYearTree ,MyApp);
scanf("%d", &command);
fflush(stdin);
char searchSong[512];
switch (command)
{
case 1:
printf("Movie Index\n-------------\n");
display_index(MyApp->myTree);
break;
case 2:
printf("Please enter the movie you want to see: ");
scanf("%s",searchSong);
display_movies_keyword(MyApp->myTree,searchSong);
break;
case 3:
most_popular_year_movies(MyApp);
break;
case 4:
exit = TRUE;
break;
default:
printf("command not recognized\n");
break;
}
}
printf("\n");
return 0;
}
MYAPP read_data(char *argv[],MYAPP MyApp){
FILE *outfile = fopen(argv[1],"r");
AVLTree newNode = NULL;
if(outfile == NULL)
{
printf("File does not exist...\n");
return NULL;
}
int delimiterCount = 0;
char inputData[2001];
while((fgets(inputData,2001,outfile)) != NULL)
{
int len = strlen(inputData);
if (len >= 0 && inputData[len-1] == '\n')
inputData[--len] = '\0';
AVLTree temp = NULL;
//initialize the newNode
temp = (struct tree*)malloc(sizeof(struct tree));
temp->height = 0;
temp->left = NULL;
temp->right = NULL;
char* token = strtok(inputData, ",");
strcpy(temp->title,token);
while (token != NULL)
{
token = strtok(NULL, ",");//reading the rest of the tokens with strtok
delimiterCount++;
switch (delimiterCount) // this switch orders the tokens by their places
{
case 1:
strcpy(temp->year,token);
break;
case 2:
strcpy(temp->imdbID,token);
break;
case 3:
strcpy(temp->posterlink,token);
break;
}
}
newNode = temp;
MyApp->myTree = InsertElement(newNode,MyApp->myTree);
int x = atoi(newNode->year);
MyApp->myYearTree = InsertElementYear(x,MyApp->myYearTree);
delimiterCount = 0;
}
fclose(outfile);
return MyApp;
}
My struct definitions are:
typedef struct tree * AVLTree;
typedef struct year *AVLYear;[enter image description here][1]
struct tree{
char title[512];
char posterlink[1024];
char imdbID[512];
char year[512];
struct tree* left;
struct tree* right;
int height;
};
struct MyApp{
AVLTree myTree;
AVLYear myYearTree;
int maxMovieYear;
int maxMovieNum;
};
typedef struct MyApp* MYAPP;
typedef struct year *AVLYear;
struct year
{
int year;
int num;
AVLYear left;
AVLYear right;
int height;
};
when i am trying to get filename as argument fopen returns me this
**<msvcrt!_iob+96>**
what might be causing this problem?
my aim is to get the data from a file and put it in 2 different avltree's, i keep my trees in another struct called MYAPP to pass between functions easily. can it be the problem?
i could not see the cause of this error.
Edit: i am using my own header files for struct definitions and functions. also including:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "AVLTree.h"
#include "AVLYear.h"
thanks.
It seems you are running the program in your debugger. When you come at the fopen statement/call, the debugger shows you what fopen returned.
remember that fopen returns zero upon error, or a pointer to an open file structure. Since it does not return zero, it must have returned a pointer.
But your debugger wants to tell you where it is pointing to, and that is to the symbol msvcrt!_iob offset with 96 bytes. The seems like a valid structure, iob meaning something like "I/O buffer", or whatever the Microsoft programmer intended for that abreviation.
Conclusion: there is no error.
How can I solve this problem given to us in our lab test? I have tried manier times but failed. I have started learning C since 2 months.
Q:
Read a file named food.txt during execution of your program to store all these items and their respective prices in an array of structure item.
Note: 'struct item' contains 'char name' and 'int price'.
Also, first line of food.txt gives number of entries.
(command: ./a.out < food.txt).
Edit: This is my code. I can't find my mistake.
#include<stdio.h>
//Defining the struct
typedef struct {
char name[25];
int price;
}item;
int main(){
int n; //Number of entries
int i,j,k,flag;
int temp[40];
scanf("%d",&n);//first line gives number of entries as input
item items[n]; //creating our items struct
int c = getchar();
for(i=0;i<n;i++){
items[i].price=0;
for(j=0;;j++){
c=getchar();
if(c<'0' || c>'9') items[i].name[j]=c; //If c is character, it store it in name
if(c=='\n')break; //If c is \n, it breaks from the loop and starts again with i++
temp[j]=c;
}
for(j=0;;j++){
if(temp[j]>=0 && temp[j]<=9){
items[i].price = (items[i].price)*10 + temp[j];
}
else if(temp[j]=='\n')break;
}
}
printf("\n.........................................\n");
for(i=0;i<n;i++){
printf("%d. %s %d \n",i+1,items[i].name,items[i].price);
}
}
food.txt
8
hot black tea 5
hot lemon tea 6
hot masala tea 7
hot milk tea 9
hot black coffee 7
hot milk coffee 10
finger potato 45
potato chips 35
Here is an minimal example for understanding how to approach this problem statement:
#include<stdio.h>
#define MAX 100
struct node
{
char name[MAX];
int price;
};
int main(void)
{
int inp;
int count_char=0; //COUNTS THE NUMBER OF CHARACTERS OF A NAME
int count_arr=0; //COUNTS THE NUMBER OF SEPARATE NAME-PRICE STRUCTURES USED
struct node EMPTY={{'\0'},0}; //EMPTY STRUCTURE FOR DEFAULT INITIALIZATION
struct node arr[]={[0 ... 99]=EMPTY}; //ARRAY OF STRUCTURES CONTANING 100 ELEMENTS
int temp_count=0;
int count_space=0; //COUNT NUMBER OF SPACES WITHIN THE STRING
while((inp=getchar())!=EOF)
{
if(inp=='\n')
{
count_space=0;
count_arr++;
count_char=0;
continue;
}
if((((inp>='A')&&(inp<='Z'))||((inp>='a')&&(inp<='z')))||(inp==' '))
{
if((count_char==0)&&(inp==' ')) //LEADING SPACE HANDLING
{
continue;
}
if(inp==' ') //SPACE WITHIN STRINGS HANDLING
{
++count_space;
}
else
count_space=0;
if(count_space>1)
continue;
arr[count_arr].name[count_char++]=inp;
}
if((inp>='0')&&(inp<='9'))
{
arr[count_arr].price = (arr[count_arr].price)*10 + inp - '0';
}
}
while(temp_count<count_arr)
{
printf("%s",arr[temp_count].name);
printf("%d\n",arr[temp_count++].price);
}
return 0;
}
If the file contains:
INPUT:
3
xyz 123
abc 89
lmn tub 956
OUTPUT:
xyz 123
abc 89
lmn tub 956
NOTE: There can be tons of things done to streamline this example but this is only a minimal demo.
You can take advantage of the fgets() and sscanf() functions found in stdio.h. This gives the ability to scan the same line of input repeatedly when unexpected input arises, and is generally a better option than using scanf() alone.
In the code below, the line[] array is used to hold the contents of each line of input. This has been made large enough to hold any reasonably sized line, but fgets() ensures that unexpected input will not cause a buffer overflow. More robust code would check for such large inputs anyway, which would cause problems with the remaining input. Note also that the name[] field of the item structure has been enlarged from 25 to 256; there is no reason to be stingy here.
The fgets() function is used to get the first line of input, and if no line is retrieved, or if the first line is non-numeric, an error message is printed to stderr and the program exits with a value of -1.
Then the fgets() function is used again in a loop to read lines of input which are parsed by sscanf(). Here a scanset is used to scan the input line[] and assign to the .name field; it is assumed that the food name contains no numbers. Also note that the .name field will contain any non-numeric characters found before the first digit, so any spaces found before the price will be included in the .name string. These spaces could be trimmed, if desired. Before parsing with sscanf(), the code checks to see if the input line[] is blank, i.e., if the first character is a newline character; if so, the item counter i is decremented, and the loop is continued, skipping any blank lines in the input.
Finally, the contents of the items[] array are displayed for verification.
#include <stdio.h>
struct item {
char name[256];
int price;
};
int main(void)
{
int num_entries; // number of entries, not number of lines
char line[512]; // storage for input lines
if (fgets(line, sizeof line, stdin) == NULL) {
fprintf(stderr, "Empty input file\n");
return -1;
}
if (sscanf(line, "%d", &num_entries) != 1) {
fprintf(stderr, "Formatting error in first line\n");
return -1;
}
struct item items[num_entries];
for (int i = 0; i < num_entries; i++) {
if (fgets(line, sizeof line, stdin) == NULL) {
fprintf(stderr, "Inconsistent file length\n");
return -1;
}
// Do not count blank lines
if (line[0] == '\n') {
--i;
continue;
}
// Assign to struct
if (sscanf(line,
"%255[^0123456789]%d",
items[i].name, &items[i].price) != 2) {
fprintf(stderr, "Formatting error in entry %d\n", i + 1);
return -1;
}
}
// Display contents of array
for (int i = 0; i < num_entries; i++) {
printf("Item %d: %s, $%d\n", i + 1, items[i].name, items[i].price);
}
return 0;
}
Sample interaction:
>$ ./a.out < food.txt
Item 1: hot black tea , $5
Item 2: hot lemon tea , $6
Item 3: hot masala tea , $7
Item 4: hot milk tea , $9
Item 5: hot black coffee , $7
Item 6: hot milk coffee , $10
Item 7: finger potato , $45
Item 8: potato chips , $35
*scnr*:
#include <stddef.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define STRING(x) #x
#define STRINGIFY(x) STRING(x)
#define MAX_ITEM_NAME_LENGTH 100
typedef struct item_tag {
char *name;
int price;
} item_t;
item_t item_create()
{
item_t new_item = { NULL, 0 };
return new_item;
}
bool item_read(item_t *item)
{
char name[MAX_ITEM_NAME_LENGTH + 1];
int price;
if (scanf(" %" STRINGIFY(MAX_ITEM_NAME_LENGTH) "[^0-9]%d%*[\n]", name, &price) != 2)
return false;
size_t name_length = strlen(name);
if (name_length && isspace((int)name[name_length - 1]))
name[--name_length] = '\0';
item->name = malloc(strlen(name) + 1);
strcpy(item->name, name);
item->price = price;
return true;
}
void item_print(item_t *item, size_t longest_name_length)
{
printf("%-*s %4d\n", (int)longest_name_length, item->name, item->price);
}
void item_destroy(item_t *item)
{
free(item->name);
}
typedef struct products_list_tag {
size_t size;
item_t *items;
size_t longest_name_length;
} products_list_t;
products_list_t products_list_create(void)
{
products_list_t new_products_list = { 0, NULL, 0 };
return new_products_list;
}
bool products_list_read(products_list_t *products_list)
{
size_t num_items;
if (scanf(" %zu%*[\n]", &num_items) != 1)
return false;
else if (!num_items)
return true;
item_t *new_items = calloc(num_items, sizeof *new_items);
size_t num_valid_items = 0;
size_t longest_name_length = 0;
for (size_t i = 0; i < num_items && !feof(stdin); ++i) {
new_items[i] = item_create();
if (!item_read(&new_items[i]))
--i;
else {
++num_valid_items;
size_t name_length = strlen(new_items[i].name);
if (longest_name_length < name_length)
longest_name_length = name_length;
}
}
if (num_valid_items != num_items) {
free(new_items);
return false;
}
new_items = realloc(new_items, num_valid_items * sizeof *new_items);
products_list->items = new_items;
products_list->size = num_valid_items;
products_list->longest_name_length = longest_name_length;
return true;
}
void products_list_print(products_list_t *products_list)
{
for (size_t i = 0; i < products_list->size; ++i)
item_print(&products_list->items[i], products_list->longest_name_length);
}
void products_list_destroy(products_list_t *products_list)
{
for (size_t i = 0; i < products_list->size; ++i)
item_destroy(&products_list->items[i]);
free(products_list->items);
products_list->size = 0;
}
int main(void)
{
products_list_t products = products_list_create();
if (!products_list_read(&products)) {
perror("Failed to read products list!\n\n");
products_list_destroy(&products);
return EXIT_FAILURE;
}
products_list_print(&products);
products_list_destroy(&products);
}
Update:
Just read about a stupid no-other-headers-than-<stdio.h> restriction in a comment on a temporarily deleted, now resored answer.
#include <stdio.h>
#define STRING(x) #x
#define STRINGIFY(x) STRING(x)
#define MAX_ITEM_NAME_LENGTH 100
#define MAX_PRODUCTS_LIST_ITEMS_COUNT 100
/* BEGIN stupid no-other-headers-than-<stdio.h> workaround */
#define MY_EXIT_FAILURE -1
#define true 1
#define false 0
typedef int my_bool;
size_t my_strlen(char const *str)
{
char const *p = str;
while (*p) ++p;
return p - str;
}
char* my_strcpy(char *dst, char *src)
{
char *p = dst;
while (*dst++ = *src++);
return p;
}
/* END stupid no-other-headers-than-<stdio.h> workaround */
typedef struct item_tag {
char name[MAX_ITEM_NAME_LENGTH + 1];
int price;
} item_t;
my_bool item_read(item_t *item)
{
char name[MAX_ITEM_NAME_LENGTH + 1];
int price;
if (scanf(" %" STRINGIFY(MAX_ITEM_NAME_LENGTH) "[^0-9]%d%*[\n]", name, &price) != 2)
return false;
size_t name_length = my_strlen(name);
if (name_length && name[name_length - 1] == ' ')
name[--name_length] = '\0';
my_strcpy(item->name, name);
item->price = price;
return true;
}
void item_print(item_t *item, size_t longest_name_length)
{
printf("%-*s %4d\n", (int)longest_name_length, item->name, item->price);
}
typedef struct products_list_tag {
size_t size;
item_t items[MAX_PRODUCTS_LIST_ITEMS_COUNT];
size_t longest_name_length;
} products_list_t;
products_list_t products_list_init(void)
{
products_list_t new_products_list = { 0 };
return new_products_list;
}
my_bool products_list_read(products_list_t *products_list)
{
size_t num_items;
if (scanf(" %zu%*[\n]", &num_items) != 1)
return false;
else if (!num_items)
return true;
size_t num_valid_items = 0;
size_t longest_name_length = 0;
for (size_t i = 0; i < num_items && !feof(stdin); ++i) {
if (!item_read(&products_list->items[i]))
--i;
else {
++num_valid_items;
size_t name_length = my_strlen(products_list->items[i].name);
if (longest_name_length < name_length)
longest_name_length = name_length;
}
}
if (num_valid_items != num_items)
return false;
products_list->size = num_valid_items;
products_list->longest_name_length = longest_name_length;
return true;
}
void products_list_print(products_list_t *products_list)
{
for (size_t i = 0; i < products_list->size; ++i)
item_print(&products_list->items[i], products_list->longest_name_length);
}
int main(void)
{
products_list_t products = products_list_init();
if (!products_list_read(&products)) {
perror("Failed to read products list!\n\n");
return MY_EXIT_FAILURE;
}
products_list_print(&products, stdout);
}
Output:
hot black tea 5
hot lemon tea 6
hot masala tea 7
hot milk tea 9
hot black coffee 7
hot milk coffee 10
finger potato 45
potato chips 35
I'm a noob at C and create this program to help me learn. Purpose is to add soccer players to a team and print info.
I'm trying to print fields of my club structure but when my program gets to my print method, all my values are garbage or addresses. How can I get "real" values
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 8
typedef struct player {
int id;
char *position;
} Player;
typedef struct club {
int size;
Player *team[SIZE];
} Club;
Player *create_player(int id, const char *description);
void create_team(Club *club);
void print_club(const Club *club);
void add_player_to_club(Club *club, int id, const char *position);
int main() {
Club club;
create_team(&club);
add_player_to_club(&club, 1, "forward");
add_player_to_club(&club, 2, "goalie");
print_club(&club);
return 0;
}
Player *create_player(int id, const char *description){
Player *player;
player = malloc(sizeof(Player));
if(description == NULL){
player->position = NULL;
} else {
player->position = malloc(strlen(description) + 1);
strcpy(player->position, description);
player->id = id;
}
return player;
}
void create_team(Club *team){
team = malloc(sizeof(Club));
if (team == NULL) {
return;
} else {
team->size = 0;
}
}
void print_club(const Club *club) {
int i = 0;
if (club == NULL) {
return;
} else if (club->size == 0) {
printf("No team members\n");
} else {
for (i = 0; i < SIZE; i++) {
printf("Id: %d Position: %s\n", club->team[i]->id,
club->team[i]->position);
}
}
}
void add_player_to_club(Club *club, int id, const char *position){
if (club == NULL || club->size >= SIZE) {
return;
} else {
Player player = *create_player(id, position);
club->team[club->size -1] = &player;
}
}
Here's a pic of my debugging session
Debugger
Problem 1
create_team is not doing anything useful for main. You are changing the value of a function local variable. As a consequence club remains uninitialized in main. You proceed to use it as though it is valid object, which is cause for undefined behavior.
You can change that function to:
void create_team(Club *team){
team->size = 0;
for (int i = 0; i < SIZE; ++i )
{
team->team[i] = NULL; // Unfortunate choice of variable names
// but should be OK.
}
}
Problem 2
You are storing a pointer to a function local variable in add_player_to_club. That pointer becomes invalid the function returns.
Player player = *create_player(id, position);
club->team[club->size -1] = &player; // Problem
Change it to:
club->team[club->size] = create_player(id, position);
club->size++;
Problem 3
You are printing too may Players in print_club. There aren't always SIZE number of Players in the team. Change the line
for (i = 0; i < SIZE; i++) {
to
for (i = 0; i < club->size; i++) {