I need to write the content of an array into a file. Let's suppose I generate random numbers and put them into an array. How do I copy those values into the output file?
[... previous code/declarations ...]
file = open(filename, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU|S_IWGRP|S_IWOTH);
buffer = (double *) calloc(d, sizeof(double));
for (i = 0; i < d; i++)
{
double div = (double) (RAND_MAX/0.333);
double r = rand()/div;
(*(buffer+i)) = r;
}
write(file, buffer, sizeof(double));
[ ... ]
If I try to read the files, all I see is this memory garbage, nonsense chars all over my screen. Can anyone please help me figuring out what is I do wrong?
The write call is used to write memory blocks to a file, which will seem like garbage mostly if you try to just output the file later. That's because they will most likely be an IEEE754 binary representation.
If you want a textual representation of the numbers, use something like:
fh = fopen (filename, "w");
for (i = 0; i < d; i++)
fprintf (fh, "%f\n", buffer[i]);
fclose (fh);
You are writing random binary values to the file. When you read the file, you see the random binary values, interpreted as characters. Where's the problem?
At least this part is wrong:
write(file, buffer, sizeof(double));
You're writing only a single value, not the whole array. Multiply the size with d (which seems to be the number of elements in your array).
Why do you put
double div = (double) (RAND_MAX/0.333);
inside the loop?
Related
This is some code I used to read and store lines from a text file into an "expressions" array:
//create array for going through the file
char lines[128];
//create array for storing expressions
char **expressions = malloc(128*sizeof(char*));
FILE *file = fopen(argv[1],"r");
int count = 0;
while (fgets(lines,128,file)){
expressions[count] = lines;
printf("expressions[%d] is %s\n",count,expressions[count]);
count++;
}
for (int i = 0; i<count; i++){
printf("%s",expressions[i]);
}
And this is the text this code is trying to read:
f = g + h - 42;
g = 12 + 23;
My issue here is that while it appears to go through the file properly (count matches the number of lines), the final print loop prints the last line g = 12 + 23 twice instead of the two distinct lines. Why is this occuring and what can I do to fix this issue?
Each time you read a line, you store it in the lines character array, and then you save the address of that array in the next space of expressions. If you look at the values stored in expressions you'll find that they are all the same.
If you want to keep a copy of each line, you're going to have to have space to store a copy of each line. If you have a maximum number of lines which you're going to deal with, you can allocate that memory in the program. Otherwise you're going to have to start using dynamic memory allocation.
Let's work on 100 lines maximum, with each line no longer than 127 characters (as above):
char expressions[100][128];
int count = 0;
while (fgets(lines,128,file)) {
strcpy(expressions[count], lines);
printf("expressions[%d] is %s\n",count,expressions[count]);
count++;
if (count == 100)
break;
}
I need to write an array whose parts are scattered in code.
In short, my code is this:
(...)
FILE *f = fopen(filepath, "wb"); // wb -write binary
for (uint i = 0; i < num_points; i++) {
fwrite(points[i].loc, sizeof(float[3]), 1, f);
}
fclose(f);
As you can see, my solution was writing each new part of the array in front of the file.
But does this have a problem with efficiency, or memory reading? Should I allocate the entire array in RAM and then write the file?
fwrite will buffer your data until its buffer is full, or fflush/fclose/etc. is called. So it won't perform a syscall each iteration.
I'm making a program that reads two sets of data (float) from two different .txt files, and then it transfers these data to two different arrays, which will be used in further calculations. However, when I try to use dynamic allocation more than once, something goes wrong and the data seem not to be stored in the array.
The following simplified program seems to be working fine:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
float *VarA;
int n = 0;
int *counter;
int i;
FILE *input1;
input1 = fopen("C:\\Users\\...test.txt","r");
VarA = (float*)calloc(20001, sizeof(float));
for(i = 0; i < 20001; i++)
{
fscanf(input1,"%f",&VarA[i]);
printf("%f\n",VarA[i]);
}
free(VarA);
fclose(input1);
return 0;
}
it successfully shows the data stored in the array VarA. However, if I introduce a new array to count the number of lines in the file (which is necessary for my further calculations), I just get the value 0.000000 from every array element:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
float *VarA;
int n = 0;
int *counter;
int i;
FILE *input1;
input1 = fopen("C:\\Users\\...test.txt","r");
counter = (int*)calloc(100000, sizeof(int));
while(fscanf(input1,"%f",&counter[n]) != EOF)
{
n++;
}
free(counter);
printf("n = %i\n", n);
VarA = (float*)calloc(n, sizeof(float));
for(i = 0; i < n; i++)
{
fscanf(input1,"%f",&VarA[i]);
printf("%f\n",VarA[i]);
}
free(VarA);
fclose(input1);
return 0;
}
I know that I can avoid using another array to count the number of lines. The point is that every time I use another array, for any purpose, I get the same result. For instance, if I don't use an array to count the number of lines, but I make another one to store my other set of data, one of these arrays just won't present the data after the reading. I tried to modify my program several times in order to find the source of such behavior, but without success.
(At least) two major problems: first,
counter = (int*)calloc(100000, sizeof(int));
while(fscanf(input1,"%f",&counter[n]) != EOF) {
n++;
}
free(counter);
is basically saying "Grab me a chunk of memory, fill it with data as I read the file, then throw it away without ever using it." Probably not what you intended. Then,
VarA = (float*)calloc(n, sizeof(float));
for (i = 0; i < n; i++) {
fscanf(input1,"%f",&VarA[n]);
printf("%f\n",VarA[n]);
}
free(VarA);
which says, "Grab a big chunk of memory, then read data from after the end of the file I just read everything from, put it there, then throw it away."
If you want to read the data from the same file again, you'll have to close it an reopen it (or "seek" to the start). And if you want to do anything with it, you'll have to do it before free()ing the memory you loaded it into.
counter = (int*)calloc(100000, sizeof(int));
// ^--- `int*` ^--- `int`
// v--- `int` pointer
while(fscanf(input1,"%f",&counter[n]) != EOF)
// ^--- `float` designator
Do you see any discrepancies here? Your code allocates ints, then passes a pointer to those ints to fscanf telling it they're floats (using the %f designator). According to the C standard draft n1570, section 7.21.6.2p10 this constitutes undefined behaviour:
If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.
My suggestion would be to use the * assignment suppression modifier here, for example:
while (fscanf(input1, "%*f") != EOF) n++;
or, alternatively
while (fscanf(input1, "%f", &(float){0}) != 1) n++;
Note also how I've changed the check from EOF to 1. You can find more information about the return values of fscanf here (which you really should read before using any scanf-related function... and stop guessing, because guessing in C can be harmful).
Additionally, you need to rewind your file once it reaches EOF, otherwise every call to fscanf following this loop will return EOF:
rewind(input1);
P.S. Don't cast malloc in C. This goes for calloc and realloc, too. There's a lot of this quoted stuff that has opengroup manuals of its own; I'll leave it as an exercise to you to find (and read) the opengroup manuals.
WHAT THE CODE DOES: I read a binary file and sort it. I use a frequency array in order to do so.
UPDATES:it does do the loop, but it doesn`t write the numbers correctly...
That is the code. I want to write on file after reading from it. I will suprascript what is already written, and that is okey. The problem is I have no error on compiling, but at run time it seems I have an infinite loop.
The file is binary. I read it byte by byte and that`s also the way I want to write it.
while(fread(readChar, sizeof(readChar)/2, 1, inFile)){
bit = atoi(readChar);
array[bit] = array[bit] + 1;
}
fseek(inFile, 0, SEEK_SET);
for( i = 0; i < 256; i++)
while(array[i] > 0){
writeChar[0] = array[i]; //do I correctly convert int to char?
fwite(writeChar, sizeof(readChar)/2, 1, inFile);
array[i] = array[i] -1;
}
The inFile file declaration is:
FILE* inFile = fopen (readFile, "rb+");
It reads from the file, but does not write!
Undefined behavior:
fread() is used to read a binary representation of data. atoi() takes a textual represetation of data: a string (a pointer to an array of char that is terminated with a '\0'.
Unless the data read into readChar has one of its bytes set to 0, calling atoi() may access data outside readChar.
fread(readChar, sizeof(readChar)/2, 1, inFile);
bit = atoi(readChar);
Code it not reading data "bit by bit" At #Jens comments: "The smallest unit is a byte." and that is at least 8 bits.
The only possible reason for an infinite loop I see is, that your array is not initialized.
After declaration with:
int array[256];
the elements can have any integer value, also very large ones.
So there are no infinite loops, but some loops can have very much iterations.
You should initialize your array with zeros:
int array[256]={0};
I don't know the count of elements in your array and if this is the way you declare it, but if you declare your array like shown, than ={0} will initialize all members with 0. You also can use a loop:
for(int i=0; i < COUNT_OF_ELEMENTS;i++) array[i] = 0;
EDIT: I forgot to mention, that your code is only able to sort files with only numbers within.
For that, you have also to change the conversion while writing:
char writeChar[2]={0};
for( int i = 0; i < 256; i++)
while(array[i] > 0){
_itoa(i,writeChar,10);
fwrite(writeChar, sizeof(char), 1, inFile);
array[i] = array[i] -1;
}
File content before:
12345735280735612385478504873457835489
File content after:
00112223333334444455555556777778888889
Is that what you want?
#include <stdio.h>
#include <time.h>
int main(int argc,char *argv[])
{
int i;
int array[20];
srand(time(NULL));
for (i=0; i<20; i++)
array[i] = rand()%8999 + 1000;
char *fname = argv[1];
FILE *fp;
fp = fopen(fname,"w");
fwrite(array,sizeof(int),20,fp );
fclose(fp);
return 0;
}
my program should generate a sequence of 20 random numbers within a range of 1000 to 9999. I need to create an array of 20 nums, sort it and transfer to the file passed at cmd line... But, it says Segmentation fault
Your formula for getting the random values is also wrong:
With this code:
rand()%9999 + 1001;
you will get values from [1001, 11000]. When you are claiming you want a range from [1000, 9999].
Try to solve this for a simpler case, lets say a dice from [1, 6] will be:
rand()%5 + 1
The other problem is your for loop:
Remove the for loop and you should be fine. You don't need that for loop to print the array. Check the rewind function if you really need to do something like that.
First check the return value of fopen.
Then:
fwrite(array,sizeof(int),20,fp );
You are not moving your array pointer. Use something like:
fprintf(fp, "%d\n", array[i]);
Also:
array[i] = rand()%9999 + 1001;
What if the value yielded by rand()%9999 is 9998? I think then 9998 + 1001 is no longer between 1000 and 9999. Also how can rand()%9999 + 1001 yields 1000?
for (i=0; i<20; i++)
array[i] = rand()%8999 + 1000; // change random Number logic
for (i=0; i<20; i++)
fprintf(fp,"%d\t",array[i]); // change fwrite(array,sizeof(int),20,fp );
see fprintf()
First problem, the rand calculation is false, if you want an integer between 1000 and 9999, then it should be :
array[i] = rand()%9000 + 1000; // 9000%9000 = 0 ...
Then, your call to fwrite writes the whole content of the array buffer, seen as a set of sizeof (int) long substrings. Since odds are quite low that you will end up with valid character encoding, when you will open your file with a text editor to see the results, you will only have gibberish data ... Thus, your whole for loop is useless (you will print 20 times the whole content of array subsequently to your file).
Here, what you could do is a for loop with a call to fprintf to write the array[i] number in a human readable format or just stick with your single call to fwrite.
Then, I would like to say that you do not test the return value of your function calls.
It can be a source of errors so be very careful with this. I think of the whole file operation functions (fopen, fwrite).
Then, what if argv[1] doesn't exist ? When the call to fopen will be run, you'll have a segmentation fault ... Here is a little checking you could add :
if (argc > 1) {
fname = argv[1];
} else {
fname = NULL;
}