fwrite not writing entire buffer - c

I am currently making a small test program for simple file checking. The program writes two small matrices(A and B) to files, closes and reopens them, reads in the matrices from the files, multiplies them and writes the resulting matrix(C) to a new file. It then closes and reopens this file containing the answer and prints it out for me to check if the IO operation proceeded correctly.
My problem is that the result matrix reads differently than expected.
I consider myself a beginner in C and of file input/output operations and this is the code that is causing me trouble. I am using WinXP, Codeblocks and Mingw.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define bufferA(i,k) (bufferA[i*cols+k])
#define bufferB(k,j) (bufferB[k*cols+j])
#define bufferC(i,j) (bufferC[i*cols+j])
void printMatrix(int *nMatrixToPrint, int nNumberOfElements, int nDimension) {
// This function prints out the element of an Array. This array represents a matrix in memory.
int nIndex;
printf("\n");
for (nIndex = 0; nIndex < nNumberOfElements; nIndex++) {
if (nIndex % nDimension == 0)
printf("\n");
printf("%d,",nMatrixToPrint[nIndex]);
}
return;
}
int main(int argc, char *argv[]) {
int nElements = 16, nDim = 4;
int A[4][4] = {{1,2,3,1},{2,2,1,2},{4,2,3,1},{5,1,1,3}};
int B[4][4] = {{3,2,1,4},{2,2,3,3},{4,1,3,2},{2,2,5,1}};
// Create files of A and B, delete old ones if present
FILE *fpA = fopen("A.dat", "w+");
FILE *fpB = fopen("B.dat", "w+");
// Write data to them
fwrite((int*)A, sizeof(*A), nElements, fpA);
fwrite((int*)B, sizeof(*B), nElements, fpB);
// and close them
fclose(fpA);
fclose(fpB);
// Reopen files
fpA = fopen("A.dat", "r");
fpB = fopen("B.dat", "r");
// Allocate memory
int *bufferA = (int*)malloc(nElements * sizeof(*bufferA));
int *bufferB = (int*)malloc(nElements * sizeof(*bufferB));
int *bufferC = (int*)calloc(nElements, sizeof(*bufferC));
// Read files
fread(bufferA, sizeof(int), nElements, fpA);
fread(bufferB, sizeof(int), nElements, fpB);
printf("\nA");
printMatrix(bufferA, nElements, nDim);
printf("\n\nB");
printMatrix(bufferB, nElements, nDim);
// Matrix multiplication
// Calculate and write to C
int i,j,k = 0; // Loop indices
int n = nDim,l = nDim, m = nDim, cols = nDim;
// multiply
for (i = 0; i < n; i++) { // Columns
for (j = 0; j < m; j++) { // Rows
//C(i,j) = 0;
for (k = 0; k < l; k++) {
bufferC(i,j) += bufferA(i,k) * bufferB(k,j);
}
}
}
printf("\n\nC_buffer");
printMatrix(bufferC, nElements, nDim);
// Create C and write to it
FILE* Cfile = fopen("C.dat", "w");
fwrite(bufferC, sizeof(*bufferC), nElements, Cfile);
// Close files
fclose(fpA);
fclose(fpB);
fclose(Cfile);
// reopen C for reading
Cfile = fopen("C.dat", "r");
// Obtain file size
fseek(Cfile , 0 , SEEK_END);
long lSize = ftell(Cfile);
rewind(Cfile);
printf("\nC file length is: %ld", lSize);
// read data into bufferA
fread(bufferA, sizeof(int), lSize, Cfile);
fclose(Cfile);
printf("\n\nC_file");
printMatrix(bufferA, nElements, nDim);
// Free allocated memory and remove dangling pointers
free(bufferA); bufferA = NULL;
free(bufferB); bufferB = NULL;
free(bufferC); bufferC = NULL;
exit(0);
}
Which gives me the following output:
A
1,2,3,1,
2,2,1,2,
4,2,3,1,
5,1,1,3,
B
3,2,1,4,
2,2,3,3,
4,1,3,2,
2,2,5,1,
C_buffer
21,11,21,17,
18,13,21,18,
30,17,24,29,
27,19,26,28,
C file length is: 64
C_file
21,11,21,17,
18,13,21,18,
30,17,24,29,
27,19,1,3,
As you can see, the last two elements in C_file are wrong, instead the output shows the last two elements in A as I was writing the file contents into bufferA. A switch to bufferB would swap the last two characters with the last elements in B which is still erroneous. A filecopy into another project would yield the last two integers as whatever was in ram at that malloc address.
My question is as follows: Why does not fwrite write the proper data into the file. Why does it manage the first 14 elements but not the last two? And how does this differ from my previous correct uses of fwrite and fread when I wrote and retrieved the elements of A and B?

