I have a problem with reallocating memory of dynamically allocated array. So what i am trying to do is:
typedef struct {
int s;
int l;
int* arr;
bool orient;
}DAC;
...
int main()
{
DAC heap = {
4, 0, (int*)malloc(4 * sizeof(int))
};
char c = 0;
int n = 0;
while (1)
{
scanf("%c", &c);
switch (c)
{
case '+':
if (heap.s == heap.l)
{
heap.s *= 2;
heap.arr = (int*)realloc(heap.arr, heap.s);
}
scanf("%d\n", &(heap.arr[heap.l]));
heap.l++;
break;
case 'p':
for (int i = 0; i < heap.l; i++)
printf("%d ", heap.arr[i]);
printf("\n");
break;
}
}
}
As long as my whole structure works for n<5 (i start with array of size '4'), weird things happens when this block is executed:
if (heap.s==heap.l)
{
heap.s*=2;
heap.arr=(int*)realloc(heap.arr,heap.s);
}
What is the reason im getting wrong output at index [2] of my array?
I know i could do it with mallocs, just wondering as i think it is weird case
Whole input/output:
+ 1
+ 2
+ 3
+ 4
p
1 2 3 4
+ 5
p
1 2 -33686019 4 5
You start correct when you initialize heap:
DAC heap = {
4, 0, (int*)malloc(4 * sizeof(int))
};
But when you actually want to increase the size, you forget to adjust to the size of integers.
Instead of increasing the size to fit for 8 int values, you only get 8 bytes instead.
As Felix G reminded in a comment, you should never directly assign to the same pointer. If realloc returns NULL you have no more access to the old address.
Use this instead:
if (heap.s == heap.l)
{
heap.s *= 2;
void *tmp = realloc(heap.arr, heap.s * sizeof(int));
if (tmp != NULL) {
heap.arr = tmp;
} else {
// handle error...
}
}
Related
I am an inexperienced C beginner. I have wrote this following to print fibbonaci numbers, which works well to some where below 50 numbers. It produces nonsense however if going beyond 50 numbers. I am almost certain this is a type decleration problem, but I can't figure out where the problem raises. Any help is appreciated.
#include <stdio.h>
void fib(int* a, int* b)
{
int acp = *a;
*a = *b;
*b += acp;
}
int nth(int n)
{
int a = 0;
int b = 1;
for (int i = 0; i < n; ++i) {
fib(&a, &b);
}
return a;
}
int main()
{
for (int i = 0; i < 50; ++i) {
printf("%ith fib: %i\n", i, nth(i));
}
return 0;
}
prints:
1th fib: 1
2th fib: 1
3th fib: 2
4th fib: 3
5th fib: 5
6th fib: 8
...
45th fib: 1134903170
46th fib: 1836311903
47th fib: -1323752223
48th fib: 512559680
49th fib: -811192543
The problem is the "size" of int, which can store numbers in range from -2,147,483,648 to 2,147,483,647. You could use unsigned int to make the range go from 0 to 4,294,967,295, but overall, it would not be a good improvement.
It makes us go further, but at least we know that if we work with integers, we may use unsigned to make the range bigger for our case. Thus, we can use unsigned long long (or unsigned long long int), which will store way more numbers than int (up to 18,446,744,073,709,551,615).
There is also another way which you may use, but is a bit different and probably off-topic. This would be using double type and calculating values of next Fibonacci numbers using Binet's formula. The caveat is, when calculating big numbers, you will lose the precision, thus the values you may get will be approximations.
To add on #whiskeyo answer, here is an implementation working for any size of integers, limited to a maximal value of 2 ^ (2 ^ 32 x 8) - 1 [ simply a 4GB integer ] and mainly by your system resources (your RAM...).
To overcome system integers sizes (see limits.h), one way is to manipulate theses integers as a bits chain, while applying adequate arithmetic.
In this basic example, we define a "number" as an array of bytes with a defined "size", it is the s_num object. The fib function here computes a = b + a by a simple carry report while adding byte by byte the "number" b to the "number" a. To display the computed number, we use printf capabilities while we can (8 bytes or less "number") and a simple hexadecimal display over 8 bytes.
An interesting work could be to build a decimal display for "number" over 8 bytes, one that could work byte by byte to output decimal digits in the same way (warning, that's not easy maths).
EDIT: Adding comments and take the point from #WeatherVane about reusing preceding computed Fibonacci in the main iteration loop. Improve readability by expanding byte arithmetic expressions in fib.
EDIT: Use of command line argument for N. Add an extract of the output.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// The s_num representing an integer as an array of bytes with a size.
// The [bytes] member stores the bytes from the least significant to the
// most significant.
struct s_number {
unsigned char *bytes;
unsigned int size;
};
typedef struct s_number s_num;
// This function build a s_num able to store [size] bytes.
// Returns the corresponding s_num pointer or NULL if something goes wrong.
s_num *new_num(unsigned int size) {
s_num *num = malloc(sizeof(s_num));
if (num != NULL) {
num->bytes = malloc(size);
if (num->bytes == NULL) {
perror("Failed to allocate. ");
free(num);
return NULL;
}
if (memset(num->bytes, 0, size) == NULL) {
perror("Failed to initialize. ");
free(num->bytes);
free(num);
return NULL;
}
num->size = size;
}
return num;
}
// This function deallocate the provided s_num.
// Returns 0 or anything else if something goes wrong.
int free_num(s_num *num) {
if (num != NULL) {
if (num->bytes != NULL) free(num->bytes);
free(num);
}
return 0;
}
// This function build a copy of the provided s_num.
// Returns the corresponding s_num pointer or NULL if something goes wrong.
s_num *dup_num(s_num *num) {
s_num *dup;
if (num == NULL) return NULL;
dup = new_num(num->size);
if (dup == NULL) {
perror("Failed to allocate a dup. ");
return NULL;
}
if (memcpy(dup->bytes, num->bytes, num->size) == NULL) {
perror("Failed to duplicate. ");
free_num(dup);
return NULL;
}
return dup;
}
// This function extend the byte array up to [size] and fill the new extent
// with 0.
// Returns the s_num pointer or NULL if something goes wrong.
s_num *extend_num(s_num *num, unsigned int size) {
unsigned char *tmp;
if (num == NULL) return NULL;
if (size > num->size) {
tmp = realloc(num->bytes, size);
if (tmp == NULL) {
perror("Failed to re allocate. ");
return NULL;
}
num->bytes = tmp;
if (memset(num->bytes + num->size, 0, size - num->size) == NULL) {
perror("Failed to initialize. ");
return NULL;
}
}
return num;
}
// A simple method to display s_num, in decimal up to 8 bytes, in hex after.
// Returns anything other than 0 if something goes wrong.
int display_num(s_num *num) {
if (num == NULL) return 1;
unsigned int size = num->size;
if (size > 8) {
printf(" => 0x");
while(size-- > 0) { printf("%02X", num->bytes[size]); }
printf("\n");
} else {
if (size > 0) {
unsigned long long fordisp = 0;
while(size-- > 0) { fordisp += ((unsigned long long )num->bytes[size]<<(8*size)); }
printf("%llu\n", fordisp);
} else{
printf("Empty\n");
}
}
return 0;
}
// Fibonacci processor, it adds B to A and return a copy of the original A.
s_num *fib(s_num *a, s_num *b) {
unsigned char *a_offset;
unsigned char *b_offset;
unsigned int b_size;
unsigned int a_size;
unsigned char carry;
unsigned char next_carry;
s_num *dup = NULL;
if (a == NULL || b == NULL) return NULL;
if (a->bytes != NULL && b->bytes != NULL) {
// We keep a duplicate of A, as B should become A at the end
dup = dup_num(a);
if (dup == NULL) return NULL;
if (extend_num(a, b->size) == NULL) {
free_num(dup);
return NULL;
}
// Offsets pointers for A and B, and their respective size in bytes
a_offset = a->bytes;
a_size = a->size;
b_offset = b->bytes;
b_size = b->size;
// The carry we may have to port byte to byte, initialy 0.
carry=0;
// We consider at first all the bytes from A, adding from B while we can.
while(a_size-- > 0) {
if (b_size > 0) {
// While we have bytes in B, we add them, carry included, to the
// corresponding bytes in A
if ((unsigned int) *a_offset + *b_offset + carry > 255u) {
next_carry=1;
} else {
next_carry=0;
}
// The following line is in fact :
//*a_offset++ += *b_offset++ + carry;
// We have anyway to let the C compiler know that we look voluntary to
// discard any overflow from the unsigned char cast, as we already have
// the carry from the preceding code.
*a_offset = (unsigned char) ((unsigned int)*a_offset + *b_offset + carry); a_offset++; b_offset++;
carry = next_carry;
b_size--;
} else {
// No more bytes in B, if there is no carry left, we can leave the loop
if (carry == 0) break;
// If there is a carry left, we add it to A. The resulting addition
// can also imply another carry.
if ((unsigned int) *a_offset + carry > 255u) {
next_carry=1;
} else {
next_carry=0;
}
// The following line is in fact :
//*a_offset++ += carry;
// We have anyway to let the C compiler know that we look voluntary to
// discard any overflow from the unsigned char cast, as we already have
// the carry from the preceding code.
*a_offset = (unsigned char) ((unsigned int)*a_offset + carry); a_offset++;
carry = next_carry;
}
}
// When the carry implies one more byte for the number
if (carry > 0) {
if (extend_num(a, a->size + 1) == NULL) {
free_num(dup);
return NULL;
}
a->bytes[a->size++] = carry;
}
}
// We return the copy of the original A
return dup;
}
// Your nth function adapted to work with s_num and able to take a start point
// from fibonacci current and previous.
// Beware that the function will free the s_num provided in previous.
s_num *nth(unsigned int n, s_num *current, s_num *previous)
{
// We define A and B as s_num
s_num *a = NULL;
s_num *b = NULL;
unsigned int start_i = 0;
// Do we have previous fibonacci s_num provided ?
if (previous != NULL && current != NULL && previous != current) {
// If we have only the previous fibonacci, we need one more compute
// to take a starting point.
a = current;
b = previous;
// If a previous fibonacci is provided, we consider it as the immediatly
// preceding fibonacci number for n
start_i = n - 1;
} else {
// If there is no start s_num provided,
// we define A as a s_num number 1 with 1 byte in size.
a = new_num(1);
if (a == NULL) return NULL;
*(a->bytes) = 1;
// And we define B as a s_num number 0 with 1 byte in size.
b = new_num(1);
if (b == NULL) {
free_num(a);
return NULL;
}
}
s_num *tmp;
for (; start_i < n; ++start_i) {
// We get in tmp a copy of the original A, as it will become B
tmp = fib(a, b);
if (tmp == NULL) {
free_num(a);
free_num(b);
return NULL;
}
free_num(b);
b = tmp;
}
free_num(b);
// We return a pointer to A, as it contains our corresponding result.
// It is here the caller responsibility to free it.
return a;
}
// We produce the 100 first fibonacci number from 0
int main(int nbargs, char *argc[]) {
s_num *num = NULL;
s_num *previous_num = NULL;
s_num *previous_previous_num = NULL;
unsigned int limit = 100u;
if (nbargs > 1 ) {
limit=(unsigned int)strtol(argc[1], NULL, 10u);
}
for (unsigned int i = 0u; i < limit; ++i) {
printf("%uth fib: ", i);
num = nth(i, previous_num, previous_previous_num);
if (num != NULL) display_num(num);
// No need to free num here, as we will reuse it for the next iteration,
// then it will be the next nth call that will free num.
// We have only then to free it if we leave the loop.
previous_previous_num = previous_num ;
previous_num = num;
}
if (num != NULL) free_num(num);
// Here, as we are out of the loop, we are freeing "previous" as
// "previous_previous_num" received it from the last iteration.
if (previous_previous_num != NULL && previous_previous_num != num) free_num(previous_previous_num);
// No more required for actual ANSI C
// return 0;
}
Extract of the output for N = 10000 :
0th fib: 1
1th fib: 1
2th fib: 2
3th fib: 3
4th fib: 5
5th fib: 8
6th fib: 13
7th fib: 21
8th fib: 34
9th fib: 55
10th fib: 89
11th fib: 144
12th fib: 233
13th fib: 377
..
90th fib: 4660046610375530309
91th fib: 7540113804746346429
92th fib: 12200160415121876738
93th fib: => 0x0111F38AD0840BF6BF
94th fib: => 0x01BB433812A62B1DC1
95th fib: => 0x02CD36C2E32A371480
96th fib: => 0x048879FAF5D0623241
97th fib: => 0x0755B0BDD8FA9946C1
..
9999th fib: => 0x26455354C816C43235B9A5B9708A80EC209E5A36521B054E1F08B364AC5F9EA8A618BA6203D6598679F82A57B25E5727326C1BEC42026ED6BB5E577D20563519B1086FA78E79A13DF45829FA84BFD0AB6F0B2DBEB34CDD8BE556F2BA12DC96342BC50CD1C313479C2C83AFDFDD28C1F9FCFF8EE23EEEE443349BA0964E0AA29F35941217D12487CECACDC9CCC9B77D11D14F72BCCC265FD0FE7F831747EBE7634B9A246915F996315C79DE01E48EFA8A52CAAE6BE757783411BE20664AB19D18CC63AF13E623895D5C879D5F3B1D5768317FBF95DC91FBF8402131015E5F5154F3B14DCFDA6C3E88BABEE1BA117394C9EE4360096BDF6650209D8005BCC5E2459072F8066895C7331F271051F2830EDDCC8A0102DF15711544823B820D863EC63AB8ED88A777D4C7CFED7563DAB155C06D057C0BACB621E2D50B7A655E647EA443C8555005BB5D7066096A2E811D53571E24181DFE37FF0979AF3B063B133BDC511FE7FC3E71C74D2529F1E6C218F213EECF09A09194857B1130A3E8DFD9CF3B38E6A18A68103C4698D3E014DC8D6D59EC1C6D2478BD16E42A20FBCB81B03C86470AFE986FE20AD2C54706CD01D198BCC78BF5A0B0C6FA15C2585647635F965925246AF87C8D05CC0F072355F3D31867944AEF1C0AD65B32DA8121EBBC36AC1A3554BEE17AB8E680DB4C6F305AE9836CA2B8BEEB64D2B1BD5F6B801139AEB8298BF53AE4EEA0B4237965F95C6CBC92F5BE3427CBD0B2E8771C54B578032F865CD74E66CB093D51B51F808308B71FCAFE88250528A3F5D1E308A1A9CE9872547FA5ACC2CF434B9503B368066143606EA5458B0B9ED1538A465EAA4638A340B8AB274AAAC060A56F2D2FA639B7A8CBF00ADAD2286AB2B299C9ADF471647736E8B97B5A6F8781CF0707617BE5570BB649C47E122F6D4781BF97BC02BFBDF59D558820DF190348081A3028FA2F3EFBF486D2F69AEB5C8FB963F27BF01300F047E4989C9CAD353A1EE19AA20752F5789EA65AAEFC62DD5F836456C17B08B5194C682118570AEBDFECD446A1F63AE261A299C23C6AB19E7B2758E4FE91D35D8FE1D5DFF7359FB73A5DEDB172765B205628AC2DCF0DE6865874CCC0CB5369623FB3E96F09A07D07F4753F50034CCACE3542ED83D69BBD346E43A1D4BF5C229A116B35F9F98E4C8752CA26035035F30F7DB929B9C06FA898222219DEE5079FAAD824476D4A0819DB
Program Explain:
1/2/3
2 3 5
2 9 4
2 5 7
if i write 1in up it give me 2+9+7
if i write 2in up it give me 5+9+2
if i write 3in up it give me (2+9+7)-(5+9+2)
(BUT IT GIVES WARING:
* stack smashing detected *: unknown terminated
Aborted (core dumped)
)
#include <stdio.h>
#include <math.h>
int main()
{
int whatUDo;
int square[2][2];
int counter1 = 0, counter2 = 0, counter3 = 0;
int threeTime = 3;
scanf("%d", &whatUDo);
while (counter1 < 3)
{
scanf("%d", &square[0][counter1]);
counter1++;
}
while (counter2 < 3)
{
scanf("%d", &square[1][counter2]);
counter2++;
}
while (counter3 < 3)
{
scanf("%d", &square[2][counter3]);
counter3++;
}
int first = square[0][0] + square[1][1] + square[2][2];
int second = square[0][2] + square[1][1] + square[2][0];
int third = first - second;
if (whatUDo == 1)
{
printf("%d", first);
}
else if (whatUDo == 2)
{
printf("%d", second);
}
else if (whatUDo == 3)
{
printf("%d", third);
}
return 0;
}
TL;DR
The size of your array is wrong.
For the code you have provided, you have to declare your array as
int square[3][3];
Because the boundaries you are handling are from 0..2 and 0..2, respectively. The number you specify when declaring the array is the size, not the maximum index allowed.
In other way, if you declare:
int myarray[5];
The items of your array are accessed from 0 to 4, and your array has a capacity of 5 items accessed by the indices 0, 1, 2, 3 and 4.
● int vectorInsert(Vector * array, int index, Data value);
I am doing
If this can be corrected according to the given statement.
I am calling it using
Vector *vect = initVector();
Data data_array[20];
for(i = 0 ; i < 20 ; i++){
data_array[i].value = (rand() % 20) + 1;
vectorInsert(vect, i, data_array[i]);
}
There are a couple of errors in your code, but the most important one is in your initVector function, you actually need to allocate memory for the vector.
You also need to do the following things:
in initVector return v instead of v->data or &v
in vectorInsert print array->data[index].value instead of array->data[index]
in vectorInsert return 1 on success, add error checking in your allocation and return 0 on memory error.
All of these except the original malloc were warnings returned by the compiler.
First, according to your specifications, max_size should be an unsigned integer, so I changed Vector to reflect this, using size_t. I also changed the related format specifiers from %d to %zu to match this new type.
Your initVector() function needed to allocate memory for a Vector, so that has been added. Furthermore, there was no need to allocate memory for the dynamic array of Data structs here, so v->data is set to NULL. This function should also return the pointer to the newly allocated memory, v, instead of a pointer to the .data field of this Vector, as you originally had.
In the vectorInsert() function, you neglected to check for memory allocation errors, so I added a check after the attempted allocation which returns 0 if there is an error. After inserting the new Data struct, your check to increment .current_size is wrong. First, you need to increment if array->current_size <= index. Next, you need to add one to the .current_size, not set .current_size to one larger than the index value. Also, when printing the inserted value here, you forgot to access the .value field. I think that this may have been due to the confusing name that you used for the Data struct that you passed into vectorInsert(). You call this struct value, so in the previous line we have array->data[index] = value, where you are assigning the struct value to array->data[index]. But in the call to printf() you want to show the value held by the struct value. Choosing better names is always a win! Finally, this function returns 1 on a successful insertion.
I added to your test code to display the contents of vect and vect->data, and also added a Data struct, test_insert, to test insertion into an arbitrary index.
Finally, you need to free memory allocations after all of this, so I added a couple of calls to free().
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
int value;
}Data;
/* Specs say that max_size should be an unsigned integer */
typedef struct{
size_t max_size; //initialize to 0
size_t current_size; //initialize to 0
Data *data; // array of integers we're storing
} Vector;
/* Modified function */
Vector * initVector(void){
Vector *v = malloc(sizeof(*v));
v->max_size=0;
v->current_size=0;
v->data = NULL;
return v;
}
int vectorInsert(Vector * array, size_t index, Data value)
{
if(index >= array->max_size)
{
array->max_size = index * 2 + 1;
printf("Inside Vect max_size is : %zu\n", array->max_size);
Data *new_array = malloc(sizeof(Data) * array->max_size);
/* Added check for allocation error */
if (new_array == NULL)
return 0;
if(array->data != NULL)
{
memcpy(new_array, array->data, sizeof(Data)*array->current_size);
free(array->data);
array->data = NULL;
}
array->data = new_array;
}
array->data[index] = value;
printf("Main : %d\n", array->data[index].value);
/* Modified current_size increment logic */
if(array->current_size <= index)
{
array->current_size += 1;
}
/* Successful insertion */
return 1;
}
int main(void)
{
size_t i;
Vector *vect = initVector();
Data data_array[20];
Data test_insert = { -5 }; // to test index insertion
for(i = 0 ; i < 20 ; i++){
data_array[i].value = (rand() % 20) + 1;
vectorInsert(vect, i, data_array[i]);
}
/* Display results */
printf("vect->max_size = %zu\n", vect->max_size);
printf("vect->current_size = %zu\n", vect->current_size);
printf("vect->data contains:\n");
for (i = 0; i < vect->current_size; i++)
printf("%d ", vect->data[i].value);
putchar('\n');
/* Insert test_insert at index 5 */
vectorInsert(vect, 5, test_insert);
/* Display results */
printf("vect->max_size = %zu\n", vect->max_size);
printf("vect->current_size = %zu\n", vect->current_size);
printf("vect->data contains:\n");
for (i = 0; i < vect->current_size; i++)
printf("%d ", vect->data[i].value);
putchar('\n');
/* Free memory allocations */
free(vect->data);
free(vect);
return 0;
}
And here is a sample of the results:
vect->max_size = 31
vect->current_size = 20
vect->data contains:
4 7 18 16 14 16 7 13 10 2 3 8 11 20 4 7 1 7 13 17
vect->max_size = 31
vect->current_size = 20
vect->data contains:
4 7 18 16 14 -5 7 13 10 2 3 8 11 20 4 7 1 7 13 17
Enable all warnings and debug info in your compiler (e.g. compile with gcc -Wall -g). Then it should warn you about
Vector * initVector(){
Vector *v; /// UNINITALIZED
v->max_size=0;
v->current_size=0;
v->data = malloc(sizeof(int)*v->max_size);
return v->data;
// return (&v);
}
So you have an undefined behavior, and that is awfully bad.
(Of course the compiler will give a lot of other warnings, and you should improve your code till you got no warnings at all. Then you should use the gdb debugger)
You might want to read about flexible array members.
Consider perhaps having at least:
Vector* createVector(int maxsize) {
if (maxsize<=0)
{ fprintf(stderr, "bad maxsize=%d\n", maxsize); exit(EXIT_FAILURE); };
Vector* v = malloc(sizeof(Vector));
if (!v) { perror("malloc Vector"); exit(EXIT_FAILURE); };
v->data = malloc(sizeof(Data)*maxsize);
if (!v->data) { perror("malloc data"); exit(EXIT_FAILURE); };
v->max_size = maxsize;
v->current_size = 0;
memset(v->data, 0, sizeof(Data)*maxsize);
return v;
}
I'm attempting to store arrays of integers that I read from a file (with a separate function) in a 2D array but I keep having issues with Segmentation fault. I know it's an issue with my pointers but I can't figure out exactly what I'm doing wrong.
Here is my function (takes an integer and compares it with an integer read from a file before storing it in my 2D array).
int **getStopTimes(int stop_id) {
int **result = malloc(sizeof(*result));
char const* const fileName = "stop_times_test.txt";
FILE* txt = fopen(fileName, "r");
char line[256];
int count = 0;
while (fgets(line, sizeof(line), txt) != NULL) {
int *formattedLine = getStopTimeData(line); //getStopTimeData returns a pointer to an array of ints, memory is allocated in the function
if (formattedLine[1] == stop_id) {
result[count] = formattedLine;
count++;
}
}
fclose(txt);
return result;
}
And my main:
int main(int argc, char *argv[]) {
int **niceRow = getStopTimes(21249);
for (int i=0; i<2; i++) { //Only looping 3 iterations for test purposes
printf("%d,%d,%d,%d\n",niceRow[i][0], niceRow[i][1], niceRow[i][2], niceRow[i][3]);
}
free(niceRow);
return 0;
}
getStopTimeData function thats being called (Pulls certain information from an array of chars and stores/returns them in an int array):
int *getStopTimeData(char line[]) {
int commas = 0;
int len = strlen(line);
int *stopTime = malloc(4 * sizeof(*stopTime)); //Block of memory for each integer
char trip_id[256]; //Temp array to build trip_id string
char stop_id[256]; //Temp array to build stop_id string
int arrival_time; //Temp array to build arrival_time string
int departure_time; //Temp array to build departure_time string
int counter;
for(int i = 0; i <len; i++) {
if(line[i] == ',') {
commas++;
counter = 0;
continue;
}
switch(commas) { //Build strings here and store them
case 0 :
trip_id[counter++] = line[i];
if(line[i+1] == ',') trip_id[counter] = '\0';
break;
case 1: //Convert to hours past midnight from 24hr time notation so it can be stored as int
if(line[i] == ':' && line[i+3] == ':') {
arrival_time = (line[i-2]-'0')*600 + (line[i-1]-'0')*60 + (line[i+1]-'0')*10 + (line[i+2]-'0');
}
break;
case 2 :
if(line[i] == ':' && line[i+3] == ':') {
departure_time = (line[i-2]-'0')*600 + (line[i-1]-'0')*60 + (line[i+1]-'0')*10 + (line[i+2]-'0');
}
break;
case 3 :
stop_id[counter++] = line[i];
if(line[i+1] == ',') stop_id[counter] = '\0';
break;
}
}
//Assign and convert to ints
stopTime[0] = atoi(trip_id);
stopTime[1] = atoi(stop_id);
stopTime[2] = arrival_time;
stopTime[3] = departure_time;
return stopTime;
}
This line:
int **result = malloc(sizeof(*result));
allocates just memory for one single pointer. (*result is of type int *, so it's a pointer to data -- the sizeof operator will tell you the size of a pointer to data ... e.g. 4 on a 32bit architecture)
What you want to do is not entirely clear to me without seeing the code for getStopTimeData() ... but you definitely need more memory. If this function indeed returns a pointer to some ints, and it handles allocation correctly, you probably want something along the lines of this:
int result_elements = 32;
int **result = malloc(sizeof(int *) * result_elements);
int count = 0;
[...]
if (formattedLine[1] == stop_id) {
if (count == result_elements)
{
result_elements *= 2;
result = realloc(result, result_elements);
}
result[count] = formattedLine;
count++;
}
Add proper error checking, malloc and realloc could return (void *)0 (aka null) on out of memory condition.
Also, the 32 for the initial allocation size is just a wild guess ... adapt it to your needs (so it doesn't waste a lot of memory, but will be enough for most use cases)
The upper answer is good,
just to give you an advice try to avoid using 2D array but use a simple array where you can store all your data, this ensures you to have coalescent memory.
After that, you can access your 1D array with an easy trick to see it like a 2D array
Consider that your 2D array has a line_size
To access it like a matrix or a 2d array you need to find out the corresponding index of your 1d array for given x,y values
index = x + y * line size;
In the opposite way:
you know the index, you want to find x and y corresponding to this index.
y = index / line_size;
x = index mod(line_size);
Of course, this "trick" can be used if you already know your line size
I am trying to write a program, but every time I try allocating memory, the 4th member of other array loses its meaning. Here is my code:
At first I read file with integer type numbers: In example. 1 2 3 1 2 3 1 2 3
int* reading (int* numbers, char* arg2[])
int* fuction(int* numbers);
int main(int arg1, char *arg2[] ){
if(arg1 != 2){return 0;}
int *numbers;
numbers = reading(numbers, arg2);
numbers = function(numbers);
return 0;
}
int* reading (int* numbers, char* arg2[]){
FILE *in=fopen(arg2[1], "r");
if (in == NULL) {
fprintf(stderr, "Can't open file !\n");
exit(1);
}
int data, length = 1;
numbers = (int*)malloc(3*sizeof(int));
while (fscanf(in, "%d", &data) != EOF){
numbers[length] = data;
length++;
numbers = realloc(numbers, length+1);
}
numbers[0] = length;
numbers[0]--;
return numbers;
}
int* fuction(int* numbers){
int sum = 0;
int i = 0;
int* places;
places = (int*)malloc(1*sizeof(int));
places[0] = 0;
for(i = 1; i <= numbers[0]; i++){ sum += numbers[i];}
if((((numbers[0]) % 3) > 0) || ((sum % ((numbers[0])/3)) > 0)){return places;}
sum = sum / ((numbers[0])/3);
int* newNumbers;
for(i = 1;i<=numbers[0];i++){printf("%d ", numbers[i]);}
printf("\n");
Here in cmd I see: 1 2 3 1 2 3 1 2 3
newNumbers = calloc(numbers[0]+1,sizeof(int) );
for(i = 1;i<=numbers[0];i++){printf("%d ", numbers[i]);}
printf("\n");
But after allocating memory for newNumbers(I tried both - malloc and calloc), I see result like this: 1 2 3 102506522 2 3 1 2 3
places = realloc(places, numbers[0]+1);
for(i = 1;i<=numbers[0];i++){printf("%d ", numbers[i]);}
printf("\n");
Here result stays the same: 1 2 3 102506522 2 3 1 2 3
}
Writing like this:
places = realloc(places, numbers[0]+1);
newNumbers = calloc(numbers[0]+1,sizeof(int) );
I mean allocating memory for "places" at first,
does not solve my problem as well. After:
newNumbers = calloc(numbers[0]+1,sizeof(int) );
I lose numbers[4]- meaning.
I can't understand why it is happening. Maybe someone could help me and give me an advice, how could I correct it.