C Passing file pointer into a function - c

I have a problem with passing file pointers. How do I pass it if there is a function with a file pointer within a function(void writequest in my code)? It was working before I put in the void writequest. The program itself is supposed to read from one file that is filled with movie names and then put them into another. Of course, feel free to note any other failures in my code.
void writequest(int no)
{
int i, j, loop_ctrl, destination;
int movement;
char lib[loop_ctrl+1][92];
int write_nr[loop_ctrl], sorting[destination];
char searching[92];
char *c;
FILE *watched;
FILE *temp;
FILE *refrom;
FILE *reto;
FILE *towatch;
if(no==1)
{
printf("No match found.\n");
}
else if(no==0)
{
printf("Do you wish you write them into a file?\n1 - Yes\n0 - No\n");
scanf("%d", &j);
if(j==1)
{
tofile(watched, temp, refrom, reto, destination, loop_ctrl, write_nr, lib, movement);
close(towatch, watched, temp, refrom, reto);
remove("To_watch.txt");
rename("temp.txt", "To_watch.txt");
}
else if(j==0)
{
printf("Alright then\n");
close(towatch, watched, temp, refrom, reto);
}
}
}

char *c;
FILE *watched;
FILE *temp;
FILE *refrom;
FILE *reto;
FILE *towatch;
These are all pointers. So if you call upon them in your functions your asking for the value inside them. That's their address. except for movement. What is a bit strange.
It is vital to know what the functions exactly are before anyone can say what the problem is.

Related

My professor ran this code successfully, but I cannot. Seems to be an issue with the fopen() and the pointers