You are writing binary data, and therefore you have to open the file in binary mode, the default is text mode. This makes a difference on windows, but not on *nix, which explains why it works for the other people here.
for all your fopen calls, include the letter 'b' in the mode argument, e.g. replace "w+" with "w+b" , replace "r" with "rb" and so on.

Your program runs just fine on my Mac.
The results would look better if printMatrix() output a final newline. Perhaps the unterminated line is causing some sort of confusion on your system?

Related

Efficiently read CSV file into array of doubles in C

Looking for a more efficient method of reading a CSV file into a 2D array of doubles. My current code works okay but takes 2 minutes to read into the array.
The CSV file being read is as follows. The entire file contains 28,325,381 lines and is 1.8GB.
CoordinateX,CoordinateY,CoordinateZ,Pressure,Temperature,VelocityX,VelocityY,VelocityZ,
0,0,0.0904,33.5797,300,-0.00146382,0.000389435,-0.00147085,
0,0.0003,0.0904,33.5795,300,0.126682,-0.000382509,0.00330599,
0,0.0006,0.0904,33.5793,300,0.250278,-0.00151828,0.0100881,
0,0.0009,0.0904,33.5788,300,0.365407,-0.00287706,0.0184123,
...
The original code...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
/* Declare file and character pointers */
FILE *pFile_r = NULL;
FILE *pFile_w = NULL;
char *pCell;
int n = 0, p = 0, number_properties = 8;
/* Open CSV file */
char buffer[128];
pFile_r = fopen("G:\\csv\\coarse (19000 - 39000)\\39500.csv","r");
/* Declare array */
int array_total_nodes = 28325340; //number of nodes in array
double **properties_array;
properties_array = malloc(array_total_nodes * sizeof(double*));
for (n=0; n<array_total_nodes; n++) {
properties_array[n] = malloc(number_properties * sizeof(double));
}
/* Fill array */
rewind(pFile_r);
fgets(buffer, 128, pFile_r);
while (!feof(pFile_r)) {
pCell = strtok(buffer, ",");
for (p=0; p<number_properties; p++) {
properties_array[n][p] = strtod(pCell, &pCell);
pCell = strtok(NULL, ",");
}
fgets(buffer, 128, pFile_r);
n++;
}
return 0;
}
This method is something simple I came up with. I'm hoping there is a more clever way that's faster. Your help is appreciated.
Update
I have switched for fgets to fscanf as such...
while (!feof(pFile_r)) {
fscanf(pFile_r, "%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,", &properties_array[n][0], &properties_array[n][1], &properties_array[n][2], &properties_array[n][3],
&properties_array[n][4], &properties_array[n][5], &properties_array[n][6], &properties_array[n][7]);
n++;
}
Reading in now takes 70 seconds as opposed to 120 (a 40% decrease). I would like to improve upon this further if possible.

Reading a .tiff file in c from inside zip

I have multiple tiff images stored inside a zip file and would like to read their pixel values in c. I am very new to c so please forgive the dodgy code. I have got to the point where I have a char * with the contents of the tiff file but can't seem to work out how to now process that with libtiff (or something similar). libtiff seems to require that I pass TIFFOpen a filename to open. I could write the tiff to a temporary file but it feels like there must be a more efficient way.
So far I have:
#include <stdlib.h>
#include <stdio.h>
#include <zip.h>
#include <string.h>
int main()
{
//Open the ZIP archive
int err = 0;
struct zip *z = zip_open("test.zip", 0, &err);
// Determine how many files are inside and iterate through them
int num_files = zip_get_num_entries(z, 0);
printf("%u\n", num_files);
int i;
for (i=0; i < num_files; i++)
{
const char * filename;
filename = zip_get_name(z, i, 0);
// If the file name ends in .tif
if (strlen(filename) > 4 && !strcmp(filename + strlen(filename) - 4, ".tif"))
{
printf("%s\n", filename);
// Get information about file
struct zip_stat st;
zip_stat_init(&st);
zip_stat(z, name, 0, &st);
printf("%lld\n", st.size);
// Allocate memory for decompressed contents
char *contents;
contents = (char *)malloc(st.size);
// Read the file
struct zip_file *f = zip_fopen(z, filename, 0);
zip_fread(f, contents, st.size);
zip_fclose(f);
// Do something with the contents
// Free memory
free(contents);
}
}
//And close the archive
zip_close(z);
}
EDIT: My question is similar to this one but the accepted answer there relates to c++ and I'm not sure how to translate it to straight c.

