C - creating a struct with input-dependent number of arrays - c

I’m wondering if anyone could provide any advice on storing “class slices” of values? I.e., for a table of values (see below for example), I want to be able to store, for each row, an array of the values that corresponds to each class. I have already sorted the table by class and determined the number of classes and the number of elements in each class. I’ve written out the basic conditions that I think will let me iterate over each row, over each class with the goal of copying the values from one struct into the new “class slice arrays”:
int x = 0;
for(int i = 0; i < total_rows - 1; i++)
{
for (int j = 0; j < n_classes; j++)
{
for (int k = 0; k < class_size[j]; k++)
{
data[x].value[i] = // value at the xth position of the “class slice” array for the jth class of values in the ith row //
x++;
}
}
}
where data[x].value[0] is the value I have stored for the xth sample in row i.
I guess my question is - how would you start mallocing space for arrays to store these class slices if you don’t know how many you’re even going to need (since that’s dependent on the number of rows and the number of classes)?
Example input, if this helps to make it clearer:
Class Case Case Case Case Case Case Case Case Case Case Case Case Case Case Control Control Control Control Control Control Control Control Control Control Control Control Control Control Control Control
Obs1 0.000741628 0.00308607 0.000267431 0.001418697 0.001237904 0.000761145 0.0008281 0.002426075 0.000236698 0.004924871 0.000722752 0.003758006 0.000104813 0.000986619 0.000121803 0.000666854 0 0.000171394 0.000877993 0.002717391 0.001336501 0.000812089 0.001448743 5.28E-05 0.001944298 0.000292529 0.000469631 0.001674047 0.000651526 0.000336615
Obs2 0.102002396 0.108035127 0.015052531 0.079923731 0.020643362 0.086480609 0.017907667 0.016279315 0.076263965 0.034876124 0.187481931 0.090615572 0.037460171 0.143326961 0.029628502 0.049487575 0.020175439 0.122975405 0.019754837 0.006702899 0.014033264 0.040024363 0.076610375 0.069287599 0.098896479 0.011813681 0.293331246 0.037558052 0.303052867 0.137591517
Obs3 0.218495065 0.242891829 0.23747851 0.101306336 0.309040188 0.237477347 0.293837554 0.34351816 0.217572429 0.168651691 0.179387106 0.166516699 0.099970652 0.181003474 0.076126675 0.10244981 0.449561404 0.139257863 0.127579104 0.355797101 0.354544105 0.262855651 0.10167146 0.186068602 0.316763006 0.187466247 0.05701315 0.123825467 0.064780343 0.069847682
Obs4 0.141137543 0.090948286 0.102502388 0.013063365 0.162060849 0.166292135 0.070215996 0.063535037 0.333743609 0.131011609 0.140936687 0.150108506 0.07812762 0.230704405 0.069792935 0.120770743 0.164473684 0.448110378 0.42599534 0.074094203 0.096525097 0.157661185 0.036737518 0.213931398 0.091119285 0.438073807 0.224921728 0.187034237 0.06611442 0.086005218
Obs5 0.003594044 0.003948354 0.008137536 0.001327901 0.002161974 0.003552012 0.002760334 0.001898667 0.001420186 0.003165988 0.001011853 0.001217382 0.000314439 0.004254794 0.000213155 0.003650147 0 0.002742309 0.002633978 0 0.002524503 0.002146234 0.001751465 0.006543536 0.003941146 0.00049505 0.00435191 0.001944054 0.001303053 0.004207692
Obs6 0.000285242 2.27E-05 0 1.13E-05 0.0002964 3.62E-05 0.000138017 0.000210963 0.000662753 0 0 0 0 4.11E-05 0 0 0 0 0.000101307 0 0 0 0 5.28E-05 0.00152391 0 0 0 0 0
Obs7 0.002624223 0.001134584 0.00095511 0.000419934 0.000401011 0.001739761 0.00272583 0.002566717 0.000520735 0.002311674 0.006287944 0 6.29E-05 0.000143882 3.05E-05 0.000491366 0 0 3.38E-05 0 0.001782002 0.000957104 0.002594763 0.000527704 0.000105097 0.001192619 3.13E-05 0 0.000744602 0.000252461
Obs8 0.392777683 0.383875286 0.451499522 0.684663315 0.387394299 0.357992026 0.488406597 0.423473155 0.27267563 0.47454646 0.331020526 0.484041709 0.735955056 0.338841956 0.781699147 0.625403622 0.313596491 0.270545891 0.379259109 0.498913043 0.372438372 0.446271644 0.606698813 0.305593668 0.360535996 0.29889739 0.328710081 0.521222594 0.419924299 0.584111756

