The thing is that im trying to read some integers to know the levels of the game I have already passed through, then I want to put the integer of the current level to one if t is not already. It creates the file but doesn't write anything. Anyone know why? Now, it does it the first time when creating it with printf but when reading it gives status access violation.
void SaveGame(void)
{
FILE *pFile = fopen("SavedData.txt","rb");
int MyArray[8] = {0};
if(pFile)
{
fscanf(pFile, "%d %d %d %d %d %d %d %d" , MyArray[0], MyArray[1], MyArray[2], MyArray[3], MyArray[4], MyArray[5], MyArray[6], MyArray[7]);
fclose(pFile);
}
if(MyArray[Current] == 0)
MyArray[Current] = 1;
pFile = fopen("SavedData.txt", "wb");
if(pFile)
{
fprintf(pFile, "%d %d %d %d %d %d %d %d" , MyArray[0], MyArray[1], MyArray[2], MyArray[3], MyArray[4], MyArray[5], MyArray[6], MyArray[7]);
fclose(pFile);
}
}
You can do what you want something like this (untested) :
#define SAVE_FILE "SavedData.txt"
#define NUMS_SIZE 8
void SaveGame() {
FILE *f;
f = fopen(SAVE_FILE, "r");
if (!f) {
fprintf(stderr, "Error: Can't open save file for reading.\n");
exit(-1);
}
int nums[NUMS_SIZE] = {0};
int n, i = 0;
while (fscanf(f, "%d", &n) == 1) {
if (i >= NUMS_SIZE) break;
nums[i++] = n;
}
fclose(f);
f = fopen(SAVE_FILE, "w");
if (!f) {
fprintf(stderr, "Error: Can't open save file for writing.\n");
exit(-1);
}
int j = 0;
if (i > 0) fprintf("%d", nums[0]);
for (j = 1; j < i; ++j)
fprintf(" %d", nums[j]);
fclose(f);
}
That's not how you read a file.
For starters if it is a text file, open with mode "r", not "rb".
When you do a read operation you should check to see whether the read operation suceeded or failed. You don't do feof instead. There is a lot of code out there that does feof and most of it is wrong. Be wary when copying off internet code samples.
Also, it's a great idea to read the documentation for any standard function you use. You may learn things about the function that you didn't know. For example, fscanf returns how many items were successfully read.
So in your reading loop, either check that fscanf returns 8 (or loop 8 times as ooga suggested, checking for 1 each time). Don't check feof during the loop.
Once the read fails, THEN you have the option to do feof to find out why the read failed, if you care to know. It could have fail because you hit the end of file (feof), or because of a device error (ferror), or because the file had words in it instead of numbers.
When you do the writing part, make sure you only write numbers which were successfully read.
Related
Receiving a segmentation fault 11 while trying to read in a .txt file and q-sort it in C. This is a home work assignment for my CS class, and in it, the professor has given us a q-sort function he has written, and we need to make it faster using posix. I'm showing the relevant code here for reading in a text file, and then creating an array and using q-sort on it. The program works for an arbitrary array of strings I made up so I'm reasonably sure it's something to do with the way I am reading in the .txt file and processing it. Poem.txt is in the same directory, and the error handler works if I change the file name. Any ideas?
int main(){
double start, end;
double total;
char *array[100000];
char buffer[MAX_LENGTH];
int i = 0;
FILE *fp;
fp = fopen("poem.txt", "r");
if (fp < 0) {
fprintf(stderr, "Couldn't open file to read in. | error number %d : %s \n", errno, strerror(errno));
exit(1);
}
// First "function" to read in a text file for sorting
while (fscanf (fp, "%s", buffer) == 1) {
array[i] = malloc (MAX_LENGTH);
strcpy (array[i++], buffer);
}
// printf ("%s\n", array[1]); /* print for troubleshooting */
start = clock();
sortThreaded (array, i);
// freeing the memory used in the array from Malloc
for (int j = 0; array[j]; j++){
free(array[j]);
}
end=clock();
total = (end-start)/CLOCKS_PER_SEC;
printf(" total clocks: %f\n", total);
fclose(fp);
return 0;
}
First, as noted above, you should check
if (NULL == fp)
not
if (fp < 0)
Because fopen returns NULL if it can't open a file.
Second, it's unsafe to use %s in fscanf. If a input line is longer than MAX_LENGTH, you can receive a "* stack smashing detected *".
You can use
char *fgets(char *s, int size, FILE *stream);
or
fscanf (fp, "%99999s", buffer)
Even though it shouldn't be the problem.
Third, array is not initialized. So, it contains garbage. In
for (int j = 0; array[j]; j++) {
free(array[j]);
}
You may be freeing some addresses that were not allocated. As may be also the case in
fclose(fp);
A couple notes/possibilities I see:
When checking fp, if the fopen() fails, it will be set to NULL not a negative number so that could be a source or error.
if (fp == NULL) {
fprintf(stderr, "Couldn't open file to read in. | error number %d : %s \n", errno, strerror(errno));
exit(1);
}
When you do the fscanf and the strcpy() the buffer could be overflowing, best to do a fgets() and a strncpy() and specify MAX_LENGTH
while (fgets (buffer, MAX_LENGTH, fp) != NULL) {
array[i] = malloc (MAX_LENGTH);
strncpy (array[i++], buffer, MAX_LENGTH);
}
The free() loop could use the same iterator i and decrement to be sure we are freeing everything we allocated, no more no less.
while (--i >= 0){
free(array[i]);
}
Segmentation fault generally happens when you try to access memory that you are not allowed to access or doesn't exist. Sometimes thrown by a MPU (memory protection unit).
I am trying to read values from a file and after some operation write to another file. Here facing a slight issue as I am also trying to save values in a 2D Array and displaying it. My file read and file write are showing correct results but my program throws an exception when it comes to display matrix part.
#include <stdio.h>
#include <ctype.h>
#ifndef NULL
#define NULL ((void *) 0)
#endif
int main(void)
{
FILE *file = NULL; //for file read
FILE *fptr = NULL; //for file write
int mat[182][274];
// code to read and display number from file
// open file for reading
file = fopen("file.txt", "r");
fptr = fopen("file1.txt", "w");
int i = 0,j=0;
fscanf (file, "%d", &i);
while (!feof (file))
{
symbol = fgetc(file);
if (symbol == '\n' || feof(file))
{
fprintf (fptr,"\n");
printf("\n");
}
else{
j=255-i;
mat[i][j]=j;
fprintf (fptr,"%d ", j);
fprintf (fptr," ");
printf ("%d ", j);
}
fscanf (file, "%d", &i);
}
fclose (file);
fclose (fptr);
//Facing issue in this part
int k;
int l;
for (k=0;k<=182;k++)
{
for(l=0;l<=274;l++)
{
printf("%d ", mat[k][l]);
}
}
return 0;
}
Arrays in C start at 0 and end at (array_size - 1).
As you're accessing memory just outside the array, you're most likely experiencing segmentation faults.
To fix this issue, change these lines:
for (k=0;k<182;k++)
{
for(l=0;l<274;l++)
{
printf("%d ", mat[k][l]);
}
}
Notice that I changed the relational operators from <= and >= to < and >, respectively.
Along with that, you may need to fully initialize your array. Odd values may be printed if the array is not initialized. (#Weather Vane).
However, to best be sure if this is the case, we need file.txt and file1.txt.
I'm trying to read two records form a file, where one is hexadecimal formated number. Well I'm newcomer to C, before when I been reading hexadecimal, generated by ftok(), I just used printf("%x", key) and it worked fine. Now when I try to read it from the file, it does not work that way.
So my code looks like this:
int countRecords(FILE *f_p) {
int tmp_key = 0;
int tmp_msgqid = 0;
int n = 0;
while (!feof(f_p)) {
if (fscanf(f_p, "%x %i", &tmp_key, &tmp_msgqid) != 2)
break;
n = n + 1;
}
return n;
}
Later on i read this value in the code like:
printf("Records: %i \n", countRecords(f_msgList));
And this compiles with no warnings. Anyway when I run the program the value of countRecords(f_msgList) is 0, when the file have a bunch of data in it:
5a0203ff 360448
850203ff 393217
110203ff 425986
EDIT:
Here is the code where the file is opened or created:
FILE *f_msgList;
f_msgList = fopen("../message_queues.list", "a");
// if file does not exist then create one and check for errors
if (f_msgList == NULL) {
FILE *f_tmp;
f_tmp = fopen("../message_queues.list", "w");
if (f_msgList == NULL) {
fprintf(stderr, "Error occurred while creating the file! \n");
exit(1);
} else
f_msgList = f_tmp;
}
Problems
You opened the file in "append" mode. which does not let you read through the file.
If you want to write and then read the file, file pointer must be reset to the starting of the file.
feof(f_p) is worst way of checking whether file pointer is at end of the file.
Solution
Open File in "read" mode by 'r' or in append+read mode 'a+'.
if you are writing in to the file. reset it using rewind(f_p); after writing.
check out this way to read through the file :
int ret, ans, key;
while ((ret = fscanf(fp, "%x %i", &key, &ans))) {
if (ret == EOF)
break;
else
printf("%x %i \n",key, ans);
}
here integer ret is :
EOF, if the pointer is reached end of file.
0, if no input matched with the variable
(greater than 0), that is, number of matched variables with the file input
I am writing some code that inputs grid coordinates of "islands" (connected points on a grid) and finds the center of mass for each island. The code is successful for grids with a few large islands, however, it fails for grids with many small islands.
I've narrowed down the issue to rewind() failing on the 252nd loop-through. I have no idea why it fails as I've verified that island # 252 exists by printing the coordinates prior, and if I skip 252, the code fails on island 253, so I believe it is just rewind failing after 252 uses.
The code is quite large, so I'll try to just post the relevant parts:
FILE *f;
if((f = fopen(argv[1], "r")) == NULL)
{
printf("Could not open file to read.\n");
return 0;
}
while(!feof(f))
{
fscanf(f, "%d %d %d\n", ¤t_x, ¤t_y, &island_number);
if(island_number > number_of_islands)
{
number_of_islands = island_number;
}
}
fclose(f);
This the first instance when f is used, but it's used again later, and again in the following for loop which is where the problem emerges:
for( int i = 0; i < number_of_islands; i++)
{
printf("new loop: %d (number of islands: %d) \n", loop, number_of_islands);
if(loop == 252)
{
printf("putting in x, y at 252...\n");
}
This is where the code fails...
//putting numbers in x and y
rewind(f = fopen(argv[1], "r"));
Here's a bit of the following part (probably not important):
if(loop == 252)
{
printf("rewound at 252...\n");
exit(0);
}
while(!feof(f))
{
fscanf(f, "%d %d %d\n", ¤t_x, ¤t_y, &island_number);
if(island_number == current_island_number)
{
x_array[current_x] += 1;
y_array[current_y] += 1;
}
}
if(loop == 252)
{
printf("finished putting in x, y at 252...\n");
exit(0);
}
A sample of what the output looks like is this:
Everything looks good, except for the sudden segfault.
So my question is, why is rewind() suddenly segfaulting on the 252nd attempt?
this: rewind(f = fopen(argv[1], "r"));
does not rewind f.
instead it assigns a new value for f, opening the same file and rewinding it (although it has just been opened).
on some systems there is a limit to the open file descriptors you can have. why 252? i guess your limit is 256 and the kernel probably uses the remaining 4.
to fix the problem you can either close the file first, or:
rewind(f);
this should work with no reassignment of f.
I have this function to read numbers from txt files that are structured like so:
1 2 5
2 1 9
3 5 8
The function reads the values correctly into my values, but I want to check if the line I have read is the last in the file.
My last if statement in the below function attempts to do this by seeing if fscanf produces NULL but it doesn't work, the function always returns NULL even if it's not the last line.
void process(int lineNum, char *fullName)
{
int ii, num1, num2, num3;
FILE* f;
f = fopen(fullName, "r");
if(f==NULL)
{
printf("Error: could not open %S", fullName);
}
else
{
for (ii=0 (ii = 0; ii < (lineNum-1); ii++)
{
/*move through lines without scanning*/
fscanf(f, "%d %d %d", &num1, &num2, &num3);
}
if (fscanf(f, "%*d %*d %*d\n")==NULL)
{
printf("No more lines");
}
fclose(f);
}
}
Check this below code.Using this code u can see whether you have reached the end of file or not.It is not suggested to use fscanf to read the end of file.
/* feof example: byte counter */
#include <stdio.h>
int main ()
{
FILE * pFile;
int n = 0;
pFile = fopen ("myfile.txt","r");
if (pFile==NULL) perror ("Error opening file");
else
{
while (fgetc(pFile) != EOF) {
++n;
}
if (feof(pFile)) {
puts ("End-of-File reached.");
printf ("Total number of bytes read: %d\n", n);
}
else puts ("End-of-File was not reached.");
fclose (pFile);
}
return 0;
}
You can use feof() to check if you are reading past the end of the file.
From man page of fscanf:
RETURN VALUE
These functions return the number of input items successfully matched
and assigned, which can be fewer than provided for, or even zero in the
event of an early matching failure.
You if the last line that you are trying to read is not in the expected format, fscanf may not read anything and return 0 which is same as NULL.