pass dynamic array of pointers to C function

I want to store each line of the file in an 2D array, and anthor array pointing each line (so I can identify each line), I need to pass this pointers array to a function so I can manipulate my lines, I d'ont know how to do that
I have this code to read and store in the arrays
char ligne[MAX];
//open end test the file
FILE* fichier = fopen("csp.txt","r");
if(fichier == NULL){
printf("can't open the file \n");
return EXIT_FAILURE;
}
//the first line in the file contain number of other lines
fgets(ligne, sizeof(ligne), fichier);
int nbrTaille = strtol(ligne, NULL, 10);
//array of pointers
char (*tab)[nbrTaille] = malloc(nbrTaille * sizeof(ligne));
int i = 0;
//tab array point each line
while(fgets(ligne, sizeof(ligne), fichier)){
if(ligne == NULL) EXIT_FAILURE;
strncpy(tab[i], ligne, strlen(ligne));
printf("line%d : %s\n", i, tab[i]);
i++;
}
//call the funnction by passing array of pointers and the number of lines
allDiff(tab, nbrTaille);
the file I'm reading is
2
1 2
2 3
to receive the array by the function I tried this but it doesn't work
void allDiff(char** T, int taille)
I am always confused with the parenthesies and asterisks. The easier way is to declare a double pointer:
char ** tab;
//you need to take care of errors. I am not doing it for simplicity
//tab = {pointer1, pointer2, pointer3, ...., pointerN} total memory needed N * sizeof(pointer)
tab = malloc(lines* sizeof(tab)); //how many pointers you want
for(i = 0; i < lines; i++){
tab[i] = malloc(MAX); //each string
}
In the end free the memory:
for(i = 0; i < lines; i++){
free(tab[i]);
}
free(tab);
EDIT complete code
char ligne[MAX];
//open end test the file
FILE* fichier = fopen("csp.txt","r");
if(fichier == NULL){
printf("can't open the file \n");
return EXIT_FAILURE;
}
//the first line in the file contain number of other lines
fgets(ligne, sizeof(ligne), fichier);
int nbrTaille = strtol(ligne, NULL, 10);
//array of pointers
//char (*tab)[nbrTaille] = malloc(nbrTaille * sizeof(ligne));
int i = 0;
char **tab;
tab = malloc(nbrTaille * sizeof(tab)); //how many pointers you want
for(i = 0; i < nbrTaille; i++){
//sizeof(ligne) is equal to MAX
tab[i] = malloc(MAX); //each string
}
i = 0;
//tab array point each line
while(fgets(ligne, sizeof(ligne), fichier)){
if(ligne == NULL) EXIT_FAILURE;
strncpy(tab[i], ligne, strlen(ligne));
printf("line%d : %s\n", i, tab[i]);
i++;
}
//call the funnction by passing array of pointers and the number of lines
allDiff(tab, nbrTaille);
void function(char tab[][MAXLEN], ...);
This will do.
For the sake of readbility and sanity, typedef C function pointers before creating arrays or double pointers to them.
/* typedef the function pointer. An ftabptr points to a void function that
takes a char * */
typedef void (*ftabptr)(char *p);
/* create an uninitalised list of twenty of them */
int N = 20;
ftabptr *pointerlist = malloc(N * sizeof(ftabptr));
However I don't think you really want to do this. You can write a
functioning program that does weird things with tables of function
pointers, but normally you use a language other than C if you
want to play that game (Lisp-like languages, etc). The high level
language then often emits C as an intermediate step.

Return an array of files