Edit: If it matters, I'm using Dev C++ with -std=c99 as an option.
My professor was able to run this code in class and successfully open a file that eventually reads the data into a linked list. When running the exact same code, my program abruptly exits despite the file being successfully opened.
All I'm trying to do is get this code to run. I've solved what he wants us to solve in my own example, but I can't figure out why his code doesn't run on my machine.
I did add in a puts("Success") line to verify the file has been opened, and I've gone through the methods it calls to see if I can find an error, but I cannot.
Here is the method with the issue (I'm assuming)
int ReadFileStoreInList(void)
{
FILE *cfPtr;
if ((cfPtr = fopen("Hertz-Homework-9-List.txt", "r")) !=NULL)
{
char make[TWELVE]={""}, model[TWELVE]={""}, size[TWELVE]={""}, color[TWELVE]={""}, power[TWELVE]={""};
char rented = 'A';
float daily_rate=0.0;
char dAilyRate[TWELVE];
fscanf(cfPtr, "%s%s%s%s%s%s", make, model, size, color, power, dAilyRate);
while (!feof(cfPtr))
{
fscanf(cfPtr, "%s%s%s%s%s%f", make, model, size, color, power, &daily_rate);
rented = 'A';
add_at_end(make, model, size, color, power, daily_rate, rented);
}
printScreenTitleAndHeaderForCars();
traverse_in_order();
}
else
{
puts("Input data file could not be opened, I have no new inventory of cars from headquarters\n\n\n");
}
fclose(cfPtr);
}
This calls traverse_in_order(); and printScreenTitleAndHeaderForCars();, which I will list below.
void traverse_in_order()
{
node *ptr;
if(start==NULL)
{
printf("list is empty\n");
return;
}
printScreenTitleAndHeaderForCars();
for(ptr=start; ptr!=NULL; ptr=(*ptr).next)
printf("%-12s%-12s%-12s%-12s%-12s%9.2f%12c\n", ptr->make, ptr->model, ptr->size, ptr->color, ptr->power, ptr->daily_rate, ptr->rented);
}
void printScreenTitleAndHeaderForCars()
{
system("Cls");
printf("%35s\n\n","Hertz Rental Cars");
printf("%79s\n","Avail");
printf("%-12s%-12s%-12s%-12s%-12s%-12s%8s\n", "Make", "Model", "Size", "Color", "Power", "Daily_Rate", "Rented");
for (int x=0; x< 7; x++)
printf("----------- ");
printf("\n");
}
In case the structure/header file was also needed:
#define TWELVE 12
typedef struct node_type
{
char make[TWELVE];
char model[TWELVE];
char size[TWELVE];
char color[TWELVE];
char power[TWELVE];
float daily_rate;
char rented;
struct node_type *next;
} node;
node *start=NULL;
int ReadFileStoreInList(void);
void add_at_beginning();
void add_at_end(char make[TWELVE], char model[TWELVE], char size[TWELVE], char color[TWELVE], char power[TWELVE], float daily_rate, char rented);
void add_after_element();
void add_before_element();
void traverse_in_order();
void traverse_in_reverse_order(node *);
void delete_at_beginning();
void delete_at_end();
void delete_after_element();
void delete_before_element();
void sort();
void doSomething(); // menu to ask operator what to do
void RentaCar();
void FindCarAndUpdateAsRented(char *modelSelected);
void ReturnCar();
void toTitleCase(char *aString);
void printScreenTitleAndHeaderForCars();
Requested add_at_end function:
void add_at_end(char make[TWELVE], char model[TWELVE], char size[TWELVE], char color[TWELVE], char power[TWELVE], float daily_rate, char rented)
{
node *ptr, *loc;
ptr = (node *) malloc(sizeof(node));
if(ptr==NULL)
{
printf("no space\n");
return;
}
strcpy((*ptr).make,make);
strcpy((*ptr).model,model);
strcpy((*ptr).size,size);
strcpy((*ptr).color,color);
strcpy((*ptr).power,power);
(*ptr).daily_rate = daily_rate;
(*ptr).rented = rented;
if(start==NULL)
{
start=ptr;
(*start).next=NULL;
}
else
{
loc = start;
while((*loc).next != NULL)
loc=(*loc).next;
(*loc).next=ptr;
(*ptr).next=NULL;
}
}
Interesting enough, if I rename this file to something that isn't correct, the proper printScreenTitleAndHeaderForCars() text executes and shows on screen. That's why I believe it has something to do with ReadFileStoreInList();
I've tried to debug this for a few hours now, but with the knowledge I've learned in class I just can not figure out why this doesn't run.
I expect the output to have the header information given from printScreenTitleAndHeaderForCars(), and then the data from the file I'm reading to appear on screen.
When the file is named improperly in my code, it runs this:
Hertz Rental Cars
Avail
Make Model Size Color Power Daily_Rate Rented
----------- ----------- ----------- ----------- ----------- ----------- -----------
list is empty
enter choice
1. Select Model and Rent
2. Select Model and Return
5. traverse in order
11. sort
12. exit
Where "list is empty" is situated, it should be populating the data from the text file and putting it there.
Instead, I just get:
--------------------------------
Process exited after 1.433 seconds with return value 3221225477
Press any key to continue . . .
I have a feeling this has to do with the way the pointers are written, but I'm struggling to understand how he could run the code and I couldn't.
Any knowledge as to why this might happen would be appreciated!
Edit: Text file contents:
make, model, size, color, power,daily rate.
Mazda,3,4-door,Black,4-Cyl,$99.73
Jeep,Cherokee,4-door,Blue,8-Cyl,$131.92
Buick,Regal,4-door,Purple,6-Cyl,$125.19
Fullsize,SUV,5-door,Brown,8-Cyl,$163.94
Chrysler,Pacifica,4-door,Green,6-Cyl,$127.49
Ford,Focus,2-door,Red,4-Cyl,$99.73
VW,Jetta,2-door,Orange,4-Cyl,$94.91
Chevrolet,Suburban,4-door,Yellow,8-Cyl,$204.92
Nissan,Pathfinder,4-door,White,6-Cyl,$145.11
Chevrolet,Spark,2-door,Teal,4-Cyl,$99.55
You concluded in comments that you thought the data file contents were to blame for your issue. You now having posted those, I can confirm that they are indeed a contributing factor. Imprudent details of your scanf format also contribute.
In the first place, the call for reading the header is dangerous:
fscanf(cfPtr, "%s%s%s%s%s%s", make, model, size, color, power, dAilyRate);
Since the data are just going to be discarded, there is no point in storing them. Moreover, it's not necessarily safe to assume that the header data will have characteristics matched to those of the associated data. It would be better to read and not assign the whole line:
fscanf(cfPtr, "%*[^\n]");
The * in the format says that the field directive is not to be assigned, only read. Overall, that reads (and ignores) everything up to but not including the first newline. That also allows you to get rid of the abominably-named dAilyRate variable.
Then there is the format for reading the actual data:
fscanf(cfPtr, "%s%s%s%s%s%f", make, model, size, color, power, &daily_rate);
It simply does not match the data. Specifically, the %s field descriptor skips leading whitespace and matches a whitespace-delimited string. Your data are comma-delimited, not whitespace-delimited except for line terminators. As a result, that scanf call will try to write a whole line's worth of data into each of the first five strings, thus overrunning each of their bounds. That's a plausible reason for a segfault.
What's more, the line read into daily_rate will fail, since the next data available at that point will be non-numeric. Yet even if the commas were changed to spaces, the rate data would still not be read correctly, because $ is not a valid part of a number. And that, in turn will throw off the reads for the second and subsequent lines.
The field overruns could have been avoided by specifying maximum field widths in the format. It would, moreover, be prudent to check the return value of scanf() to verify that all fields were read, as #Achal demonstrated in his answer, before relying on that data.
Here's a data file in a format compatible with the formats you're actually using:
make model size color power rate
Mazda 3 4-door Black 4-Cyl 99.73
Jeep Cherokee 4-door Blue 8-Cyl 131.92
Buick Regal 4-door Purple 6-Cyl 125.19
Fullsize SUV 5-door Brown 8-Cyl 163.94
Chrysler Pacifica 4-door Green 6-Cyl 127.49
Ford Focus 2-door Red 4-Cyl 99.73
VW Jetta 2-door Orange 4-Cyl 94.91
Chevrolet Suburban 4-door Yellow 8-Cyl 204.92
Nissan Pathfinder 4-door White 6-Cyl 145.11
Chevrolet Spark 2-door Teal 4-Cyl 99.55
And here's a safer way to read it:
#define STR_SIZE 12
char make[STR_SIZE]={""}, model[STR_SIZE]={""}, size[STR_SIZE]={""}, color[STR_SIZE]={""},
power[STR_SIZE]={""};
float daily_rate;
fscanf(cfPtr, "%*[^\n]");
while (fscanf(cfPtr, "%11s%11s%11s%11s%11s%f", make, model, size, color, power, &daily_rate) == 6) {
add_at_end(make, model, size, color, power, daily_rate, 'A');
}
The %11s fields will read up to 11 characters into your 12-character arrays, leaving room for the string terminator that fscanf() will append to each. This will still run into trouble if there is overlong data in the file, but it should not segfault.
I should say also that scanf is difficult to use safely and properly, and that there are other, better alternatives for parsing and consuming the data -- either in the original or in the modified format.
Here are few observation.
Firstly provide more readbility to your code by giving some meaningful macro name instead of TWELVE. For e.g #define NUMBER_OF_ITEMS 12
Secondly, In function definition the formal argument make[TWELVE] doesn't look good as you are passing char array & it decays to char*, so only char *make is enough.
This
void add_at_end(char make[TWELVE], char model[TWELVE], char size[TWELVE], char color[TWELVE], char power[TWELVE], float daily_rate, char rented) { }
can be replaced as
void add_at_end(char *make, char *model, char *size, char *color, char *power, float daily_rate, char rented) { }
And most importantly, this
fscanf(cfPtr, "%s%s%s%s%s%s", make, model, size, color, power, dAilyRate); /* Just Remove it */
just before
while (!feof(cfPtr))
creates an issue i.e that information you are not using, its getting overwritten by second fscanf() statement inside loop. Also do read Why is “while (!feof(file))” always wrong?
Sample code
void add_at_end(char *make, char *model, char *size, char *color, char *power, float daily_rate, char rented)
{
/* same code */
}
And
int ReadFileStoreInList(void)
{
FILE *cfPtr;
if ((cfPtr = fopen("input", "r")) !=NULL)
{
char make[TWELVE]={""}, model[TWELVE]={""}, size[TWELVE]={""}, color[TWELVE]={""}, power[TWELVE]={""};
char rented = 'A';
float daily_rate=0.0;
char dAilyRate[TWELVE];
while (fscanf(cfPtr, "%s%s%s%s%s%f", make, model, size, color, power, &daily_rate) == 6)
{
rented = 'A';
add_at_end(make, model, size, color, power, daily_rate, rented);
}
printScreenTitleAndHeaderForCars();
traverse_in_order();
}
else
{
puts("Input data file could not be opened, I have no new inventory of cars from headquarters\n\n\n");
return 0; /* in case of fopen failed */
}
fclose(cfPtr);
}

Creating a file with the name of a structure i just read from another file

I am trying to read a structure from the file f and i need some arrays of that structure ( "nume" and "firma.nrang") to be written into another file with the name of "localitate" which is also an array of the structure i am reading.
If two structures from f have the same "localitate" array, then their "nume" and "firma.nrang" fields need to be written in the same file called "localitate". I hope i explained well enough. However, i dont know why i cannot open the files i am creating, which i specifically wanted to be text and not binary. What is the problem?
This is my code which doesnt work properly:
typedef struct
{
char localitate[10];
int nrang;
} FIRMA;
typedef struct
{
char nume[20];
int varsta;
FIRMA firma;
} ANG;
ANG x;
FILE *p;
for (i=0; i<m+n; i++)
{
fread(&x,sizeof(x),1,f);
p=fopen(x.firma.localitate,"a");
if (p==NULL)
{
printf("eroare");
exit (1);
}
fwrite(&x.nume,sizeof(x.nume),1,p);
fwrite(&x.firma.nrang,sizeof(x.firma.nrang),1,p);
fclose(p);
}

Why remove and rename functions does not work in my program?

When I try to delete a file using the fowling lines of code, I get as result that the both files (stock.dat and clone.dat) exists after the end of the program (as result i want to exist only the renamed stock.dat (=original name was clone.dat)). Thanks in advance.
int code;
FILE *stock=fopen("stock.dat","rb");
FILE *stc_clone=fopen("clone.dat","wb");
printf("PLEASE TYPE THE CODE OF THE PRODUCT YOU WISH TO DELETE:\t");
scanf(" %d",& code);
printf("\n");
fseek(stock,0,SEEK_END);
int fl_size=ftell(stock);
int quantity= fl_size/sizeof(product);
rewind(stock);
prdct prd_pntr= (product *) malloc(sizeof(product)*quantity);
assert(prd_pntr);
fread(prd_pntr,sizeof(product),quantity,stock);
int i;
for(i=0;i<quantity;i++){
if(prd_pntr[i].code==code){
continue;
}else{
fprintf(stc_clone,"%d %s %d",prd_pntr[i].code,prd_pntr[i].description,prd_pntr[i].volume);
}
}
fclose(stc_clone);
fclose(stock);
remove(stock);
rename("clone.dat","stock.dat");
free(prd_pntr);
printf("\n\a THE PRODUCT DELETED!!!\n");
Your function does not remove the file because you are passing FILE* instead of char* to the remove function:
FILE *stock = fopen("stock.dat","rb");
...
fclose(stock);
remove(stock); // <<== HERE: you are supposed to pass a name, not FILE*
To fix the problem, change the remove line as followsL
remove("stock.dat");

C: lists, structures: error: structure has no member

English is not my motherlanguage, I'm sorry for any grammar mistakes in the description or in the code, I translated it in order to share it here with you.
Hello, I'm writing a little program in C and I need some help, I'm stuck with one error I can't fix, I searched here on forums and anywhere else, but nothing I found helped me. The other functions in the program work just fine.
This function reads a list of words and categories from txt file, puts it into a structure, makes a list. The user types what word he wants to delete from file, so function searches if it's there and deletes if it is.
I'm not the best with lists so there's probably a really basic, stupid problem here, any help please?
void REMOVE_WORD (int howmanylines)
{
FILE *fp;
if ((fp=fopen("words.txt", "r+w"))==NULL)
{printf("Error while opening the file!\n");
exit(1);}
else
{
typedef struct base
{
struct base *next;
char word[25];
char category[15];
} list_els;
struct base tab[howmanylines];
int i=0;
while (!feof(fp))
{
fscanf(fp, "%s", &tab[i].word);
fscanf(fp, "%s", &tab[i].category);
i++;
}
fclose(fp);
list_els *head;
list_els *el=(list_els*)malloc(sizeof(list_els));
list_els *ind=head;
while (ind->next)
{
ind=ind->next;
ind->next=el;
}
printf("What word do you want to remove?\n\n");
char word_remove[25];
scanf("%s", &word_remove);
if (strcmp(ind->next->word, word_remove)==0)
{
printf("Found:\n Word: | Category:\n %s | %s\n", ind->next->word, ind->next->category);
printf("Are you sure you want to remove?\n1)Yes\n 2)No\n\n");
int removing;
if (removing==1)
{
list_els *removed=ind->next;
ind->next=removed->next;
free(removed);
}
else if (removing==2) {printf("Removing cancelled.\n\n");}
else {printf("Wrong operation number!");}
}
else printf("Word not available in the base!\n\n");
}
}
It shows me an error 'struct base' has no member named 'word' in the line where I use the strcmp.
In this snippet
list_els *head;
list_els *el=(list_els*)malloc(sizeof(list_els));
list_els *ind=head;
while (ind->next)
{
ind=ind->next;
ind->next=el;
}
You are not initialising ind to any valid value. You probably meant to write ind = el instead of head. Also, don't cast malloc().

C programming opening and reading from a file

int main(void){
FILE *ifp; //input file pointer
int totalClock; //total clock count
// BEGIN OPERATIONS=============================
ifp=fopen("prog1.asy.txt", "r");
system("PAUSE");
assert(ifp!=NULL);
//populate the instMem with inst===================
int i=0;
//system("PAUSE");
for (i=0;i<512;i++)
{
inst temp=parser(ifp);
if (temp.opcode==-1)
break;
instMem[i]=temp;
printf("%s\n", instMem[i].rawCode);
}
printf("\n%d instructions parsed\n", i-1);
system("PAUSE");// PAUSE TO CHECK CODE PARSING IS CORRECT========
int cont=0;
while (cont==0){
//begin sim================================================
//initialize the mem=======================================
int i;
for (i=0;i<512;i++)
data[i]=0;
for (i=0;i<32;i++)
reg[i]=0;
IF_Time=0;
ID_Time=0;
EX_Time=0;
MEM_Time=0;
WB_Time=0;
//prompt input parameters===================================
printf("Memory access time: c=");
scanf("%d", &c);
printf("\nMultiply time: m=");
scanf("%d", &m);
printf("\nExecute time: n=");
scanf("%d", &n);
assert(c>0);
assert(m>0);
assert(n>0);
//start execution now that the program has been broken to unparsed strings====
while (0==0)
{
WB();
MEM();
if (MEM_WB.instruction.opcode==HALT)
break;
EX();
ID();
IF();
totalClock++;
system("PAUSE");
}
//PRINT RESULTS=============================================
printf("Run again with new parameters? 0=yes");
scanf("%d", &cont);
}
fclose(ifp);
system("PAUSE");
return 0;
}
struct inst parser(FILE *ifp){
char str[100];
struct inst temp;
if (fgets(str, 100, ifp)==NULL) {
inst temp={"NULL", -1,0,0,0};
}
else {
inst temp={str, 0,0,0,0};
puts(str);
}
return temp;
}
I am trying to read in a test file so that i can parse it into strings for analysis later. It opens the test file but it doesn't read the lines of test in the code. Is there something I am doing wrong.
Your parser functions only reads once from the file and does nothing with the result (since temp would be a local variable to the if branch, not to the function). First thing is to remove inst from inst temp = ... to see that it reads the first instruction. Then, you need to make that function loop over all lines in the file.
First of all, you need to format your source code on this page to make it more readable.
For parser(), I don't think you can return a structure. So please use a pointer instead. And, as Mihai mentions, "temp" is a temporary variable located on the stack, and it will be destroyed when returning from function parser().
I don't see the declarations of variables in the code snippet:
IF_Time=0;
ID_Time=0;
EX_Time=0;
MEM_Time=0;
WB_Time=0;
So I assume you could remove some unused code to make the question clear.
The last thing is: to analyze log files, shell scripts is more suitable than C. If you're not working on a UNIX/Linux box, you could also use Perl/Python if you want. They are all less error prone and easy to debug when used to analyze log files.

Resources