Heap related questions - c

I know the forum has many questions about heap etc. but nothing helped me this much (except for the understanding of why it doesn't work).
I have a huge quantity of data and of course the heap can't follow. The data I need to store are only integers. Malloc starts returning null quite early.
4 arrays of size: (allocation by malloc)
875715
875715
875715
5105043 cells (but it's a 2D array)
Here are my questions:
1) To know the quantity of memory needed, is it:
875715 * 3 * 4 + 5105043 * 4 = 62454492 ? (because integer is 4)
Does it mean around 62 MB? (Sorry if it seems dumb)
2) How can we know the size of the heap available? Is there a way to increase it?
3) I have 3 arrays of the same size, is there an advantage of merging them into one 2D array?
For example, array[875715][3] instead of 3 different arrays (of course, by using malloc)
I use Window seven, 64 bit, 8GB of RAM.
EDIT: Here is a typical allocation I do for the 1D array and for the beginning of the 2D array (first level):
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define FILE_NAME "SCC.txt"
#define ARRAY_SIZE 875714
void getGgraph(int mode,int **graph,int *sizeGraph);
int sizeOfArray(int *array);
void getGraphSize(int mode,int *arr);
void runThroughGraph(int node,int **graph,int *exploredNode,int *magicalPath,int *sizeGraph);
void getMagicalPath(int *magicalPath,int **graph,int *sizeGraph);
void main()
{
int i, *magicalPath,*sizeGraph, **graph;
/* ------------- creation of the array sizeGraph ------------------ */ // contain the size of each level to initiate the array
if ((sizeGraph =(int*) malloc((ARRAY_SIZE + 1) * sizeof(sizeGraph[0]))) == NULL) {
printf("malloc of sizeGraph error\n");
return;
}
memset(sizeGraph, 0, (ARRAY_SIZE + 1) * sizeof(sizeGraph[0]));
/* ------------- create reverse G graph, this will be a 2D array ------------------ */
if ((graph =(int**) malloc((ARRAY_SIZE + 1) * sizeof(*graph))) == NULL) {
printf("malloc of graph error\n");
return;
}
getGgraph(1,graph,sizeGraph);
// [..... Some more code .....]
// end of main()
}
void getGgraph(int mode,int **graph,int *sizeGraph) {
char int_string[40];
char stringToAdd[10];
FILE *integerFile = NULL;
int i = 0, j = 0, n = 0,stCurrentInt, tail,head,*temp;
getGraphSize(mode,sizeGraph);
for (i = 0; i < (ARRAY_SIZE + 1); i++) {
if ((graph[i] =(int*) malloc((ARRAY_SIZE + 1) * sizeof(graph[i][0]))) == NULL) {
// THIS IS WHERE IT STOPS (i = 594)
printf("Malloc of graph[%d] error\n",i);
return;
}
}
if ((temp =(int*) malloc((ARRAY_SIZE + 1) * sizeof(temp[0]))) == NULL) {
printf("malloc of temp in getGgraph function error\n");
return;
}
memset(temp, 0, (ARRAY_SIZE + 1) * sizeof(temp[0]));
if ((integerFile = fopen(FILE_NAME, "r")) != NULL) {
while (fgets(int_string,40, integerFile) != NULL) {
n = 0, i = 0, stCurrentInt = 0,head = 0; // initialisation
while (int_string[n] != NULL) {
if (int_string[n] == ' ') {
for (j = stCurrentInt; j < n; j++) {
stringToAdd[j - stCurrentInt] = int_string[j];
}
if (stCurrentInt == 0) // first integer is the index
tail = (int) atoi(stringToAdd);
else {
head = atoi(stringToAdd);
if (mode == 0) {
graph[tail][temp[tail]] = head;
temp[tail]++;
}
else if (mode == 1) {
graph[head][temp[head]] = tail;
temp[head]++;
}
}
for (j = 0; j < 10; j++) { // empty the string for next iteration
stringToAdd[j] = NULL;
}
stCurrentInt = n + 1;
}
n++;
}
}
free(temp);
fclose(integerFile);
}
else {
printf("\n File missing in getGgraph.\n");
return;
}
}
void getGraphSize(int mode,int *arr) {
char int_string[40],stringToAdd[10];
FILE *integerFile = NULL;
int i = 0, j = 0, n = 0,stCurrentInt,tail,head;
if ((integerFile = fopen(FILE_NAME, "r")) != NULL) {
while (fgets(int_string,40, integerFile) != NULL) {
n = 0, i = 0, stCurrentInt = 0,head = 0; // initialisation
while (int_string[n] != NULL) {
if (int_string[n] == ' ') {
for (j = stCurrentInt; j < n; j++) {
stringToAdd[j - stCurrentInt] = int_string[j];
}
if (stCurrentInt == 0) // first integer is the index
tail = (int) atoi(stringToAdd);
else
head = atoi(stringToAdd);
for (j = 0; j < 10; j++) { // empty the string for next iteration
stringToAdd[j] = NULL;
}
stCurrentInt = n + 1;
}
n++;
}
if (mode == 0 && head != 0)
arr[tail]++;
else if (mode == 1 && head != 0)
arr[head]++;
}
}
else {
printf("\n File missing in getGraphSize.\n");
return;
}
}
EDIT2: My program actually works like a charm for smaller inputs.
[..... Some more code .....]: this is after the issue. The failing malloc is inside getGraph, so I don't think the rest is relevant. I free() the arrays later on in the program.