I am trying to create a function that returns an array of files but I couldn't find a way to access that array outside of the function.
Here's what I tried:
FILE* *arquivoescrita(int k) //gerar nome de arquivo
{
char filename[sizeof("file1000000000000.txt")];
static FILE* arquivos[2];
for (int i = k; i < k+2; ++i)
{
sprintf(filename, "file%d.txt", i);
arquivos[i] = fopen(filename,"r");
}
return arquivos;
}
And I'm calling the function inside main like this:
FILE* psaidas[2];
psaidas = arquivoescrita(0);
And the error I get is
error: array type 'FILE *[2]' is not assignable
psaidas = arquivoescrita(0);
How can I access this kind of array?
You are returning a pointer to the static array. That's fine. But C will not magically copy the array for you into another location. You can change your declaration:
FILE**psaidas;
psaidas = arquivoescrita(0);
And this will work. But at this point, psaidas will be pointing in to your static FILE * array. So if you call arquivoescrita again, it will be overwritten.
If that works - and it probably will work - then proceed. If you have to worry about calling arquivoescrita multiple times before you finish with the files, then you must either use malloc or calloc to dynamically allocate your result within arquivoescrita or you may choose to copy the array after you receive it:
FILE * psaidas[2];
memcpy(psaidas, arquivoescrita(0), sizeof(psaidas));
There is one issue in returning a FILE ** array of open file stream, you need to know how many are actually open. You have a couple of choices, (1) pass a pointer to the function and update the pointer to reflect the number of files successfully opened, or (2) what probably makes more sense, is to pass a FILE * array as a parameter to the function and return the number of files successfully opened to be use as an index back in the calling function. (you could also simply check the stream before attempting to read from it)
For example, if you declared file pointer array FILE *fparray[MAXF] = {NULL}; in main, you could simply pass that as a parameter to be filled in your function. e.g.
nfiles = openmulti (fparray, 0, MAXF);
Your function would then take the array, just as any other type of array, and fill the elements with open and validated FILE * elements:
int openmulti (FILE **fp, size_t k, size_t n)
{
char fname[MAXFN] = "";
size_t i, idx = 0;
for (i = k; i < n; i++) {
sprintf (fname, "file%zu.txt", i);
fp[idx] = fopen (fname, "r");
if (!fp[idx])
continue;
idx++;
}
return (int)idx;
}
(the beginning number file#.txt is passed as k and then number of files to open is passed as n)
A short example opening file0.txt and file1.txt in the function for reading back in the calling function could be:
#include <stdio.h>
enum { MAXF = 2, MAXFN = 256 };
int openmulti (FILE **fp, size_t k, size_t n);
int main (void) {
FILE *fparray[MAXF] = {NULL};
size_t i, nfiles;
nfiles = openmulti (fparray, 0, MAXF); /* populate array */
if (nfiles < MAXF) /* validate number of open files */
fprintf (stderr, "warning: '%zu' of %d files open.\n",
nfiles, MAXF);
for (i = 0; i < nfiles; i++) { /* read/output file contents */
printf ("\ncontents of 'farray[%zu]'\n\n", i);
char buf[MAXFN] = "";
while (fgets (buf, MAXFN, fparray[i]))
printf ("%s", buf);
fclose (fparray[i]); /* close file after reading */
}
return 0;
}
int openmulti (FILE **fp, size_t k, size_t n)
{
char fname[MAXFN] = "";
size_t i, idx = 0;
for (i = k; i < n; i++) {
sprintf (fname, "file%zu.txt", i);
fp[idx] = fopen (fname, "r");
if (!fp[idx])
continue;
idx++;
}
return (int)idx;
}
Example Input Files
$ cat file0.txt
1.
2. hello -- file0.txt
3.
$ cat file1.txt
1.
2. hello -- file1.txt
3.
Example Use/Output
$ ./bin/filemultiopen
contents of 'farray[0]'
1.
2. hello -- file0.txt
3.
contents of 'farray[1]'
1.
2. hello -- file1.txt
3.
Unless there is some critical need to return FILE **, it seems to make things a bit more straight forward to pass an array to the function and return the number of files successfully opened. Both ways are possible, whatever fits your needs.
Let me know if you have any additional questions.

Many doubts about decrypt an image file in c

Firstly, i'm not very familiarized with C, i come from Java, C#, C++... and possibly i inherited defects from this languages in order to realize this practice, well i have the follows question, here is my code:
#include <stdio.h>
#include <stdlib.h>
void decrypt(unsigned long* v, unsigned long* k);
const int MAX = 32;
const long delta = 0x9e3779b9;
long sum=0xC6EF3720;
int main() {
FILE *fp;
FILE *destino;
unsigned long v[2];
unsigned long k[4] = { 128, 129, 130, 131 };
unsigned long tam=0;
char* buffer;
char* aux[sizeof(unsigned long)];
int i;
if ((fp = fopen("image.png", "rb")) == NULL) {
printf ("Error! \n ");
return 0;
}
else {
fread(&aux,sizeof(unsigned long),1,fp);
memcpy(&tam,&aux,sizeof(unsigned long));
buffer = (char*)malloc(tam);
//fread(&buffer,1,tam,fp);
char *buffer2[28568];
fread(&buffer2,1,28568,fp);
/*for(i = 0;i < tam;++i) {
printf("%c", ((char *)buffer2)[i]);
}*/
for(i=4;i<tam;i+=8) {
memcpy(&v,&buffer2[i],8);
decrypt(&v,&k);
}
if ((result= fopen("image2.png", "rb")) == NULL) {
printf ("Error! \n ");
return 0;
}
else {
fwrite(v,sizeof(unsigned long)*2,1,result);
fclose (result);
fclose(fp);
}
}
return 0;
}
void decrypt(unsigned long* v, unsigned long* k) {
int i=0;
while(i<MAX) {
v[1] = v[1] -((4 << v[0])+(k[2]^v[0])+(sum^(5 >> v[0]))+k[3]);
v[0] = v[0] -((4 << v[1])+(k[0]^v[1])+(sum^(5 >> v[1]))+k[1]);
sum = sum-delta;
i++;
}
}
Where tam is the size of my binary file (image in this case) where i store first 4 bytes (unsigned long) where is located the size in my png file (28568)
When i create my char* buffer i have to assign dynamically with malloc but when i make a new fread from my file i get a "No source available for "msvrct!memcpy() at 0xrandom_memory_address" from Eclipse when i debug, well, i comment this line and i try to make it manually set a new buffer2 with 28568 as size of my array, apparently works, making a iteration of buffer2 prints ascii characters values but when i call decrypt for make the decryption of my image, the final result is stored in v array which i have to copy in a new file, i tried to search how to make a empty image png in C but i didn't find anything, so i created a copy of my encrypt image calling it "image2.png" but i suppose this not the "clean solution" for that, because for the other hand is not working at all.
For more explanation about this exercise just say that the decrypt funcion work with blocks of 8 bytes (64 bits) that through a key (array k) make a series of operation where they store in v array itself, crossing through the loop 8 in 8 and retrieve the value of buffer in v in each one, after the loop execution we have the result in v and only left to copy in a new file where finally show up the image decrypt.
It's a very complex practice for all of one newbies in C, it's driving my crazy trying to figure out what i doing wrong.
I hope anyone can see what i'm not able to for now.
I think you are having problems with the declarations of the buffers. I think the correct should be:
FILE *fp;
FILE *destino;
unsigned long v[2];
unsigned long k[4] = { 128, 129, 130, 131 };
unsigned long tam=0;
char* buffer;
char aux[sizeof(unsigned long)]; // without the "*"
int i;
if ((fp = fopen("image.png", "rb")) == NULL) {
printf ("Error! \n ");
return 0;
}
else {
fread(aux,sizeof(unsigned long),1,fp);
memcpy(&tam,aux,sizeof(unsigned long));
buffer = (char*)malloc(tam);
//fread(buffer,1,tam,fp); // without the "&" in this case
char buffer2[28568]; // without the "*"
fread(buffer2,1,28568,fp); // or fread(buffer,1,tam,fp);
/*for(i = 0;i < tam;++i) {
printf("%c", buffer2[i]); // or buufer[i] if you change to use it again
}*/
for(i=4;i<tam;i+=8) {
memcpy(v,&buffer2[i],8);
decrypt(v,k);
}
...
I don't fully understand what you are trying to accomplish, but one problem is here:
char* aux[sizeof(unsigned long)];
// ... some code ...
fread(&aux,sizeof(unsigned long),1,fp);
Understand that char* aux[sizeof(unsigned long)]; means that you are declaring a double pointer, but fread() prototype states that the destination is a single pointer:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
so what you should be doing instead is:
char aux[sizeof(unsigned long)];
// ... some code ...
fread(aux,sizeof(unsigned long),1,fp);
Don't complicate things that are not complicated!
You also do this mistake in other parts of your code, you need to re-check everything, ok? Again:
char *buffer2[28568];
fread(&buffer2,1,28568,fp);
should be:
char buffer2[28568];
fread(buffer2, 1, 28568, fp);
// or: fread(buffer2, 1, sizeof(buffer2), fp);
There are some interesting tutorials on pointers and arrays, I suggest you read some.

Resources