I think what you are looking for is a struct containing a pointer to double and an int that keeps track of the number of values being stored:
struct data {
int numValues;
double *value;
};
If you don't know how many data structs you need, you declare a pointer to one, and allocate them as needed. Whenever you allocate a new data struct, you set the value to point to NULL. As you add values, you reallocate storage, reset the value pointer, and update the counter for that struct. Here is a little toy example to illustrate how it works:
#include <stdio.h>
#include <stdlib.h>
struct data {
int numValues;
double *value;
};
int main(void)
{
struct data *myData;
int numData = 0;
int i, last;
myData = NULL;
++numData;
i = numData - 1;
myData = realloc(myData, sizeof(*myData) * numData);
myData[i].numValues = 0;
myData[i].value = NULL;
last = myData[i].numValues;
myData[i].value = realloc(myData[i].value, sizeof(double) * (last + 1));
myData[i].numValues += 1;
myData[i].value[last] = 3.1415926536;
last = myData[i].numValues;
myData[i].value = realloc(myData[i].value, sizeof(double) * (last + 1));
myData[i].numValues += 1;
myData[i].value[last] = 2.7182818285;
printf("Value [0][0]: %lf\n", myData[i].value[0]);
printf("Value [0][1]: %lf\n", myData[i].value[1]);
++numData;
i = numData - 1;
myData = realloc(myData, sizeof(*myData) * numData);
myData[i].numValues = 0;
myData[i].value = NULL;
last = myData[i].numValues;
myData[i].value = realloc(myData[i].value, sizeof(double) * (last + 1));
myData[i].numValues += 1;
myData[i].value[last] = 1.6180340;
last = myData[i].numValues;
myData[i].value = realloc(myData[i].value, sizeof(double) * (last + 1));
myData[i].numValues += 1;
myData[i].value[last] = 2.99792458;
printf("Value [1][0]: %lf\n", myData[i].value[0]);
printf("Value [1][1]: %lf\n", myData[i].value[1]);
/* Let's free all of the memory we allocated! */
// first, free space allocated for values
for (int j = 0; j <= i; j++)
free(myData[j].value);
// next, free space allocated for structs
free(myData);
return 0;
}
Edit
I cleaned up the code a bit and stored a couple of numbers in a second struct in an attempt to make the example a little more illustrative. I also added a few lines to free the allocated memory.
I am not exactly sure what your data is representing, but it might be useful to add a second dynamic array to the struct:
struct data {
int numCase;
int numControl;
double *caseValue;
double *controlValue;
};
Some variation on this idea would allow you to keep your "case" and "control" values separate, and you could manage the addition of new values as before.

Related

How can I correctly allocate memory for this MergeSort implementation in C (with the DS I am using)?

