I have this problem in my c program when I start to reinsert the contents of my file and save a new one. It fails in the while loop and i don't understand why it does that if i have some contents to reinsert from it.
here's my code:
'''
void init(){
char pn[30],pd[30],pp[30];
if ((flptr = fopen("MASTER.dat","r+")) == NULL) {
printf("Couldnt Get Cred");
return;
}
fscanf(flptr,"%s %s %s",pn,pd,pp);
while(!feof(flptr)){
r = (struct Records *) malloc(sizeof(struct Records));
int fr = fscanf(flptr,"%s %s %f",r->PartNum,r->PartDesc, &r->PartPrice);
if(fr == EOF){
printf("HERE");
break;
}
if(head == NULL){
head = r;
}
else{
tail->next = r;
}
tail = r;
}
fclose(flptr);
}
void put(){
if ((flptr = fopen("MASTER.dat","r")) == NULL) {
printf("Couldnt Get Cred");
return;
}
r = head;
fprintf(flptr,"PartNumber PartDescription PartPrice\n");
while (r != NULL){
fprintf(flptr,"%s %s %f\n", r->PartNum, r->PartDesc, r->PartPrice);
r = r->next;
}
fprintf(flptr,"Changes SAVED.");
fclose(flptr);
}
In the function put you open the file to read it, not to write, so your fprintf will have no effect and the file not be even created
if ((flptr = fopen("MASTER.dat","r")) == NULL) {
must be
if ((flptr = fopen("MASTER.dat","w")) == NULL) {
If later you try to read that non existing file with init you will not success
Out of that put and init use the global variable r and modify it, I encourage you to use a local variable to avoid possible problems
Why do you open file file with "r+" in init while you only read it ?
When you read string through (f)scanf I encourage you to limit the length to not write out of the receiver with an undefined behavior, and to always check the result, so for instance replace
fscanf(flptr,"%s %s %s",pn,pd,pp);
by
if (fscanf(flptr,"%29s %29s %29s",pn,pd,pp) != 3) {
printf("invalid file contain\n");
return;
}
Related
I get this error when trying to run round robin algorithm, and the algorithms are working perfectly fine when taking input from user. this is the code:
else if (select==2)
{
FILE * filehandle;
char lyne[100];
char *item;
int reccount = 0;
// open file
filehandle = fopen("Input_Data1.txt","r");
// Read file line by line
while (fgets(lyne,99,filehandle))
{
numprocess =
printf("%s",lyne);
item = strtok(lyne," ");
p[reccount].arrivetime =atoi(item);
item = strtok(NULL," ");
p[reccount].bursttime =atoi(item);
reccount++;
}
//Close file
fclose(filehandle);
}
The error I get is segmentation fault (core dumped).
screen shot of the input file
I tried reading from a file execting the same result as reading from user input but I got the error showed in the image.
At least these issues:
Avoid atoi(NULL)
item = strtok(lyne," "); may return NULL.
item = strtok(NULL," "); may return NULL.
I suspect the 2nd should be item = strtok(NULL," \n");
NULL == filehandle?
Open may fail.
reccount may exceed max
No need for a -1
// fgets(lyne,99,filehandle)
fgets(lyne, sizeof lyne, filehandle)
FILE * filehandle = fopen("Input_Data1.txt","r");
if (filehandle == NULL) {
fprintf(stderr, "Open failed\n");
return;
}
char lyne[100];
int reccount = 0;
while (reccount < reccount_n && fgets(lyne, sizeof lyne, filehandle)) {
numprocess = printf("%s", lyne); // Unclear how OP is using numprocess
char *item = strtok(lyne," ");
if (item == NULL) {
fprintf(stderr, "strtok(lyne,\" \") failed\n");
return;
}
p[reccount].arrivetime =atoi(item);
item = strtok(NULL," \n");
if (item == NULL) {
fprintf(stderr, "strtok(NULL,\" \n\") failed\n");
return;
}
p[reccount].bursttime =atoi(item);
reccount++;
}
fclose(filehandle);
The following function is written in c:
void store_files(char *pathname){
printf("pathname = %s\n", pathname);
char nextPath[PATH_MAX];
DIR *dir;
struct dirent *sd;
struct stat stat_buffer;
int fileNum = 0;
int dirCount = 0;
if((dir = opendir(pathname)) == NULL){
printf("Cannot open directory!\n");
exit(EXIT_FAILURE);
}
while((sd = readdir(dir)) != NULL){
if(strcmp(sd->d_name, ".") == 0 || strcmp(sd->d_name, "..") == 0){
continue;
}
if(stat(pathname, &stat_buffer) != 0){
perror(pathname);
}
if(S_ISDIR(stat_buffer.st_mode)){
//Defines archive number
for(int i = 0; i < 100; i++){
if(strcmp(tmpDirPathNames[i], pathname) == 0){
dirCount++;
break;
}
}
//BUILD PATH
sprintf(nextPath, "%s/%s", pathname, sd->d_name);
store_files(nextPath);
}
else if(S_ISREG(stat_buffer.st_mode)){
printf("filename = %s & filesize = %ld\n", sd->d_name, stat_buffer.st_size);
time_t time = getFileModDate(pathname);
archiveNum[dirCount - 1].fileData[fileNum].size = stat_buffer.st_size;
archiveNum[dirCount - 1].fileData[fileNum].absolutePath = pathname;
printf("modification date = %s ", ctime(&time));
printf("fileNum = %i\n", fileNum);
fileNum++;
}
}
closedir(dir);
}
I don't see a real need to explain what each of the if statements in the while loop do since they aren't really relevant to the question. But I'll explain the issue I'm having in more detail here:
One of my other function will create a tmp file with a lot of tmpdir.XXX inside it from an extraction process I do on compressed files.
example of tmp file with a lot of tmpdir.XXX inside it:
tmp
->tmpdir.XXX
->TestFolder1
->TestFolder2
->tmpdir.XXX
->TestFolder3
->TestFolder4
The propose of my function is I want to extract information from every file in tmp. Right now, the function is fine in going into the first tmpdir.xxx and go through all the folders in that fine, i.e. TestFolder1 and TestFolder2. However, it doesn't go into the second tmpdir.XXX because this happens: (what printf("pathname = %s\n", pathname); prints):
pathname = /mnt/c/Users/.../Desktop/.../.../.../Project2/tmp
pathname = /mnt/c/Users/.../Desktop/.../.../.../Project2/tmp/tmpdir.JlzQFY
pathname = /mnt/c/Users/.../Desktop/.../.../.../Project2/tmp/tmpdir.JlzQFY/Testfile1in2
pathname = /mnt/c/Users/.../Desktop/.../.../.../Project2/tmp/tmpdir.JlzQFY/Testfile2in2
pathname = /mnt/c/Users/.../Desktop/.../.../.../Project2/tmp/tmpdir.JlzQFY/tmpdir.QE1nk2
Notice the last print, it tacks on the next tmpdir.XXX onto the first one. I dont really understand what's going on here and ive been staring at this for ages trying to work it out.
So I am trying to write a c file that has a student record database, once the file runs it is supposed to read student records from a binary file and add them to a linked list: the student struct looks like this :
typedef struct student {
char lname[10], initial, fname[10];
unsigned long SID;
float GPA;
struct student* next; /* pointer to the next student record */
} studentList;
I am using single linked lists for my data, and my code runs fine if I read and write the data with fscanf. However, once I started using fwrite and fread, everytime my program loads it would not load up the data from the text file correctly, when I check the binary file it seems it has data in it. Here is what I have for my load and write data functions:
void printRecords() {
FILE *fPointer = fopen("data.bin", "w");
studentList *newStudent = head;
while (newStudent != NULL) { /*Loop through linked list starting from head node*/
fwrite(&newStudent, sizeof(newStudent), 1, fPointer);
newStudent = newStudent->next;
}
}
void loadRecords() {
studentList *cStudent;
FILE *fPointer = fopen("data.bin", "r");
int counter = 0;
int x = 0;
int n = 0;
while (n != 0) {
printf("test\n");
if (fPointer == NULL) {
break;
}
cStudent = (studentList *)malloc(sizeof(studentList));
n = fread(&cStudent, sizeof(cStudent), 1, fPointer);
x = cStudent->GPA;
printf("%d\n", x);
if (feof(fPointer)) { break; }
if (counter == 0) {
head = cStudent;
temp = (studentList *)malloc(sizeof(studentList));
temp = cStudent;
counter++;
}
temp->next = (studentList *)malloc(sizeof(studentList));
temp->next = cStudent;
temp = temp->next;
}
fclose(fPointer);
}
so what am I doing wrong as right now it does not read anything into my list, it seems like it writes but not sure if it even writes the correct data, I have spent a long time trying to figure this out and have been stuck on it for a while now, thanks in advance.
To read write to binary files in c.
FILE *fPointer=fopen("data.bin","wb"); //to write file
FILE *fPointer=fopen("data.bin","rb"); //to read file
There are multiple problems with your code.
printRecords has problems:
you should use binary mode.
you write the contents of the pointer and some indeterminate contents instead of whet the pointer points to. This is actually undefined behavior.
you forgot to close the file.
the value written to the file for the next member is meaningless. Writing the same records may produce different file contents for different runs.
Here is a corrected version that returns the number of records written or -1 if the file could not be opened:
int printRecords(void) {
FILE *fPointer = fopen("data.bin", "wb");
studentList *sp;
int n = 0;
if (fPointer == NULL)
return -1;
/* Loop through linked list starting from head node */
for (sp = head; sp != NULL; sp = sp->next) {
n += fwrite(sp, sizeof(newStudent), 1, fPointer);
}
fclose(fPointer);
return n;
}
loadRecords has even more problems:
binary mode should be used too.
the way you test for end of file is incorrect.
the way you link records does not work either.
Here is a corrected version of loadRecords that returns the number of records read or -1 if the file could not be opened:
int loadRecords(void) {
studentList student, *newsp, *sp;
FILE *fPointer = fopen("data.bin", "rb");
int n = 0;
if (fPointer == NULL)
return -1;
while (fread(&student, sizeof(student), 1, fPointer) == 1) {
n++;
student.next = NULL; // value read from file is meaningless
newsp = malloc(sizeof(studentList));
*newsp = student;
if (head == NULL) {
head = newsp;
} else {
/* append the new record to the list */
for (sp = head; sp->next; sp = sp->next)
continue;
sp->next = newsp;
}
}
fclose(fPointer);
return n;
}
Be aware that storing binary data to the file system this way is not portable. The representation of integers and floats may differ from one platform to another, as well as alignment of the structure members, especially the next pointer which is useless in the file anyway. This file should only be read back on the same platform, with the same program that wrote it, making it a poor choice for backup or persistent storage.
There are problems in the file write function, mainly the data pointer and size:
void printRecords(){
FILE *fPointer = fopen("data.bin","wb"); // add "b" mode (MSVC)
if (fPointer == NULL) // check file opened
exit(1); // or report "Cannot open file"
studentList *newStudent = head;
while(newStudent !=NULL)
{
fwrite(newStudent, sizeof(*newStudent), 1, fPointer); // remove the & and add a *
newStudent = newStudent->next;
}
if (fclose(fPointer)) // close the file
exit(1); // or report "Failed to close file"
}
I'm trying to make a sort of a database program and ran into a few issues with reading integers from a text file in C.
I have the following code:
#include <stdio.h>
int main(){
int index;
FILE * fp;
if((fp = fopen("read_file.txt","r+")) == NULL){
perror("Cannot open file");
printf("\nCreating new file...");
if((fp = fopen("read_file.txt","w+")) == NULL){
perror("\nCannot create file.. Terminating..");
return -1;
}
}
fputs("INDEX = 3",fp);
fscanf(fp, "INDEX = %d",&index);
printf("index = %d\n",index);
fclose(fp);
return 0;
}
When i try to run the program it outputs "index = 16", i tried using fgets and sscanf but same thing happens. With strings however it decides to print out a bunch of characters that don't make sense.
What you see in undefined behavior because you write a string to the file and try to scan INDEX = %d which is not there in the file because of the file pointer is pointing after INDEX = 3
You need to rewind(fp) before scanning.
fputs("INDEX = 3",fp);
rewind(fp);
if( fscanf(fp, "INDEX = %d",&index) != 1)
printf("Scanning failes\n");
else
printf("INDEX = %d\n",index);
So here's my code for my main()
int main(int argc, char **argv) {
if (argc != 3) {
puts("Invalid number of args in the input. Sorry.");
return 0;
}
if (doesItExist(argv[2]) == 0) {
return 0;
}
FILE *fpoint;
char yesorno[2];
tail = (WordN) malloc(sizeof(struct WordNode));
tail->word = "";
tail->first = (FileN) malloc(sizeof(struct FileNode));
(tail->first)->freq = -1;
ftw(argv[2], tokeForMe, 1);
/**
fpoint = fopen(argv[1], "r");
if(fpoint != NULL) { // file exists give user option to overwrite or rename
getInput("Do you want to overwrite the file? Enter only either Y or N nothing else\n", yesorno, 2);
if(yesorno[0] == 'N' || yesorno[0] == 'n') {
puts("All right. Not going to proceed with the program");
return 0;
}
else if(yesorno[0] != 'Y' && yesorno[0] != 'y') {
puts("You inputted some other character, try again \n");
getInput("Do you want to overwrite the file? Enter Y or N. Do not enter anything other than 1 Y or 1 N \n", yesorno, 2);
}
}
fclose(fpoint);
**/
FILE *index;
index = fopen(argv[1], "w");
//puts("here");
writeToIndex(index, tail->next); //tail is pointing to the first word node
puts("there");
if (doesItExist(argv[1]) == 0) {
return 0;
}
fclose(index);
TailTerminate();
return 0;
}
The code seg faults when I uncomment the part when I make a file pointer to read argv[1] to find out whether the user wants to overwrite the file specified in argv[1].
The program itself is just a program that makes a sort of indexer out of a directory of files and then prints it out. The directory path is specified in argv[2] and the path to print out the index is specified in argv[1].
Can someone help me with this? The rest of the program (the Tail nodes and such) are only to make a sort of list the words and frequencies that appear in the program.
You don't show all the functions called from main (getInput?), and they may content errors. From your commented code, I can only say that you wrote something like this:
FILE *f = fopen(...);
if (f != NULL)
{
/* use f */
}
fclose(f);
But it should be like this:
FILE *f = fopen(...);
if (f != NULL)
{
/* use f */
fclose(f);
}
That is, do not call fclose() with a NULL pointer.