In C, I want to export a 1D array (of floats) to a CSV file to be opened by other programs. I wrote the following helper-function to do this:
#include <stdio.h>
#include <stdlib.h>
void float1DExportCSV(float *ptr, int n){
FILE *f;
f = fopen("FloatOutput.CSV", "w");
int i = 0;
for (i = 0; i < n-1; i++){
fprintf(f, "%f", ptr[i]);
fprintf(f, "%c", ',');
}
fprintf(f, "%f", ptr[n-1]);
}
I then tried to test it on an array with 10 elements, like this:
#define n 10
int main(void){
float array[n];
int i;
for(i = 0; i < n; i++){
array[i] = 4.3f*i;
}
float1DExportCSV(array, n);
return 1;
}
This works fine, and the resulting file opens correctly. Changing n to larger numbers (up to around 400,000) also works fine.
However, somewhere around the 500,000-element mark, the program simply crashes upon building. The arrays I want to export to CSV have more than 500,000 elements. Is there a robust way of doing this type of export? Is a looping fprintf method like I used above simply not a good way of exporting a large dataset?
When the array size is too large, use heap memory.
When n is too large, allocating the array on the stack causes stack overflow. At that time, allocating the memory on the heap is the answer.
Instead of
float array[n];
Use
float* array = malloc(n*sizeof(float));
Make sure to deallocate the memory. Add
free(array);
once you are done using the array.
Your problem is that local variables are allocated on the stack. If you use a static or global variable for array it will be allocated in the .bss segment. No need for malloc() or free() complexities for this simple test case.
#define n 500000
float array[n]; /* or static float array[n]; */
int main(void){
int i;
for(i = 0; i < n; i++){
array[i] = 4.3f*i;
}
float1DExportCSV(array, n);
return 1;
}
Related
I'm trying to allocate the char** path array in my batiment struct
#ifndef SDL2_BATIMENTS_H
#define SDL2_BATIMENTS_H
typedef struct{
int x;
int y;
}vecteur;
typedef struct{
int numtype; //Détermine quelle representation du batiment (route nor/ route sud...)
char** tabpath; // tableau de chemin d'acces aux images
vecteur size; // Taille du batiment en (x,y)
int habitant;
}batiment;
typedef struct {
vecteur** tuile;
batiment* tabbatiment; //tableau de batiment
}Monde;
Monde* InitBatiment(Monde* monde);
vecteur toGrid(float x,float y);
#endif //SDL2_BATIMENTS_H
I've tried to allocate it like an array[][], at first it seems to be working with no error but everytime i try to access it my program crashes
for(int i=0; i<14;i++)
{
monde->tabbatiment[i].tabpath = malloc(7 * sizeof (char*));
for (int y = 0; y < 7; y++)
monde->tabbatiment[i].tabpath[i] = (char*)malloc(50 * sizeof(char));
}
Ok First of all thank you for your answer, I changed my code to this but everytime my program try to call strcpy it crashes.
I think I still have an allocation problem or a memory leak.
for(int i=0; i<14;i++)
{
monde->tabbatiment[i].tabpath = calloc(10,sizeof(char*));
for(int y = 0; y < 10; y++)
monde->tabbatiment[i].tabpath[i] = calloc(30 ,sizeof(char));
}
FILE *f;
char c;
int numbatiment;
f=fopen("batiment.txt","r");
int x,y,numbat,numtype;
const char path[50];
for(int i =0;i<16;i++)
{
fscanf(f,"%d %d %d %d %s ",&numbat,&x,&y,&numtype,&path);
printf("%s",path);
strcpy(monde->tabbatiment[numbat].tabpath[numtype],path);
monde->tabbatiment[numbat].size.x = x ;
monde->tabbatiment[numbat].size.y=y ;
monde->tabbatiment[numbat].numtype = numtype;
printf("%d %d %d %d %s\n",numbat,monde->tabbatiment[numbat].size.x,monde->tabbatiment[numbat].size.y,monde->tabbatiment[numbat].numtype,monde->tabbatiment[numbat].tabpath[numtype]);
}
fclose(f);
Could you elaborate what you are exactly trying to accomplish with the code? It feels like there is more to it then a simple bug, but more of an implementation issue as a whole.
I cannot replicate your SEGFAULT for what it's worth. I do run into a lot of memory issues in valgrind, all of which could be attributed that you allocate memory in a loop, where you could've easily done it in a linear block (hence why I'm afraid that there might be more to this).
To directly answer your question: allocating memory for a string can go 2 ways: either you allocate enough memory from the start for which you are certain the any string you throw at it will be smaller than the allocated memory. Or you allocate memory on the go based on the length of the string that you are adding to your array.
In both cases you would be looking at a combination of malloc/calloc and strcpy/strncpy (the latter in both having my preference most often). Allocate memory where the string should reside, than copy a local buffered value to the designated memory address.
Anyway, I've refactored your example to this. I have to say: take a GOOD look at how you are using indexes in loops. You are going out of bounds often, which might trigger a SEGFAULT. For monde->tuile for instance you allocate 35 slots, but the next thing you do is loop the tuile index to 44. I've also included some define statements which are good practice over magic numbers.
#define SIZE_BATIMENT 15
#define SIZE_TUILE 34
#define SIZE_TABPATH 8
#define MAX_STRING_LEN 64
Monde *monde = calloc(1, sizeof monde);
monde->tuile = calloc(SIZE_TUILE, sizeof(vecteur *));
for (int i=0 ; i <= SIZE_TUILE ; i++)
{
monde->tuile[i] = (vecteur*)malloc(45 * sizeof(vecteur));
}
// Assign memory to allow MAX_STRING_LEN sizes
monde->tabbatiment = calloc(SIZE_BATIMENT, sizeof(batiment));
for(int i = 0; i <= SIZE_BATIMENT; i++)
{
monde->tabbatiment[i].tabpath = calloc(SIZE_TABPATH, sizeof(char *));
for (int j = 0; j <= SIZE_TABPATH; j++)
{
monde->tabbatiment[i].tabpath[j] = calloc(MAX_STRING_LEN, sizeof(char));
}
}
When trying to input a string of chars, i get a warning
warning: 'doc' may be uninitialized in this function [-Wmaybe-uninitualized]
When i run the code, it only allows me to enter the string itself and then it stops.
I tried compiling the code using an online compiler and it returned `segmentation fault (core dumped). I know something is wrong but i don't know how to fix it.
#include <stdio.h>
#include <string.h>
typedef struct Pacient{
char ime_prezime[100];
int osiguruvanje;
int broj_pregledi;
}Pacient;
typedef struct MaticenDoktor{
char ime_prezime[100];
int broj_pacienti;
Pacient pacient[200];
float cena;
}MaticenDoktor;
void najuspesen_doktor(MaticenDoktor *doc, int n){
int i, j, najgolema_zarabotka=0, najmnogu_pregledi=0, zarabotka, pregledi;
char najuspesen[100];
for(i=0; i<n; i++){
zarabotka=0;
pregledi=0;
for(j=0; j<doc[i].broj_pacienti; j++){
if(doc[i].pacient[j].osiguruvanje==0){
zarabotka+=doc[i].cena;
pregledi++;
}
}
if(zarabotka>najgolema_zarabotka){
najgolema_zarabotka=zarabotka;
strcpy(najuspesen, doc[i].ime_prezime);
najmnogu_pregledi=pregledi;
}
else if(zarabotka==najgolema_zarabotka){
if(pregledi>najmnogu_pregledi){
najgolema_zarabotka=zarabotka;
strcpy(najuspesen, doc[i].ime_prezime);
najmnogu_pregledi=pregledi;
}
}
}
printf("%s %d %d", najuspesen, najgolema_zarabotka, najmnogu_pregledi);
}
int main()
{
int i, j, n;
printf("Vnesi broj na doktori\n");
scanf("%d", &n);
MaticenDoktor *doc;
for(i=0; i<n; i++){
scanf("%s", doc[i].ime_prezime); // <---- warning here
scanf("%d", &doc[i].broj_pacienti);
scanf("%f", &doc[i].cena);
for(j=0; j<doc[i].broj_pacienti; j++){
scanf("%s", doc[i].pacient[j].ime_prezime);
scanf("%d", &doc[i].pacient[j].osiguruvanje);
scanf("%d", &doc[i].pacient[j].broj_pregledi);
}
}
najuspesen_doktor(doc, n);
return 0;
}
Does anyone know how to fix this?
MaticenDoktor *doc; only declares a pointer, and not the full structure (or the array). You need to initialize it to point to somewhere, where you can warrant there's enough free memory to hold the information. You can ensure this in several ways:
You can, instead, hold a complete structure in the function body (main in your case, with this similar declaration:
MaticenDoktor doc; /* no pointer, but a full structure variable is declared */
scan("%s", doc.ime_prezime);
...
You can, declare an array of MaticenDoktor structures with the following code:
MaticenDoktor doc[100]; /* now doc is an array with space for 100 MaticenDoktors */
scan("%s", doc[n].ime_prezime); /* n ranges from 0 to 99 max */
You can, if you don't know a priori how many MaticenDoktor you are going to have, and you read it before the loop, with:
MaticenDoktor *doc = malloc(n * sizeof *doc); /* you have doc pointing to an array of n MaticenDoktors */
scan("%s", doc[n].ime_prezime);
...
free(doc); /* after you are completely finished using doc */
You can, if you are short of memory, just declare an array of pointers with space for the maximum, and allocate the structures as you need them:
MaticenDoktor *doc[1000]; /* space for maximum of 1000 pointers to MaticenDoktor */
for (i = 0; i < n && i < 1000; i++) {
doc[i] = malloc(sizeof *doc[i]); /* size of pointed value, not of pointer */
scanf("%s", doc[i]->ime_prezime);
...
}
and later on
for (i = 0; i < n && i < 1000; i++) {
free(doc[i]); /* free space used by doc[i] */
}
... and many other ways to organize your memory :)
doc has not been assigned so points to an unpredictable location. You should either place it on the stack:
assing dynamic memory first.
MaticenDoktor *doc;
int len = 10; // all memory that you need.
doc =(MaticenDoktor *)malloc(sizeof(MaticenDoktor)*len);
it fix the Warning .
I am somewhat new to C programming. I have a doubt regarding dynamic memory allocation. The following is a code in the main program for memory allocation.
double **mat=(double**)malloc(sizeof(double*)*n);
mat[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
mat[i] = mat[i-1] + n;
mat = create_square_matrix(n);
I want to call the function and create elements in the matrix inside the function. Do I have once again allocation memory inside the function like below or Is there any other method to avoid this tedious memory allocation repetition. Following is the function.
`double** create_square_matrix(int n)
{
int i,j,sum=0;
double **array2=(double**)malloc(sizeof(double*)*n);
array2[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
array2[i] = array2[i-1] + n;
for (i = 0; i < n; ++i)
{
for (j = 0; j < n; ++j)
{
sum=sum+j;
array2[i][j]=sum;
}
}
return array2;
}
`
The above function returns the array which is stored in the 'mat' variable. And another question is how do I free the memory of variable 'array2' inside the function after using the return method. I can't free the memory possibly before returning the array. Is there a method to free the memory in the above function.
Your function create_square_matrix allocates memory and then fills it by some values.
Your top piece of code allocates memory, and then calls create_square_matrix which again allocates memory. It is like to mop floors before calling the janitor who also mops floors. You don't need to allocate memory twice. Not only it is unneccessary, in fact it is bad. Since you perform two allocations, the memory from the first one is lost, and there is no way to free it. This is called memory leak. Instead of
double **mat=(double**)malloc(sizeof(double*)*n);
mat[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
mat[i] = mat[i-1] + n;
mat = create_square_matrix(n);
you should write
double **mat = create_square_matrix(n);
As mentioned, in C there's no need to cast to/from void*. Also, your calloc is backwards: use N elements for the first argument, sizeof(element) for the second.
I will answer your question, and then suggest a better approach.
You are choosing double ** for your matrix. Even if it weren't square, you know exactly how many pointers and how many doubles you need, and of course how big each type is. So,
double **M = malloc( n * sizeof(double*) + n * m * sizeof(double) );
does the trick, does it not? If sizeof(double*) == sizeof(double) for your machine (probably true), then
double **M = calloc( (1+n) * m, sizeof(double) );
works, too, but less portably. You also get the zeros for free; you'll have trouble finding a machine for which it's not true that double f=0 yields a value for which all bits are zero.
But why define your matrix as an array of pointers? Why not instead define it as an array of doubles?
double *M = calloc( n * m, sizeof(double) );
Better yet, for the past 15 years or so, C has supported variable-length arrays, meaning you can define arrays whose size is determined at runtime. Back in K&R days, you could define an array M[n] unless n was a static constant or enum. If your arrays aren't ginormous -- meaning that for the machine in question they'll fit comfortably on the stack -- you can skip malloc and simply define your matrix by a size determined at runtime.
Even if you can't do that, can typedef one dimension dynamically,
typedef double (x_axis_t)[m];
double x_axis_t *M = calloc( n * sizeof(x_axis_t), sizeof(double) );
which is nice, because then you can access your array as
M[x][y];
Just don't try to use M[x,y], because that's something else altogether.
BTW, since you're new to the game, to use a c99 compiler, the standard command is c99, not cc. See your friendly manual for details. :-)
Using a nice function macro for memory allocation is always a good idea. Unless you have to free memory manually I would leave it to a garbage collector such as libgc. Below is an example. If you don't want to use a garbage collector you can just replace GC_MALLOC with malloc. When you free the array (manually) you must first free the individual rows.
#include <gc/gc.h>
#include <stdio.h>
#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = GC_MALLOC((n) * sizeof (ptr)[0])
double **SquareMatrix(int n)
{
double **A;
int i, j;
NEW_ARRAY(A, n);
for (i = 0; i < n; i++) {
NEW_ARRAY(A[i], n);
for (j = 0; j < n; j++) {
A[i][j] = 0.0;
}
}
return A;
}
int main(void)
{
const int n = 5;
double **A;
int i, j;
A = SquareMatrix(n);
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
printf("%5.2f ", A[i][j]);
}
putchar('\n');
}
return 0;
}
Just a quick comment to start: While there are similar threads to this one, I haven't quite been able to find the solution I'm looking for. My problem is the following:
I have 2D arrays of doulbes saved to binary files and I would like to read the binary files (using C code) into a 2D array. Additionally, I need to allocate the memory dynamically as the shape of the arrays will be changing in my application. To get started, I tried the following code:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
int N = 10; //number of rows of 2D array
int M = 20; //number of columns
/* first allocate the array */
double **data;
data = (double **)malloc(N*sizeof(double *));
for(unsigned int i=0; i < N; i++) {
data[i] = (double *)malloc(sizeof(double)*M);
}
FILE *ptr;
ptr = fopen("random_real_matrix.dat", "rb");
fread(data, sizeof(data), 1, ptr);
for(unsigned int i=0; i<10;i++){
for(unsigned int j=0; j<20;j++){
fprintf(stderr, "m[%d][%d] = %f\n ", i, j, data[i][j]);
}
}
}
Unfortunately, this code segfaults. I checked to see if I can set the array entries like
d[0][0] = 235;
and that works fine.
Assuming this approach can be fixed, I'm also interested to know if it could be extended to read to an array of double complex's.
Any advice would be greatly appreciated!
Your fread statement is incorrect. It's a common beginner mistake to think that sizeof gets the size of a dynamically allocated array. It doesn't. In this case it just returns the size of a double **. You will need to read in each double in the file and put that into the correct spot in the array.
for (int ii = 0; ii < N; ++ii)
{
for (int jj = 0; jj < M; ++jj)
{
fread(data[ii][jj], sizeof(double), 1, ptr);
// Be sure to check status of fread
}
}
You can do this with a single for loop (or a single fread) but this is probably clearer to read.
Because you allocated each row separately, you can't read into the entire array at once. You need to do it row by row.
for (int i = 0; i < N; i++) {
fread(data[i], sizeof(double), M, ptr);
}
Are there any limitations when implementing scanf int data type to an array in C? The code below gives me a "segmentation fault(core dumped) when array has more than 6 indices.
====example code=========
#include <stdio.h>
int main(void)
{
int size;
int array[size];
int x;
scanf("%d", &size);
for(x = 0; x < size; x++){
scanf("%d", &array[x]);
}
for(x = 0; x < size; x++){
printf("[%d] ", array[x]);
}
}
input:
4
3 45 5 76
output:
[3] [45] [5] [76]
input:
7
34 2 5 6 9 3 8
output:
Segmentation fault(core dumped)
My goal is to have a dynamic array. The user will decide its size. So far this proves impossible. I understand the dynamic array approach can be implemented with struct or c++ vector. However, I would like to understand whether the error is due to the code structure or am I ignorant of certain limitation in the C array.
I look forward to your knowledgeable input.
I am going to point out 2 things
Write int array[size]; after scanf statement and include stdlib.h in your code. In the new versions of gcc compiler takes care of memory allocation and finally freeing it for you. Also return some value as your return type is int.
But my advise to you is that use malloc statement in the following fashion as you might need to run the code on older version of gcc. And also compiler internally does the same thing.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int size;
scanf("%d", &size);
int *array;
array=malloc(size*sizeof(int));
int x;
for(x = 0; x < size; x++){
scanf("%d", &array[x]);
}
for(x = 0; x < size; x++){
printf("[%d] ", array[x]);
}
free (array);
return 0;
}
int size;
int array[size];
size is uninitialized right now . Array of what size would be created ?
Declare array after scanf("%d",&size).
The "classic" way would be to allocate memory for your array, either using malloc(size * sizeof(int)) or by using calloc(size, sizeof(int)). The former makes no guarantees as to the state of the memory allocated (apart from "allocated"), the latter guarantees that the memory has been zeroed before the function returns.
You can not use array[size] when size is not defined yet ! Instead if you want to use a dynamic array, you can do it like this:
#include <stdio.h>
#include <stdlib.h>
void main()
{
int size;
int *array;
int x;
if (scanf("%d", &size)==1){
array=calloc(size*sizeof(int));
}
//check if allocation has been done
for(x = 0; x < size; x++){
scanf("%d", &array[x]);
}
for(x = 0; x < size; x++){
printf("[%d] ", array[x]);
}
free(array);
return;
}
Better you dynamically allocate memory for taking a user input size.
int *arr,size;
scanf("%d",size);
arr=(int *)malloc(sizeof(int)*size);
This will create an integer array of length "size".