My goal here is to perform MergeSort on a dynamic array-like data structure I called a dictionary used to store strings and their relative weights. Sorry if the implementation is dumb, I'm a student and still learning.
Anyway, based on the segfaults I'm getting, I'm incorrectly allocating memory for my structs of type item to be copied over into the temporary lists I'm making. Not sure how to fix this. Code for mergesort and data structure setup is below, any help is appreciated.
/////// DICTIONARY METHODS ////////
typedef struct {
char *item;
int weight;
} item;
typedef struct {
item **wordlist;
//track size of dictionary
int size;
} dict;
//dict constructor
dict* Dict(int count){
//allocate space for dictionary
dict* D = malloc(sizeof(dict));
//allocate space for words
D->wordlist = malloc(sizeof(item*) * count);
//initial size
D->size = 0;
return D;
}
//word constructor
item* Item(char str[]){
//allocate memory for struct
item* W = malloc(sizeof(item));
//allocate memory for string
W->item = malloc(sizeof(char) * strlen(str));
W->weight = 0;
return W;
}
void merge(dict* D, int start, int middle, int stop){
//create ints to track lengths of left and right of array
int leftlen = middle - start + 1;
int rightlen = stop - middle;
//create new temporary dicts to store the two sides of the array
dict* L = Dict(leftlen);
dict* R = Dict(rightlen);
int i, j, k;
//copy elements start through middle into left dict- this gives a segfault
for (int i = 0; i < leftlen; i++){
L->wordlist[i] = malloc(sizeof(item*));
L->wordlist[i] = D->wordlist[start + i];
}
//copy elements middle through end into right dict- this gives a segfault
for (int j = 0; j < rightlen; j++){
R->wordlist[j] = malloc(sizeof(item*));
R->wordlist[j]= D->wordlist[middle + 1 + k];
}
i = 0;
j = 0;
k = leftlen;
while ((i < leftlen) && (j < rightlen)){
if (strcmp(L->wordlist[i]->item, R->wordlist[j]->item) <= 0) {
D->wordlist[k] = L->wordlist[i];
i++;
k++;
}
else{
D->wordlist[k] = R->wordlist[j];
j++;
k++;
}
}
while (i < leftlen){
D->wordlist[k] = L->wordlist[i];
i++;
k++;
}
while (j < rightlen){
D->wordlist[k] = L->wordlist[j];
j++;
k++;
}
}
void mergeSort(dict* D, int start, int stop){
if (start < stop) {
int middle = start + (stop - start) / 2;
mergeSort(D, start, middle);
mergeSort(D, middle + 1, stop);
merge(D, start, middle, stop);
}
I put print statements everywhere and narrowed it down to the mallocs in the section where I copy the dictionary to be sorted into 2 separate dictionaries. Also tried writing that malloc as malloc(sizeof(D->wordlist[start + i])). Is there something else I need to do to be able to copy the item struct into the wordlist of the new struct?
Again, I'm new to this, so cut me some slack :)
There are numerous errors in the code:
In merge() when copying elements to the R list, the wrong (and uninitialized) index variable k is being used instead of j. R->wordlist[j]= D->wordlist[middle + 1 + k]; should be R->wordlist[j]= D->wordlist[middle + 1 + j];.
In merge() before merging the L and R lists back to D, the index variable k for the D list is being initialized to the wrong value. k = leftLen; should be k = start;.
In merge() in the loop that should copy the remaining elements of the "right" list to D, the elements are being copied from the "left" list instead of the "right" list. D->wordlist[k] = L->wordlist[j]; should be D->wordlist[k] = R->wordlist[j];.
In Item(), the malloc() call is not reserving space for the null terminator at the end of the string. W->item = malloc(sizeof(char) * strlen(str)); should be W->item = malloc(sizeof(char) * (strlen(str) + 1)); (and since sizeof(char) is 1 by definition it can be simplified to W->item = malloc(strlen(str) + 1);).
Item() is not copying the string to the allocated memory. Add strcpy(W->item, str);.
There are memory leaks in merge():
L->wordlist[i] = malloc(sizeof(item*)); is not required and can be removed since L->wordlist[i] is changed on the very next line: L->wordlist[i] = D->wordlist[start + i];.
Similarly, R->wordlist[j] = malloc(sizeof(item*)); is not required and can be removed since R->wordlist[j] is changed on the very next line.
L and R memory is created but never destroyed. Add these lines to the end of merge() to free them:
free(L->wordlist);
free(L);
free(R->wordlist);
free(R);
None of the malloc() calls are checked for success.
Allocate it all at once, before the merge sort even starts.
#include <stdlib.h>
#include <string.h>
// Weighted Word --------------------------------------------------------------
//
typedef struct {
char *word;
int weight;
} weighted_word;
// Create a weighted word
//
weighted_word* CreateWeightedWord(const char *str, int weight){
weighted_word* W = malloc(sizeof(weighted_word));
if (W){
W->word = malloc(strlen(str) + 1); // string length + nul terminator
if (W->word)
strcpy( W->word, str);
W->weight = weight;
}
return W;
}
// Free a weighted word
//
weighted_word *FreeWeightedWord(weighted_word *W){
if (W){
if (W->word)
free(W->word);
free(W);
}
return NULL;
}
// Dictionary (of Weighted Words) ---------------------------------------------
//
typedef struct {
weighted_word **wordlist; // this is a pointer to an array of (weighted_word *)s
int size; // current number of elements in use
int capacity; // maximum number of elements available to use
} dict;
// Create a dictionary with a fixed capacity
//
dict* CreateDict(int capacity){
dict* D = malloc(sizeof(dict));
if (D){
D->wordlist = malloc(sizeof(weighted_word*) * capacity);
D->size = 0;
D->capacity = capacity;
}
return D;
}
// Free a dictionary (and all weighted words)
//
dict *FreeDict(dict *D){
if (D){
for (int n = 0; n < D->size; n++)
FreeWeightedWord(D->wordlist[n]);
free(D->wordlist);
free(D);
}
return NULL;
}
// Add a new weighted word to the end of our dictionary
//
void DictAddWord(dict *D, const char *str, int weight){
if (!D) return;
if (D->size == D->capacity) return;
D->wordlist[D->size] = CreateWeightedWord(str, weight);
if (D->wordlist[D->size])
D->size += 1;
}
// Merge Sort the Dictionary --------------------------------------------------
// Merge two partitions of sorted words
// words • the partitioned weighted word list
// start • beginning of left partition
// middle • end of left partition, beginning of right partition
// stop • end of right partition
// buffer • temporary work buffer, at least as big as (middle-start)
//
void MergeWeightedWords(weighted_word **words, int start, int middle, int stop, weighted_word **buffer){
int Lstart = start; int Rstart = middle; // Left partition
int Lstop = middle; int Rstop = stop; // Right partition
int Bindex = 0; // temporary work buffer output index
// while (left partition has elements) AND (right partition has elements)
while ((Lstart < Lstop) && (Rstart < Rstop)){
if (strcmp( words[Rstart]->word, words[Lstart]->word ) < 0)
buffer[Bindex++] = words[Rstart++];
else
buffer[Bindex++] = words[Lstart++];
}
// if (left partition has any remaining elements)
while (Lstart < Lstop)
buffer[Bindex++] = words[Lstart++];
// We don't actually need this. Think about it. Why not?
// // if (right partition has any remaining elements)
// while (Rstart < Rstop)
// buffer[Bindex++] = words[Rstart++];
// Copy merged data from temporary buffer back into source word list
for (int n = 0; n < Bindex; n++)
words[start++] = buffer[n];
}
// Merge Sort an array of weighted words
// words • the array of (weighted_word*)s to sort
// start • index of first element to sort
// stop • index ONE PAST the last element to sort
// buffer • the temporary merge buffer, at least as big as (stop-start+1)/2
//
void MergeSortWeightedWords(weighted_word **words, int start, int stop, weighted_word **buffer){
if (start < stop-1){ // -1 because a singleton array is by definition sorted
int middle = start + (stop - start) / 2;
MergeSortWeightedWords(words, start, middle, buffer);
MergeSortWeightedWords(words, middle, stop, buffer);
MergeWeightedWords(words, start, middle, stop, buffer);
}
}
// Merge Sort a Dictionary
//
void MergeSortDict(dict *D){
if (D){
// We only need to allocate a single temporary work buffer, just once, right here.
dict * Temp = CreateDict(D->size);
if (Temp){
MergeSortWeightedWords(D->wordlist, 0, D->size, Temp->wordlist);
}
FreeDict(Temp);
}
}
// Main program ---------------------------------------------------------------
#include <stdio.h>
int main(int argc, char **argv){
// Command-line arguments --> dictionary
dict *a_dict = CreateDict(argc-1);
for (int n = 1; n < argc; n++)
DictAddWord(a_dict, argv[n], 0);
// Sort the dictionary
MergeSortDict(a_dict);
// Print the weighted words
for (int n = 0; n < a_dict->size; n++)
printf( "%d %s\n", a_dict->wordlist[n]->weight, a_dict->wordlist[n]->word );
// Clean up
FreeDict(a_dict);
}
Notes for you:
Be consistent. You were inconsistent with capitalization and * placement and, oddly, vertical spacing. (You are waaay better than most beginners, though.) I personally hate the Egyptian brace style, but to each his own.
I personally think there are far too many levels of malloc()s in this code too, but I will leave it at this one comment. It works as is.
Strings must be nul-terminated — that is, each string takes strlen() characters plus one for a '\0' character. There is a convenient library function that can copy a string for you too, called strdup(), which AFAIK exists on every system.
Always check that malloc() and friends succeed.
Don’t forget to free everything you allocate. Functions help.
“Item” was a terribly non-descript name, and it overlapped with the meaning of two different things in your code. I renamed them to separate things.
Your dictionary object should be expected to keep track of how many elements it can support. The above code simply refuses to add words after the capacity is filled, but you could easily make it realloc() a larger capacity if the need arises. The point is to prevent invalid array accesses by adding too many elements to a fixed-size array.
Printing the array could probably go in a function.
Notice how I set start as inclusive and stop as exclusive. This is a very C (and C++) way of looking at things, and it is a good one. It will help you with all kinds of algorithms.
Notice also how I split the Merge Sort up into two functions: one that takes a dictionary as argument, and a lower-level one that takes an array of the weighted words as argument that does all the work.
The higher-level merge sort a dictionary allocates all the temporary buffer the merge algorithm needs, just once.
The lower-level merge sort an array of (weighted_word*)s expects that temporary buffer to exist and doesn’t care (or know anything) about the dictionary object.
The merge algorithm likewise doesn't know much. It is simply given all the information it needs.
Right now the merge condition simply compares the weighted-word’s string value. But it doesn’t have to be so simple. For example, you could sort equal elements by weight. Create a function:
int CompareWeightedWords(const weighted_word *a, const weighted_word *b){
int rel = strcmp( a->word, b->word );
if (rel < 0) return -1;
if (rel > 0) return 1;
return a->weight < b->weight ? -1 : a->weight > b->weight;
}
And put it to use in the merge function:
if (CompareWeightedWords( words[Rstart], words[Lstart] ) < 0)
buffer[Bindex++] = words[Rstart++];
else
buffer[Bindex++] = words[Lstart++];
I don’t think I forgot anything.

dynamic allocation - pointer to pointer in c

i got exercise from school.
I need to write a function that get array of grades, the size of the array, int number that represent the range of the grades, array that represent the count of the number of the grades in the same range and array that sum the grade of in the range.
the function will create sub groups to the grades, for exmaple: if the range of the grades is 10 so that sub groups is: 0-9, 10-19, 20-29, 30-39,...,90-99,100.
the range is 10 so the number of the sub-groups is 100/range + 1 (11 in that example which the range is 10).
the function will return array that is pointer to pointer, each element in this array will represent the sub-group by ASC.
if there is no values in the range (sub-group) we need to set NULL.
the count array will count the number of the grade in the same range,
and the sum array will sum those grades.
we can assume that the size of those arrays are also 100/range + 1.
important: i need to use dynamic allocate memroy.
i think i have the problem to calculate to which index in the range i need to put the grade, it work in some cases, but not to all.
examples:
int grades[SIZE_GRADES] = {98,45,77,65,89,90,100,43,54,67,55,88,76,67,33,23,45,76,72,76};
int avg_grd1[100 / GRD_RANGE1 + 1];
int avg_grd2[100 / GRD_RANGE2 + 1];
int count_grd1[100 / GRD_RANGE1 + 1];
int count_grd2[100 / GRD_RANGE2 + 1];
int** arr1 = GradeStat(grades, SIZE_GRADES, GRD_RANGE1, count_grd1, avg_grd1);
int** arr2 = GradeStat(grades, SIZE_GRADES, GRD_RANGE2, count_grd2, avg_grd2);
#define GRD_RANGE1 10
#define GRD_RANGE2 7
#define SIZE_GRADES 20
those are working for me.
but what i insert this arrays it didn't: (same vars, just different array).
int grades[SIZE_GRADES] = { 45,46,58,68,70,73,74,78,90,94 };
#define GRD_RANGE1 10
#define GRD_RANGE2 15
#define SIZE_GRADES 10
and that's my code:
int** GradeStat(int* Grades, int size_grades, int grd_range, int* count_grd, int* avg_grd)
{
int sub_range = 100 / grd_range + 1;
int** class_grd;
int place_in_sub_range;
// alocate memory.
class_grd = (int**)calloc(sub_range, sizeof(int));
if (class_grd == NULL) {
exit(1);
}
for (int i = 0; i < sub_range; i++) {
count_grd[i] = 0;
}
for (int i = 0; i < sub_range; i++) {
avg_grd[i] = 0;
}
for (int i = 0; i < SIZE_GRADES; i++) {
// the index (place) in the pointer of pointer.
place_in_sub_range = Grades[i] / grd_range;
if (place_in_sub_range <= sub_range) {
// create new pointer that relevant to the range.
if (class_grd[place_in_sub_range] == 0) {
// alocate memory, set the grade and set the address of the pointer inside the pointer to pointer array.
int* sub_range_pointer = (int*)calloc(1, sizeof(int));
if (sub_range_pointer == NULL) {
exit(1);
}
// save the grade in the memory.
*sub_range_pointer = Grades[i];
// set the pointer address in the poinet of pointer array.
class_grd[place_in_sub_range] = sub_range_pointer;
// count the number of grades in each range.
count_grd[place_in_sub_range]++;
// set the grade in the sum array.
avg_grd[place_in_sub_range] = Grades[i];
}
else {
// find out how many elemnts is exist, realloc + add new grade and add the grade to there.
int* sub_range_pointer = (int*)realloc(class_grd[place_in_sub_range], count_grd[place_in_sub_range] * sizeof(int) + sizeof(int));
if (sub_range_pointer == NULL) {
exit(1);
}
// set the grade in the relevant range.
sub_range_pointer[count_grd[place_in_sub_range]] = Grades[i];
// set the pointer address in the poinet of pointer array.
class_grd[place_in_sub_range] = sub_range_pointer;
// raise the number of grades in the relevant range.
count_grd[place_in_sub_range]++;
// set the grade in the sum array.
avg_grd[place_in_sub_range] = (avg_grd[place_in_sub_range] + Grades[i]) / 2;
}
}
//else {
// return NULL;
//}
}
for (int i = 0; i < sub_range; i++) {
if (class_grd[i] == 0) {
class_grd[i] = NULL;
}
}
// return the pointer of pointer array.
return class_grd;
so on arr1 my code is working,
but on the arr2 it isn't.
i see that when i take the 45 or 46 grade and divine it in the range i'm inserting it to the 3 index (and it should be the second).
When I'm running the code through the school test checker i get this error:
timeout: the monitored command dumped core ../runTrain.sh: line 1: 21344 Segmentation fault timeout -k 5s 5s ./MainTrain.exe > ./mainTrain.log

Why is the pointer to pointer arithmatic failing in my conditional statment?

sm is a 2D array of character pointers allocated dynamically. I need to understand why my pointer to pointer arithmetic is failing in conditional if in loop structure.
2nd column in sm is where the string is that I need to test with the grade key gk which is array of characters/string. s holds row size and q is column size for 2D array, hm is my heap memory counter for freeing function which is not importing for my question.
double *cals(char **sm, char *gk, int s, int q, unsigned *hm) {
int c = 0;
double *savg = malloc(s * sizeof(double));
assert(savg);
*hm += 1;
for (int i = 0; i < s; *(savg + i) = c / q * 100 , c = 0, ++i) {
for (int j = 0; j < q; ++j) {
if (*(*(sm + i * STUDENTATT + 1) + j) == *(gk + j))
++c;
}
}
return savg;
}
There isn't much information given about the purpose of cals function so I had to make a few assumptions to write this answer.
Assumption-1(meaningful):-
You want to find how much characters in the two strings are equal(no every characters) and then find the percentage of the same characters to the total characters. If that is the case use the below code.
double *cals(char **sm, char *gk, int s, int q, unsigned *hm) {
float c = 0; // To force float division the c is declared as a float variable
double *savg = malloc(s * sizeof(double));
assert(savg);
*hm += 1;
char* sm_i_key = NULL;
unsigned int strlen_gk = strlen(gk);
unsigned int key_length = string_gk;
for (int i=0; i<s; ++i) { //The calculation is moved inside for loop
sm_i_key = *(sm+i*q+1); // You can also use sm_i_key = &sm[i*q+1]
/* Uncomment this section if length of 2 strings are not bound to be equal
if(strlen(sm_i_key) < strlen_gk){
key_length = sm_i_key;
}
else{
key_length = strlen_gk
}
*/
for (int j = 0; j < key_length; ++j) {
if (sm_i_key[j] == gk[j])
++c;
}
savg [i] = c / strlen_gk * 100; /* Since gk is the grade key it is assumed
to be equal to the total number.*/
c = 0;
}
return savg;
}
Assumption-2:-
You want to check whether the strings whose starting address is stored in the second column of each row of a 2D array sm is equal to the string stored in array pointed by gk and then calculate a value(double).
The function cals only returns 0.0 or 100.0 as the formula avgs[i]=c / q * 100 will only produce 0 if stings are not equal(since integer division c/q will always result in 0 if c is less than q which is the case here) and 100 if strings are equal(Then why use a double to store the value if only 0 and 100 is stored).
If that is the case then what you are doing here is fine unless the array gk and array sm[i][2] have different string length(not q). It would be better to use strncmp to check the equality of string if the string length of two array's are bound to be different.
Use the below code to do that:-
double *cals(char **sm, char *gk, int s, int q, unsigned *hm) {
int c;
char* sm_i_key = NULL;
double *savg = malloc(s * sizeof(double));
assert(savg);
*hm += 1;
for (int i=0; i < s;++i){//The calculation is moved to a static assignment given below
if(strncmp(sm_i_key, gk, strlen(gk) == 0)
{
savg[i] = 100.0; // Since c/q * 100 => 100.0 if q == c
}
else
{
savg[i] = 0.0; /*Since c/q *100 => 0.0 if q < c since integer
division will result in 0.*/
}
}
return savg;
}
I hope it helps.

Out of bounds 2D array error in C

Im stuck on this one part and I was hoping to get some help. I have a project that is basically a word search. The program reads in a file that contains the Rows and columns followed by the word search puzzle itself. You are required to create possible combinations of strings from the word search and check those combinations with a dictionary that is provided as another text document.
Here's an example of the file read in 1st is Rows and 2nd is Cols followed by the word search puzzle:
4 4
syrt
gtrp
faaq
pmrc
So I have been able to get most of the code to work except for the function that creates strings for the above file. Basically It needs to search the wordsearch and create strings, each created string gets passed on to another function to check if it's in the dictionary. However my code keeps going out of bounds when creating the strings, and it's continuing to cause Seg faults which is really frustrating.
Theses are the constants that are declared, its every possible direction to go while searching the word search puzzle for possible string combinations
const int DX_SIZE = 8;
const int DX[] = {-1,-1,-1,0,0,1,1,1};
const int DY[] = {-1,0,1,-1,1,-1,0,1};
This is the function I have to create the strings:
int strCreate(char** puzzle, char** dictionary, int n, int rows, int col){
int x, y;
int nextX, nextY, i;
char str[20] = {0};
int length = 1;
for(x = 0; x < rows; x++)
{
for(y = 0; y < col; y++)
{
//Grabs the base letter
str[0] = puzzle[x][y];
length = 1;
for(i = 0; i < DX_SIZE; i++)
{
while(length < MAX_WORD_SIZE)
{
nextX = x + DX[i]*length;
nextY = y + DY[i]*length;
// Checking bounds of next array
//This is where I'm having trouble.
if((x + nextX) < 0 || (nextX + x) > (col-1)){
printf("Out of bounds\n");
break;
}
if((y + nextY) < 0 || (nextY + y) > (rows-1)){
printf("Out of bounds\n");
break;
}
str[length] = puzzle[nextX][nextY];
//search for str in dictionary
checkStr(str, dictionary, n);
length++;
}
memset(&str[1], '\0', 19);
}
}
}
return 0;
}
I know i'm not checking the bounds properly I just can't figure out how to. When X = 1 and nextX = -1, that passes the bounds check, however say the array is at puzzle[0][0] nextX would put puzzle[-1][0] which is out of bounds causing the seg fault.
Thank you for taking the time to read, and I appreciate any help at all.
nextX and nextY are the indices used to access the array puzzle. Then the array bound check should also include the same. But the array bound check includes for example x+nextX.
// Checking bounds of next array
//This is where I'm having trouble.
if((x + nextX) < 0 || (nextX + x) > (col-1)){
printf("Out of bounds\n");
break;
}
Example:
if( nextX < 0)
printf("Out of bounds...\n");

How to work on a sub-matrix in a matrix by pointer?

I have a matrix of size n. Take an example:
My recursive function does the processing on the elements that lie in the border of the matrix. Now I want to call it (the recursive call) on the inner square matrix:
This is the prototype of my recursive function:
void rotate(int** mat, size_t n);
I know that a 2D array is an array within an array. I know that *(mat+1) + 1) will give the memory address that should be the base address of my new matrix. This is what I tried:
rotate((int **)(*(mat+1) + 1), n-2)
But it does not work, and I get a segfault when I try to access it with [][].
You cannot dereference mat+1 and reinterpret that as a pointer to a whole matrix. Instead provide the offsets as arguments to your function (I assume n-by-n square matrices):
void rotate(int** mat, size_t i, size_t j, size_t n) {
// assuming row-wise storage
int *row0 = mat[j]; // assumes j < n
int *row1 = mat[j + 1]; // assumes j + 1 < n
// access row0[i..] and row1[i..]
}
If you had continuous storage for your matrix, you could do the following instead:
rotate(int* mat, size_t i, size_t j, size_t n) {
int atIJ = mat[j * n + i]; // assuming row-wise storage
// ...
}
I am not sure of your application, but I wonder if using #define for your matrix size would help....
#define X_SIZE 4
#define Y_SIZE 4
or even
#define N_SIZE 4
... because then you can use X_SIZE and Y_SIZE (OR N_SIZE) in your function without having to pass them explicitly.
in main you might put
int matrix[X_SIZE * Y_SIZE];
or
int matrix2[N_SIZE * N_SIZE];
then you can call the ith row and jth column element with
*(pmatrix + X_SIZE*j + i)
or
matrix[X_SIZE*j + i]
or
*(pmatrix2 + N_SIZE*j + i)
or
matrix2[N_SIZE*j + i]
where pmatrix and pmatrix2 are pointers to matrix and matrix2.
I am pretty sure there is no clever trick to be able to easily pass the inner square 2x2 matrix to a function, unless you were to copy the elements from the centre of your matrix into a new matrix and then copy back the result afterwards.
This is not an answer to the stated question, but it is an answer to the underlying problem: management of matrices and views to matrices with minimal effort.
This will garner downvotes, but it has been so useful in solving the underlying problems whenever the type of question the OP poses has been asked, I find it is worth showing this alternative approach here.
It is not interesting for small, fixed-size matrices, as the features only show their benefits when the sizes are larger or vary.
I use the following two structures to describe matrices. I shall leave out memory pool support (which allows one to manage a set of matrices as a pool, releasing them all at once, without having to manage each matrix separately) and everything related to multithreaded operation and thread-safety, for simplicity.
The code might contain typos; if you notice any, please leave a comment, and I'll fix them.
typedef int data_t; /* Matrix element data type */
struct owner {
long refcount; /* Number of referenced to this data */
size_t size; /* Number of elements in data[] */
data_t data[]; /* C99 flexible array member */
};
typedef struct {
int rows; /* Number of rows in this matrix */
int cols; /* Number of columns in this matrix */
long rowstride;
long colstride;
data_t *origin; /* Pointer to element at row 0, col 0 */
struct owner *owner; /* Owner structure origin points to */
} matrix;
#define MATRIX_INIT { 0, 0, 0L, 0L, NULL, NULL }
Matrix m element at row r, column c, is m.origin[r * m.rowstride + c * m.colstride], assuming 0 <= r && r < m.rows and 0 <= c < m.cols.
Matrices are typically declared as local variables, not as pointers. You do need to remember to free each individual matrix after you no longer need it. (The pool mechanism I omitted lets you avoid this, as all matrices in a pool are freed at once.)
Each matrix refers to exactly one owner structure. Owner structures record the number of references (the number of matrices referring to data in that structure), and are released when the reference count drops to zero:
void matrix_free(matrix *const m)
{
if (m != NULL) {
if (m->owner != NULL && --(m->owner.refcount) < 1L) {
m->owner.size = 0;
free(m->owner);
}
m->rows = 0;
m->cols = 0;
m->rowstride = 0L;
m->colstride = 0L;
m->origin = NULL;
m->owner = NULL;
}
}
Whenever a new matrix is created, the corresponding owner structure is created:
int matrix_new(matrix *const m, const int rows, const int cols)
{
const size_t size = (size_t)rows * (size_t)cols;
struct owner *o;
if (m == NULL)
return errno = EINVAL;
m->rows = 0;
m->cols = 0;
m->rowstride = 0L;
m->colstride = 0L;
m->origin = NULL;
m->owner = NULL;
if (rows < 1 || cols < 1)
return errno = EINVAL;
o = malloc(sizeof (struct owner) + size * sizeof (data_t));
if (o == NULL) {
return errno = ENOMEM;
o->refcount = 1L;
o->size = size;
m->rows = rows;
m->cols = cols;
m->origin = o->data;
m->owner = o;
#if DEFAULT_COLUMN_MAJOR > 0
/* Default to column-major element order */
m->rowstride = 1L;
m->colstride = (long)rows;
#else
/* Default to row-major element order */
m->rowstride = (long)cols;
m->colstride = 1L;
#endif
return m;
}
Note that the above does not initialize the matrix elements to any value, so they initially contain garbage.
Matrix transpose is a trivial, fast operation:
void matrix_transpose(matrix *const m)
{
if (m->rows > 0 && m->cols > 0) {
const int rows = m->rows;
const int cols = m->cols;
const long rowstride = m->rowstride;
const long colstride = m->colstride;
m->rows = cols;
m->cols = rows;
m->rowstride = colstride;
m->colstride = rowstride;
}
}
Similarly, you can rotate and mirror matrices, just remember to modify the origin member in those cases, too.
The interesting and useful cases are being able to create "views" into other matrices. The data referenced is exactly the same -- modifying one is immediately visible in the other(s); this is true aliasing --, no memory copying is needed. Unlike in most libraries (such as GSL, GNU Scientific Library), these "views" are perfectly ordinary matrices themselves. Here are some examples:
int matrix_submatrix_from(matrix *const m, const matrix *const src,
const int firstrow, const int firstcol,
const int rows, const int cols)
{
if (m == NULL || m == src)
return errno = EINVAL;
m->rows = 0;
m->cols = 0;
m->rowstride = 0L;
m->colstride = 0L;
m->origin = NULL;
m->owner = NULL;
if (firstrow + rows > src->rows ||
firstcol + cols > src->cols)
return errno = EINVAL;
if (src == NULL || src->owner == NULL)
return errno = EINVAL;
if (src->owner.refcount < 1L || src->owner.size == 0)
return errno = EINVAL;
else {
++(src->owner.refcount);
m->owner = src->owner;
}
m->origin = src->origin + src->rowstride * firstrow
+ src->colstride * firstcol;
m->rows = rows;
m->cols = cols;
m->rowstride = src->rowstride;
m->colstride = src->colstride;
return 0;
}
int matrix_transposed_from(matrix *const m, const matrix *const src)
{
if (m == NULL || m == src)
return errno = EINVAL;
m->rows = 0;
m->cols = 0;
m->rowstride = 0L;
m->colstride = 0L;
m->origin = NULL;
m->owner = NULL;
if (src == NULL || src->owner == NULL)
return errno = EINVAL;
if (src->owner.refcount < 1L || src->owner.size == 0)
return errno = EINVAL;
else {
++(src->owner.refcount);
m->owner = src->owner;
}
m->origin = src->origin;
m->rows = src->cols;
m->cols = src->rows;
m->rowstride = src->colstride;
m->colstride = src->rowstride;
return 0;
}
Using code similar to above, you can create one-row or one-column matrix views describing any row, column, or diagonal. (The diagonals are especially useful in certain situations.)
Submatrices can be mirrored or rotated, and so on.
You can safely free a matrix you only need a submatrix or other view from, as the owner structure reference count keeps track of when the data can be safely discarded.
Matrix multiplication, and other similar complex operations for larger matrices, are very sensitive to cache locality issues. This means that you are better off copying the source matrix data into compact arrays (with the arrays properly aligned and in elements in correct order for that operand). The overhead caused by both row and column having a separate stride (instead of only one, as is typical) is actually minimal; in my own tests, neglible.
The best feature of this approach, however, is that it lets you write efficient code without worrying about what is a "real" matrix, what is a "view", and how the actual underlying data is stored in an array, unless you care.
Finally, it is simple enough for anyone who grasps basic dynamic memory management in C to completely understand.

Resources