without pulling out a calculator, and without your code, your analysis looks right.
The HEAP will grow as needed, constrained only by OS process limits.. By default, under windows, you get no more that 2Gig. Here's a more specific link.
no significant advantage.
In your case you'd be better served by adjusting your memory allocation algorithms to allocate what you need and no more.

Related

Realloc failing after second call

I'm attempting to read in a list of words to be sorted and I start out with a fairly small array (10 elements) and then would like to increase the size of the array by 10 if the current capacity isn't enough. This seems to work with the first realloc, but I get a SIGABRT when trying to call realloc again. I'm sure it is a simple thing I'm not seeing, but I can't seem to figure it out. Here is my program:
int main(int argc, char *argv[]){
char *string = malloc(100);
// Array of pointers starting with 100 elements
char **toSort = malloc(100*sizeof(char *));
if(toSort == NULL) {
exit(1);
}
for(int i = 0; i < 100; i++) {
// Each string can be up to 100 characters long
toSort[i] = malloc(101);
if(toSort[i] == NULL) {
exit(1);
}
}
// Get all lines in the file
int counter = 0;
int max = 10;
char *toAdd;
FILE *txt = fopen("wlist0.txt", "r");
while(fgets ( string, 100, txt ) && counter < max) {;
toAdd = malloc(100);
if(toAdd == NULL) {
exit(1);
}
strcpy(toAdd, string);
toSort[counter] = string;
counter++;
//if the array needs to be enlarged
if(counter == max) {
char **new = realloc(toSort, (max+10) * sizeof(char));
if(new == NULL) {
exit(1);
}
for(int i = max; i < max + 10; i++) {
toSort[i] = malloc(101);
if(toSort[i] == NULL) {
exit(1);
}
}
toSort = new;
max += 10;
}
};
for(int i = 0; i < max; i++) {
char *word = toSort[i];
printf("%s", word);
}
for(int i = 0; i < max; i++) {
free(toSort[i]);
}
free(toSort);
return 0;
};
Like my comments say, my strings have a maximum length of 100 characters. I suppose I could dynamically allocate memory for the strings as well, but I'll worry about that when I have the other realloc working. Any help would be greatly appreciated.
This code assigns values to toSort after it the memory it points to is freed/modified by realloc():
//if the array needs to be enlarged
if(counter == max) {
char **new = realloc(toSort, (max+10) * sizeof(char));
if(new == NULL) {
exit(1);
}
for(int i = max; i < max + 10; i++) {
toSort[i] = malloc(101); <--- toSort is invalid here
if(toSort[i] == NULL) {
exit(1);
}
}
toSort = new;
max += 10;
}
This will work better:
//if the array needs to be enlarged
if(counter == max) {
char **new = realloc(toSort, (max+10) * sizeof( *new )); <-- fixed here, too
if(new == NULL) {
exit(1);
}
toSort = new;
for(int i = max; i < max + 10; i++) {
toSort[i] = malloc(101);
if(toSort[i] == NULL) {
exit(1);
}
}
max += 10;
}
There may be other errors in your code. I haven't fully examined it.

Plain C: Binary Heap Segmentation Faults/Reallocation Errors

I am VERY new to C, but I thought that I'd learn it while I'm learning basic data structures. Anyway, I'm having a problem wrapping my head about how/where errors are coming up in my code.
Basically, I'm getting two different kinds of errors:
Segmentation Faults (# binary heap length 2 and 3) when subtracting from heap.
Malloc/Realloc errors when I add to binary heap enough to make it to length 4 (and beyond), and then subtract to length 2 (I get a non-valid binary heap structure # length 3 when I do this as well).
Basically, I just want to see what exactly I'm doing wrong to get this behavior. Also, if there's anything in my code that is downright appaling, I'd like to know that too.
So, here's my code:
void printArray(int array[], int size) {
printf("[");
for (int i = 0; i < size; i++) {
if (i == (size - 1)) {
printf("%d", array[i]);
} else {
printf("%d, ", array[i]);
}
}
printf("]\n");
}
int getLeftChild(int h_array[], int p_index, int size) {
/* Summary: Obtains the `left child` of Parent at given parent index (p_index)
*
* Input: `h_array` - The binary heap
* `p_index` - The index of the parent that we are currently looking at
* `size` - The size of the binary heap.
*
* Return: `0` if the index given points out of bounds of the array. Returns the child of parent at p_index if not
*/
int child = 0;
if (p_index * 2 + 1 < size) {
child = h_array[p_index * 2 + 1];
}
return child;
}
int getRightChild(int h_array[], int p_index, int size) {
/* Summary: Obtains the `right child` of Parent at given parent index (p_index)
*
* Input: `h_array` - The binary heap
* `p_index` - The index of the parent that we are currently looking at
* `size` - The size of the binary heap.
*
* Return: `0` if the index given points out of bounds of the array. Returns the child of parent at p_index if not
*/
int child = 0;
if ((p_index * 2 + 2) < size) {
child = h_array[p_index * 2 + 2];
}
return child;
}
void heapSort(int h_array[], int size, int min_max) {
/* Summary: Performs a heap sort on a binary heap array; parents with 2 children maximum.
* This could be used to implement a priority queue, as the node with the highest (or lowest)
* priority will be at the root of the list.
* Input: `h_array` - the heap array to sort
* `size` - The size of the heap array
* `min_max` - an input that will tell whether or not we want to return a 'maxed', or a 'min'd' binary heap.
* maxed will have highest priority at the root, and min'd will have the lowest priority at the root
*
* Returns: Does not return. Performs all sorting operations on input array.
**/
int parent, leftChild, rightChild, p_holder, i = 0;
while (i < (size / 2)) {
parent = h_array[i];
leftChild = getLeftChild(h_array, i, size);
rightChild = getRightChild(h_array, i, size);
if (min_max == 0 ) {
while (parent < leftChild || parent < rightChild) {
p_holder = parent;
if (parent < leftChild) {
h_array[i] = leftChild;
h_array[(i * 2) + 1] = p_holder;
} else if (parent < rightChild) {
h_array[i] = rightChild;
h_array[(i * 2) + 2] = p_holder;
}
i = 0;
parent = h_array[i];
leftChild = getLeftChild(h_array, i, size);
rightChild = getRightChild(h_array, i, size);
}
i++;
} else {
while ((leftChild != 0 && parent > leftChild) || (rightChild != 0 &&parent > rightChild)) {
p_holder = parent;
if ((leftChild != 0) && parent > leftChild) {
h_array[i] = leftChild;
h_array[(i * 2) + 1] = p_holder;
} else if ((rightChild != 0) && parent > rightChild) {
h_array[i] = rightChild;
h_array[(i * 2) + 2] = p_holder;
}
i = 0;
parent = h_array[i];
leftChild = getLeftChild(h_array, i, size);
rightChild = getRightChild(h_array, i, size);
}
i++;
}
}
}
void heapAdd(int h_array[], int *a_size, int value, int *min_max_ptr) {
/* Summary: Adds a value to the binary heap
* Input: `h_array` - The binary heap array
* `a_size` - The size of the array. A pointer to `size` located in main().
* `value` - The value that is to be inserted in the array
* Returns: Void function. Performs all operations on inputted array.
*/
*a_size += 1;
int * a_copy = h_array;
h_array = realloc(h_array, *a_size * sizeof(int));
memcpy(h_array, a_copy, (*a_size - 2) * sizeof(int));
h_array[*a_size - 1] = value;
heapSort(h_array, *a_size, *min_max_ptr);
}
void heapSub(int h_array[], int *a_size, int *min_max_ptr) {
/* Summary: Subtracts the root value from the binary heap
* Input: `h_array` - The binary heap array
* `a_size` - The size of the array. A pointer to `size` located in main().
* Returns: Void function. Performs all operations on inputted array.
*/
h_array[0] = h_array[*a_size - 1];
int * a_copy = h_array;
h_array = realloc(h_array, *a_size - 1 * sizeof(int));
memcpy(h_array, a_copy, (*a_size - 1) * sizeof(int));
*a_size -= 1; // Put here in order to not do any stupid calculations in the calls.
heapSort(h_array, *a_size, *min_max_ptr);
}
int main(void) {
char * user_input;
int user_value;
int debug = 0;
// min_max = 0 to produce a max-heap, min_max = 1 to produce a min-heap
int min_max = 0;
int *min_max_ptr = &min_max;
int size = 0;
int *size_ptr = &size;
// Binary Heap array, initialized here
int * main_array = malloc(size * sizeof(int));
// Start building binary heap with the following loop.
while (strcmp(user_input, "q") != 0) {
printf("Current Heap:\n");
printArray(main_array, size);
// Debug
if (debug) {
printf("Current Heap Size: %i\n", size);
}
printf("What is your input?: ");
scanf("%s", user_input);
// Debug
if (debug) {
printf("Current user input is: %s\n", user_input);
}
if (strcmp(user_input, "add") == 0) {
printf("What # will you be adding to the heap?: ");
scanf("%i", &user_value);
heapAdd(main_array, size_ptr, user_value, min_max_ptr);
} else if (strcmp(user_input, "sub") == 0) {
printf("Subtracting %i from array\n", main_array[0]);
heapSub(main_array, size_ptr, min_max_ptr);
} else if (strcmp(user_input, "debug") == 0) {
printf("Do you want to toggle debug mode(y/n): ");
scanf("%s", user_input);
if (strcmp(user_input, "y") == 0) {
debug = (debug == 0) ? 1 : 0;
printf("Debug is: %i", debug);
} else {
continue;
}
} else {
printf("Incorrect Input, please read the instructions more\n\n");
}
printf("\n");
}
free(main_array);
return 0;
}
So that's the code, and here are the test cases:
Subtracting highest value from heap # length = 2 test case 1
Subtracting highest values from heap starting # length = 4 and going to length = 2 test case 2
After that it seems like every other test case works fine (past length = 4 I can add and subtract from binary heap just fine and the sorting process works great). Thank you for your help :)
I was able to reach a solution to my problems by making the following changes to my code:
void heapAdd(int h_array[], int *a_size, int value, int *min_max_ptr) {
/* Summary: Adds a value to the binary heap
* Input: `h_array` - The binary heap array
* `a_size` - The size of the array. A pointer to `size` located in main().
* `value` - The value that is to be inserted in the array
* Returns: Void function. Performs all operations on inputted array.
*/
*a_size += 1;
h_array[*a_size - 1] = value;
heapSort(h_array, *a_size, *min_max_ptr);
}
void heapSub(int h_array[], int *a_size, int *min_max_ptr) {
/* Summary: Subtracts the root value from the binary heap
* Input: `h_array` - The binary heap array
* `a_size` - The size of the array. A pointer to `size` located in main().
* Returns: Void function. Performs all operations on inputted array.
*/
h_array[0] = h_array[*a_size - 1];
h_array[*a_size - 1] = 0;
*a_size -= 1; // Put here in order to not do any stupid calculations in the calls.
heapSort(h_array, *a_size, *min_max_ptr);
}
int main(void) {
char * user_input;
int user_value;
int debug = 0;
// min_max = 0 to produce a max-heap, min_max = 1 to produce a min-heap
int min_max = 0;
int *min_max_ptr = &min_max;
int size = 0;
int *size_ptr = &size;
int alloc_size = 1000;
int * main_array = malloc(alloc_size * sizeof(int));
do {
if (alloc_size - size < 2) {
printf("Reallocating the main_array size");
alloc_size += 1000;
main_array = realloc(main_array, alloc_size * sizeof(int));
if (main_array == NULL) {
printf("realloc addition failed, exiting");
exit(1);
}
} else if (alloc_size - size > 1002) {
alloc_size -= 1000;
main_array = realloc(main_array, alloc_size * sizeof(int));
if (main_array == NULL) {
printf("Realloc subtraction failed, exiting");
exit(1);
}
}
printf("Current Heap:\n");
printArray(main_array, size);
// Debug
if (debug) {
printf("Current Heap Size: %i\n", size);
}
printf("What is your input?: ");
scanf("%s", user_input);
// Debug
if (debug) {
printf("Current user input is: %s\n", user_input);
}
if (strcmp(user_input, "add") == 0) {
printf("What # will you be adding to the heap?: ");
scanf("%i", &user_value);
heapAdd(main_array, size_ptr, user_value, min_max_ptr);
} else if (strcmp(user_input, "sub") == 0) {
if (size == 0) {
printf("Can't subtract any more from the heap.\n");
continue;
} else {
printf("Subtracting %i from array\n", main_array[0]);
heapSub(main_array, size_ptr, min_max_ptr);
}
} else if (strcmp(user_input, "debug") == 0) {
printf("Do you want to toggle debug mode(y/n): ");
scanf("%s", user_input);
if (strcmp(user_input, "y") == 0) {
debug = (debug == 0) ? 1 : 0;
printf("Debug is: %i", debug);
} else {
continue;
}
} else {
printf("Incorrect Input, please read the instructions more fully\n\n");
}
printf("\n");
} while (strcmp(user_input, "q") != 0);
free(main_array);
return 0;
}

returning string in C function [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I was trying to solve CountAndSay problem at one of the online coding site but I am not able to get why my program is printing NULL. I am sure I am doing some conceptual mistake but not getting it.
Here is my code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* countAndSay(int A) {
int i,j,k,f,count;
char a;
char *c = (char*)malloc(sizeof(char)*100);
char *temp = (char*)malloc(sizeof(char)*100);
c[0] = 1;c[1] = '\0';
for(k=2; k<=A; k++)
{
for(i=0, j=0; i<strlen(c); i++)
{
a = c[i];
count = 1;
i++;
while(c[i] != '\0')
{
if(c[i]==a)
{
count++;
i++;
}
else if(c[i] != a)
{
i--;
break;
}
else
{
break;
}
}
temp[j] = count;
temp[j+1] = a;
j += 2;
}
*(temp+j) = '\0';
if(k<A)
{
for(j=0; j<strlen(temp); j++)
{
c[j] = temp[j];
}
c[j] = '\0';
}
}
return temp;
}
int main(void) {
// your code goes here
char *c = countAndSay(8);
printf("%s\n",c);
return 0;
}
The idea is not that bad, the main errors are the mix-up of numerical digits and characters as shown in the comments.
Also: if you use dynamic memory, than use dynamic memory. If you only want to use a fixed small amount you should use the stack instead, e.g.: c[100], but that came up in the comments, too. You also need only one piece of memory. Here is a working example based on your code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ALL CHECKS OMMITTED!
char *countAndSay(int A)
{
int k, count, j;
// "i" gets compared against the output of
// strlen() which is of type size_t
size_t i;
char a;
// Seed needs two bytes of memory
char *c = malloc(2);
// Another pointer, pointing to the same memory later.
// Set to NULL to avoid an extra malloc()
char *temp = NULL;
// a temporary pointer needed for realloc()-ing
char *cp;
// fill c with seed
c[0] = '1';
c[1] = '\0';
if (A == 1) {
return c;
}
// assuming 1-based input, that is: the first
// entry of the sequence is numbered 1 (one)
for (k = 2; k <= A; k++) {
// Memory needed is twice the size of
// the former entry at most.
// (Averages to Conway's constant but that
// number is not usable here, it is only a limit)
cp = realloc(temp, strlen(c) * 2 + 1);
temp = cp;
for (i = 0, j = 0; i < strlen(c); i++) {
//printf("A i = %zu, j = %zu\n",i,j);
a = c[i];
count = 1;
i++;
while (c[i] != '\0') {
if (c[i] == a) {
count++;
i++;
} else {
i--;
break;
}
}
temp[j++] = count + '0';
temp[j++] = a;
//printf("B i = %zu, j = %zu\n",i,j-1)
//printf("B i = %zu, j = %zu\n",i,j);
}
temp[j] = '\0';
if (k < A) {
// Just point "c" to the new sequence in "temp".
// Why does this work and temp doesn't overwrite c later?
// Or does it *not* always work and fails at one point?
// A mystery! Try to find it out! Some hints in the code.
c = temp;
temp = NULL;
}
// intermediate results:
//printf("%s\n\n",c);
}
return temp;
}
int main(int argc, char **argv)
{
// your code goes here
char *c = countAndSay(atoi(argv[1]));
printf("%s\n", c);
free(c);
return 0;
}
To get a way to check for sequences not in the list over at OEIS, I rummaged around in my attic and found this little "gem":
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
char *conway(char *s)
{
char *seq;
char c;
size_t len, count, i = 0;
len = strlen(s);
/*
* Worst case is twice as large as the input, e.g.:
* 1 -> 11
* 21 -> 1211
*/
seq = malloc(len * 2 + 1);
if (seq == NULL) {
return NULL;
}
while (len) {
// counter for occurrences of ...
count = 0;
// ... this character
c = s[0];
// as long as the string "s"
while (*s != '\0' && *s == c) {
// move pointer to next character
s++;
// increment counter
count++;
// decrement the length of the string
len--;
}
// to keep it simple, fail if c > 9
// but that cannot happen with a seed of 1
// which is used here.
// For other seeds it might be necessary to
// use a map with the higher digits as characters.
// If it is not possible to fit it into a
// character, the approach with a C-string is
// obviously not reasonable anymore.
if (count > 9) {
free(seq);
return NULL;
}
// append counter as a character
seq[i++] = (char) (count + '0');
// append character "c" from above
seq[i++] = c;
}
// return a proper C-string
seq[i] = '\0';
return seq;
}
int main(int argc, char **argv)
{
long i, n;
char *seq0, *seq1;
if (argc != 2) {
fprintf(stderr, "Usage: %s n>0\n", argv[0]);
exit(EXIT_FAILURE);
}
// reset errno, just in case
errno = 0;
// get amount from commandline
n = strtol(argv[1], NULL, 0);
if ((errno == ERANGE && (n == LONG_MAX || n == LONG_MIN))
|| (errno != 0 && n == 0)) {
fprintf(stderr, "strtol failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (n <= 0) {
fprintf(stderr, "Usage: %s n>0\n", argv[0]);
exit(EXIT_FAILURE);
}
// allocate space for seed value "1" plus '\0'
// If the seed is changed the limit in the conway() function
// above might need a change.
seq0 = malloc(2);
if (seq0 == NULL) {
fprintf(stderr, "malloc() failed to allocate a measly 2 bytes!?\n");
exit(EXIT_FAILURE);
}
// put the initial value into the freshly allocated memory
strcpy(seq0, "1");
// print it, nicely formatted
/*
* putc('1', stdout);
* if (n == 1) {
* putc('\n', stdout);
* free(seq0);
* exit(EXIT_SUCCESS);
* } else {
* printf(", ");
* }
*/
if (n == 1) {
puts("1");
free(seq0);
exit(EXIT_SUCCESS);
}
// adjust count
n--;
for (i = 0; i < n; i++) {
// compute conway sequence as a recursion
seq1 = conway(seq0);
if (seq1 == NULL) {
fprintf(stderr, "conway() failed, probably because malloc() failed\n");
exit(EXIT_FAILURE);
}
// make room
free(seq0);
seq0 = NULL;
// print sequence, comma separated
// printf("%s%s", seq1, (i < n - 1) ? "," : "\n");
// or print sequence and length of sequence, line separated
// printf("%zu: %s%s", strlen(seq1), seq1, (i < n-1) ? "\n\n" : "\n");
// print the endresult only
if (i == n - 1) {
printf("%s\n", seq1);
}
// reuse seq0
seq0 = seq1;
// not necessary but deemed good style by some
// although frowned upon by others
seq1 = NULL;
}
// free the last memory
free(seq0);
exit(EXIT_SUCCESS);
}

c - skyline algorithm confusion

I am trying to write a code which gives coordinates of corners of a skyline, it was one of my friends' homework and I am trying it as a practice for myself. So, here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct building
{
int start, height, width;
} BUILDING;
int main()
{
FILE *buildingsptr, *outlineptr;
char karakter;
int satir = 1, i = 0, j = 0, *heights, lastpoint = 0 ;
BUILDING *ptr, *a, temp;
buildingsptr = fopen("buildings.txt", "r");
if (buildingsptr == NULL)
{
printf("An error occured while opening the file.\n");
system("PAUSE");
return 0;
}
while ((karakter = fgetc(buildingsptr)) != EOF)
{
if (karakter == '\n') satir++;
}
ptr = (BUILDING *) malloc(satir * sizeof(BUILDING));
a = ptr;
rewind(buildingsptr);
for (i = 0; i < satir; i++)
{
fscanf(buildingsptr, "%d %d %d", &ptr->start, &ptr->height, &ptr->width);
ptr++;
}
fclose(buildingsptr);
ptr = a; // a is for accessing the first part of the allocated memory,
// compiler gave some errors while I tried to access the first
// block of the array.
for (j = 0; j < satir; j++) //bubble sort to buildings
{
for (i = 0; i < satir; i++)
{
if (ptr[i].start > ptr[i + 1].start)
{
temp = ptr[i];
ptr[i] = ptr[i + 1];
ptr[i + 1] = temp;
}//end of if
}//end of second for
}//end of first for
lastpoint = ((ptr[satir - 1].start + ptr[satir - 1].width) + 1);
heights = (int *)calloc(lastpoint, sizeof(int));
for (j = 0; j < lastpoint; j++) // j travels the x axis
{
for (i = 0; i < satir; i++) // i counts buildings
{
if (j <= (ptr[i].start + ptr[i].width && ptr[i].start <= j))
{
if (ptr[i].height > heights[i])
heights[i] = ptr[i].height;
}
}
}
outlineptr = fopen("outline.txt", "w");
for (i = 0; i < lastpoint; i++) // for every point x,checking the heights
// and transforming them as the coordinates
{
if (heights[i + 1] > heights[i])
{
fprintf(outlineptr, "(%d,%d),", i + 1, heights[i]);
fprintf(outlineptr, "(%d,%d),", i + 1, heights[i + 1]);
}//end if
if (heights[(i + 1)] < heights[i])
{
fprintf(outlineptr, "(%d,%d),", i, heights[i]);
fprintf(outlineptr, "(%d,%d),", i, heights[i + 1]);
}//end if
}//end for
fprintf(outlineptr, "(%d,%d),", lastpoint, heights[lastpoint]);
fprintf(outlineptr, "(%d,%d)", lastpoint, 0);
getch();
return 0;
}
Code is working but it is writing wrong coordinates to the outline.txt. "buildings.txt" is something like:
24 7 4
5 7 11
26 9 7
9 5 5
3 12 4
33 9 6
37 5 7
12 9 10
First integer is starting point of a building, second one is height of the building and third one is width of the building. So, how can I re-write this code? I edited my code to be more proper.
This is a basic example of how the frame of your program should look.
The implementation of the algorithm itself should be up to you.
There is no need for separate line counting.
#include <stdio.h>
#include <stdlib.h>
typedef struct building
{
int start, height, width;
struct building *next;
struct building *prev;
} BUILDING;
int main()
{
FILE *inputFilePtr;
inputFilePtr = fopen("input.txt", "r");
if (inputFilePtr == NULL)
{
printf("An error occured while opening the file.\n");
return EXIT_FAILURE;
}
struct building *build = malloc(sizeof(*build));
struct building *reserve = build;
reserve->prev = NULL;
build->prev = NULL;
char lineBuf[1024];
while (fgets(lineBuf, 1024, inputFilePtr) != NULL)
{
sscanf(lineBuf, "%d %d %d", &(build->start), &(build->height), &(build->width));
build->next = malloc(sizeof(*build));
build->prev = build;
build = build->next;
}
build->next = NULL;
fclose(inputFilePtr);
/////////
// whatever logic comes here
////////
FILE *out = fopen("out.txt","w");
if (out == NULL) return EXIT_FAILURE;
// modify output function to fit your algorithm
while(reserve->next != NULL)
{
fprintf(out, "Build coordinates: (%d, %d, %d)\n", reserve->start, reserve->height, reserve->width);
reserve->prev = reserve;
reserve = reserve->next;
}
fclose(out);
// possible memory cleanup
/*
while(reserve->prev != NULL)
{
reserve = reserve->prev;
free(reserve->next);
}
*/
return 0;
}

Allocation - pointer-to-pointer

I would like to ask for help with allocation .... I got this homework to school...I have to write program which will load one G matrix and second G matrix and will search second G matrix for number of presences of the first G matrix....But, when I try to run my program I got Segmentation fault message... Thanks in advance.
Example how the program is supposed to work....
...
Enter number of lines of wanted g matrix:
3
Enter the wanted g matrix:
121212
212121
121212
G matrix to be searched:
12121212121212
21212121212121
12121212123212
21212121212121
12121212121212
G matrix found 8 times.
...
this is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * get_line(void) // get line
{
char * string;
if((string = (char *)malloc(100 * sizeof(char))) == NULL)
{
printf("Nedostatek pameti.\n"); // not enough memory
exit(1);
}
int i = 0;
while((string[i] = fgetc(stdin)) != '\n')
{
i++;
if((i % 100) == 0)
{
if((string = (char *)realloc(string, 100 * ( i - 1 ) * sizeof(char))) == NULL)
{
printf("Nedostatek pameti.\n"); // not enough memory
exit(1);
}
}
}
return ( string );
}
char ** get_wanted_g_matrix(int pocetradek /*number of lines*/) // get wanted g matrix
{
char ** string;
printf("Zadejte hledanou matici:\n");
int i = 0;
if(( * string = (char ** )malloc(100 * sizeof(char *))) == NULL)
{
printf("Nedostatek pameti.\n"); // not enough memory
exit(1);
}
while(i <= (pocetradek - 1))
{
string[i] = get_line();
if((i > 1) && (*string[i-1] != strlen(*string[i])))
{
printf("Nespravny vstup.\n"); // not enough memory
exit(1);
}
printf("%s", string[i]);
i++;
if((i % 100) == 0)
{
if((* string = (char **)realloc(* string, 100 * ( i - 1 ) * sizeof(char *))) == NULL)
{
printf("Nedostatek pameti.\n"); // not enough memory
exit(1);
}
}
}
return (string);
}
int get_number_of_lines(void) // get number of lines
{
int number_of_lines;
printf("Zadejte pocet radek hledane matice:\n"); // enter the number of lines of wanted g matrix
if(scanf("%d", &number_of_lines) != 1)
{
printf("Nespravny vstup.\n"); // Error
exit(1);
}
return ( number_of_lines );
}
char ** get_searched_g_matrix(void) // get wanted g matrix
{
char ** string;
printf("Matice, ktera bude prohledana:\n"); // G matrix to be searched
int i = 0;
if(( * string = (char ** )malloc(100 * sizeof(char *))) == NULL)
{
printf("Nedostatek pameti.\n"); // not enough memory
exit(1);
}
while(!feof(stdin))
{
string[i] = get_line();
if((i > 1) && (*string[i-1] != strlen(*string[i])))
{
printf("Nespravny vstup.\n"); // error
exit(1);
}
printf("%s", string[i]);
i++;
if((i % 100) == 0)
{
if((* string = (char **)realloc(* string, 100 * ( i - 1 ) * sizeof(char *))) == NULL)
{
printf("Nedostatek pameti.\n"); // not enough memory
exit(1);
}
}
}
if(feof(stdin))
{
return string;
}
}
int search( char ** string1, char ** string2 ) // search
{
int string1width = strlen(*string1[0]);
int string2width = strlen(*string2[0]);
int string2height = strlen(**string2);
int number_of_lines = get_number_of_lines();
unsigned int g = 0, h = 0, i2, j2, l = 0, i = 0, j;
while( i <= (string2height - 2) )
{
j = 0;
while( j <= string2width - 2 )
{
g = 0; h = 0;
if(string2[i][j] == string1[g][h])
{
i2 = i;
while((g <= number_of_lines - 1) && (i2 <= string2height - 2))
{
j2 = j; h = 1;
while(((string2[i2][j2] == string1[g][h]) && (j2 <= string2height - 2)) && (h <= string1width - 2))
{
j2++;
h++;
}
if(h != string1width - 1)
{
break;
}
if(g == number_of_lines - 1)
{
l++;
break;
}
i2++;
g++;
}
}
j++;
}
i++;
}
return ( l );
}
int main(void)
{
char ** string1;
char ** string2;
int number_of_lines = get_number_of_lines();
string1 = get_wanted_g_matrix(number_of_lines);
string2 = get_searched_g_matrix();
if(feof(stdin))
{
printf("Matice nalezena %d krat.\n", search( ** string1, **string2 )); // G matrix found %d times.
}
return 0;
}
In this code:
char ** get_wanted_g_matrix(int pocetradek /*number of lines*/) // get wanted g matrix
{
char ** string;
printf("Zadejte hledanou matici:\n");
int i = 0;
if(( * string = (char ** )malloc(100 * sizeof(char *))) == NULL)
You dereference string, but it is uninitialized, so you're writing to a random location in memory. Change that * string to just string. The same applies here:
if((* string = (char **)realloc(* string, 100 * ( i - 1 ) * sizeof(char *))) == NULL)
..and to the corresponding lines in get_searched_g_matrix() as well.
In this line:
if((i > 1) && (*string[i-1] != strlen(*string[i])))
You're passing a char to strlen(), when you should be passing a char *. I suspect you mean just strlen(string[i]), but that line seems somewhat nonsensical. The same problem is in get_searched_g_matrix() as well, as well as the first three calls to strlen() in search().
Your get_searched_g_matrix() can fall off the end without returning a value - you need to consider what to return if feof(stdin) is not true.
In main(), your call to search() passes char values, but the function expects char **. You probably mean:
printf("Matice nalezena %d krat.\n", search( string1, string2 ));
(The above won't be sufficient to fix your code - you also appear to have some logic problems. But it's a necessary start.)
In future, you should compile your code with a higher level of warnings enabled, then fix the problems that the compiler identifies (if you're using gcc, compile with -Wall).
Just some comments and style hints:
I'd say it's quite large for what it should do (and hard to follow), try simplifying it a bit.
1) Save vertical space, most people nowadays have wide screens, and it's quite annoing when you can't see the corresponding closing bracket.
1.1) It's very good that you check for error conditions, but try using something like
void err(const char* msg){
printf("\n\nFATAL ERROR: %s\n", msg);
exit(1);
};
so that you can do
if (!(x = malloc(sz)))
err("Not enough memory!");
1.2) While it's considered safer to use brackets for a signle statement in if, I'd suggest avoiding them when possible, or at least use fewer newlines. Brackets are for compiler, people preffer tabs.
2) There are several while statements in your search function that should be written as fors.
3) Why would you need two distinct functions to read the matrices? One would be enough.
4) As #caf pointed out, you have also errors in input functions. Test each function before going further. It takes years of experience before you can write the whole program at once.

Resources