I have a lot of records formed by 4 parameters each one.
I have to create an InsertionSort function with each field of the record, but I have three problems:
In first parameter of InsertionSort what can I write in order to pass him the pointer parameter (Is it correct give him directly struct fields *records?)
I have 4 parameters and I have to order them one by one. But, they're 4 different types and I need a generic InsertionSort. With this configuration, how can I pass those parameters? (I tried to put a generic variable void* temp but it doesn't work)
Last one, I have to pass 3 parameters in InsertionSort function. One of them (word) is the field that I must use in order to sort my records.
I hope I was clear. If not, tell me in the comment.
main.c
struct fields{
int id;
char field1[20];
int field2;
float field3;
};
int size; //number of records
struct fields *records = malloc(size * sizeof *records);
/* I fill records with my values */
InsertionSort(records, field1, size); //Here , I need to order my records by field1
InsertionSort function:
void InsertionSort(struct fields *records, char word, int size) { // point 1 and 3
int i, j;
void* temp; // point 2)
for (i = 1; i < size; i++) {
temp = records[i].word;
j = i - 1;
while (j >= 0 && records[j].word > temp) {
records[j + 1].word = records[j].word;
j--;
}
records[j + 1].word = temp;
}
}
Related
I have a lot of records formed by 4 parameters each one (id, field1, field2, field3). Records are contained in a pointer called records. My goal is to create an InsertionSort function in order to sort these records. The sorting will be done for every parameter of the record (through multiple calling). The trouble is that the function must be general.
What can I write in parameters of InsertionSort function so that the pointer works?
main.c
struct fields{
int id;
char field1[20];
int field2;
float field3;
};
int main() {
struct fields *records = malloc(100000 * sizeof *records);
/* Here , I fill *records with values */
InsertionSort(records,field1,100000); // I order by parameter "field1"
InsertionSort(records,id,100000); // I order by parameter "id"
InsertionSort(records,field2,100000); // I order by parameter "field2"
}
InsertionSort function
void InsertionSort(fields *records, char parameter ,int sizeofrecords) {
int i, j;
void* temp;
for (i = 1; i < size; i++) {
temp = records[i].parameter; //this command doesn't work (records[i])
j = i - 1;
while (j >= 0 && records[j].parameter> temp) {
records[j + 1].parameter= records[j].parameter;
j--;
}
records[j + 1].parameter= temp;
}
}
Look at the design of standard C (and POSIX) qsort(). Pass a pointer to a comparator function to your InsertionSort() function in place of the char parameter argument. When you need to compare in the sort function, invoke the comparator on the two records to be compared. Write different comparators to sort on the different fields. A standard (qsort-compatible) comparator has the signature int comparator(const void *p1, const void *p2). You might be able to use const fields * as the argument type, but then you'd not be able to use the standard qsort() function.
Without debugging any other issues in your sort (I'm not sure whether there are any), you might end up with:
void InsertionSort(fields *records, int (*cmp)(const void *p1, const void *p2), int size)
{
for (int i = 1; i < size; i++)
{
void *temp = &records[i];
int j = i - 1;
while (j >= 0 && (*cmp)(&records[j].parameter, temp) > 0)
{
records[j + 1].parameter = records[j].parameter;
j--;
}
records[j + 1].parameter = temp;
}
}
You can write just cmp(records[j].parameter, temp). I learned C long enough ago to prefer the older, more explicit notation for invoking a function via a function pointer. (I learned C in an era when the simpler notation was not an option.)
Your comparator functions might look like these (the other two are trivial variants on cmp_id):
static int cmp_id(const void *p1, const void *p2)
{
const fields *v1 = p1;
const fields *v2 = p2;
// +1 if v1 > v2; -1 if v1 < v2; else 0
return (v1->id > v2->id) - (v1->id < v2->id);
}
static int cmp_field1(const void *p1, const void *p2)
{
const fields *v1 = p1;
const fields *v2 = p2;
return strcmp(v1->field1, v2->field1);
}
The numeric comparator (cmp_id) avoids overflow and branching. You could write:
if (v1->id > v2->id)
return +1;
if (v1->id < v2->id)
return -1;
return 0;
as the body of the function. It is simpler to understand. It can also be extended to deal with tie-breakers, so that if the id values are the same, you can compare the field1 strings or the values in field2 or field3. You simply add extra comparisons after the if statements and before the return 0;.
Warning: this code has not been anywhere near a compiler, much less tested. Caveat Lector.
So Peppino wants to know how to actually do it. Well, kinda. The problem is while we can pass the member, we can't pass the member's type so this will run incorrectly. If we had all the members being the same type instead this would work:
#include <stddef.h>
struct fields{
int id;
char field1[20];
char field2[11];
char field3[20];
};
void InsertionSort(fields *records, size_t parameter ,int size) {
int i, j;
struct fields temp;
for (i = 1; i < size; i++) {
temp = records[i];
j = i - 1;
while (j >= 0 && strnatsort((char *)records[i] + parameter, (char *)records[i] + parameter) > 0) {
records[j + 1] = records[j];
j--;
}
records[j + 1] = temp;
}
}
InsertionSort(records,offsetof(fields, field1),100000);
where strnatsort does natural sort: How to implement a natural sort algorithm in c++?
I am using stack to make a map function, also the struct seq are opaque structures so I can't really use that. I just don't understand why my item in the struct sequence doesn't update with new values
sequence_item_at: is a function that gets the specific item in the stack based on its index
and sequence_length finds the length of that stack
void sequence_map(struct sequence *seq, int (*func)(int)) {
int length = sequence_length(seq);
int i =0;
while(i < length){
int item = sequence_item_at(seq,i);
int l = func(item);
item = l;
i++;
}
}
I have written a program for insertion shot like following:
int _tmain(int argc, _TCHAR* argv[])
{
int arr[10] = {1,2,3,10,5,9,6,8,7,4};
int value;
cin >> value ;
int *ptr;
ptr = insertionshot(arr); //here Im passing whole array
BinarySearch(arr,value);
return 0;
}
int * insertionshot(int arr[])
{
//Changed after a hint (now, its fine)
int ar[10];
for(int i =0;i < 10; i++)
{
ar[i] = arr[i];
}
//Changed after a hint
int arrlength = sizeof(ar)/sizeof(ar[0]); //here array length is 1, it should be 10
for(int a = 1; a <= arrlength -1 ;a++)
{
int b = a;
while(b > 0 && ar[b] < ar[b-1])
{
int temp;
temp = ar[b-1];
ar[b-1] = ar[b];
ar[b] = temp;
b--;
}
}
return ar;
}
The problem is after passing the whole array to the function, my function definition only shows 1 element in array and also "arraylength" is giving 1.
int arr[] in a function formal parameter list is a syntax quirk, it is actually processed as int *arr. So the sizeof trick doesn't behave as you expect.
In C it is not possible to pass arrays by value; and furthermore, at runtime an array does not remember its length.
You could include the length information by passing a pointer to the whole array at compile time:
int * insertionshot(int (*arr)[10])
Of course, with this approach you can only ever pass an array of length 10. So if you intend to be able to pass arrays of differing length, you have to pass the length as another parameter.
I need to work with 2d field which has always 2 columns. I have a pointer to field for that
int (*field)[2];
field = (int (*)[2]) malloc(rows * sizeof(*field)); /*further there will be also reallocating*/
The problem comes when I call this pointer to field to a different function. I call this function, but when assigning it to my original field in main, there comes an error/warning. I really tried already so many versions, none of them working.
int * function (int rows, int columns, int match, int **differentField) {
int i, j;
int (*field)[2];
int foundMatch = 0;
field = (int (*)[2]) malloc(rows * sizeof(*field));
for (i = 0; i < rows; i++) {
for (j = 0; j < colms; j++) {
if (match == differentField[i][j]) {
field[foundMatch][0] = i;
field[foundMatch][1] = j;
foundMatch ++;
}
int main (int argc, char ** argv) {
int (*field)[2];
int rows = 10;
int columns = 10;
int match = 1;
int **differentField;
/*creating different Field*/
field = function(rows, columns, match, differentField);
}
-> assignment from incompatible pointer type
Any idea how to properly work with this? Thank you really a lot...
You can not return a vector from a function. Instead, you can return a pointer:
int ** function (int rows, int columns, int match, int **differentField);
This means you declare field as:
int **field;
Well, the compiler is right; a int * is not the same as a int (*)[2]. Your code sample is incomplete as it stands right now. I assume you are intending to return field in the function function. However, you have another problem: You can't return an array. But, you CAN return a pointer to an array.
If it is field you are trying to return, then the way to declare your return value is:
int (**function(int rows, int columns, int match, int **differentField))[2]
Then when you return field, return the address instead (return &field;).
Then, in main, field = *function(rows, columns, match, differentField);
At least, that should all work. I think. It's pretty late and I've been up all night.
At some point you should really look into typedefs to make your life a lot easier.
typedef int (*field_t)[2];
Then you can field_t field; and field_t *function(int rows, int columns, int match, int **differentfield);. Isn't that a lot nicer?
I'm trying to make a struct that generates a random matrix and am getting "error: expected â=â, â,â, â;â, âasmâ or â_attribute_â before âmatrixâ" when compiling. How can I get this to work effectively and efficiently?
I guess expected errors usually are caused by typos but I don't see any.
I'm very new to C so pointers and malloc are quite foreign to me. I really appreciate your help.
/* It's called RandomMatrixMaker.c */
#include <stdio.h>
#include <stdlib.h>
typdef struct {
char* name;
int MID;
int MRows;
int MCols;
long[][]* MSpace;
} matrix;
matrix makeRIDMatrix(char* name, int MID, int MRows, int MCols) {
matrix m;
static int i, j, r;
m.name = name;
m.MID = MID;
m.MRows = MRows;
m.MCols = MCols;
for (i=0; i<m.MRows; i++) {
for (j=0; i<m.MCols; j++) {
r = random(101);
*(m.MSpace[i][j]) = r;
}
}
return m;
}
int main(void) {
makeRIDMatrix("test", 1, 10, 10);
return 0;
}
There is indeed a typo. You misspelled typedef:
typdef struct {
should be:
typedef struct {
EDIT:
Also, there's no reason to use static here:
static int i, j, r;
You can just get rid of the static modifier.
int i, j, r;
As another poster mentioned, there's a typo, but even with that corrected, it wouldn't compile, due to the definition of matrix.MSpace.
Let's begin in makeRIDMatrix(). You've declared an automatic (stack) variable of type "matrix". At the end of the function, you return that object. Whilst this is permissible, it's not advisable. If the struct is large, you will be copying a lot of data unnecessarily. Better to pass a pointer to a matrix into makeRIDMatrix(), and have makeRIDMatrix() fill in the contents.
The test in the inner loop is against i, but should be against j.
Next, let's look at the definition of "matrix". The definition of "MSpace" is a mess, and wouldn't even compile. Even if it did, because you haven't defined the length of a row, the compiler would not be able to calcuate the offset to any given item in the array. You want a two-dimensional array without giving the row length, but you can't do that in C. You can in other languages, but not C.
There's a lot more I could point out, but I'd be missing the real point. The real point is this:
C Is Not Java.
(It's also not one of the interpreted languages such as JavaScript, PHP, Python, Ruby and so on.)
You don't get dynamically-expanding arrays; you don't get automatic allocation of memory; you don't get garbage collection of unreferenced memory.
What you need is something more like this:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct {
char* name;
int MID;
unsigned int MRows;
unsigned int MCols;
long *MSpace;
} matrix;
void makeRIDMatrix(matrix *pmx, char* name, int MID,
unsigned int MRows, unsigned int MCols) {
int i, j;
long *MSpace = malloc(sizeof(*MSpace)*MRows*MCols);
if (MSpace == NULL) {
return;
}
pmx->name = name;
pmx->MID = MID;
pmx->MRows = MRows;
pmx->MCols = MCols;
pmx->MSpace = MSpace;
srandom((unsigned int)time(NULL));
for (i=0; i<MRows; i++) {
for (j=0; i<MCols; j++) {
long int r = random() % 101L;
*(MSpace++) = r;
}
}
}
inline long * item_addr(const matrix *pmx,
unsigned int row, unsigned int col) {
if (pmx == NULL || pmx->MSpace == NULL
|| row >= pmx->MRows || col >= pmx->MCols) {
return NULL;
}
return &(pmx->MSpace[row * pmx->MCols + col]);
}
long get_item(const matrix *pmx, unsigned int row, unsigned int col) {
long *addr = item_addr(pmx, row, col);
return addr == NULL ? 0L : *addr;
}
void set_item(matrix *pmx,
unsigned int row, unsigned int col,
long val) {
long *addr = item_addr(pmx, row, col);
if (addr != NULL) {
*addr = val;
}
}
int main(void) {
matrix m;
makeRIDMatrix(&m, "test", 1, 10, 10);
return 0;
}
Note a few things here. Firstly, for efficiency, I fill the array as if it were one-dimensional. All subsequent get/set of array items should be done through the getter/setter functions, for safety.
Secondly, a hidden nasty: makeRIDMatrix() has used malloc() to allocate the memory - but it's going to be job of the calling function (or its successors) explciitly to free() the allocated pointer when it's finished with.
Thirdly, I've changed the rows/cols variables to unsigned int - there's little sense in definining an array with negative indices!
Fourthly: little error checking. For example, makeRIDMatrix() neither knows nor cares whether the parameter values are sensible (e.g. the matrix pointer isn't checked for NULLness). That's an exercise for the student.
Fifthly, I've fixed your random number usage - after a fashion. Another exercise for the student: why is the way I did it not good practice?
However - all of this is moot. You need to get yourself a good C textbook, or a good online course, and work through the examples. The code you've given here shows that you're punching above your weight at the moment, and you need to develop some more C muscles before going into that ring!
In relation to your question about "variable sized arrays", you could have something like:
/* can stick this into your struct, this is just an example */
size_t rows, cols;
long **matrix;
/* set the values of rows, cols */
/* create the "array" of rows (array of pointers to longs) */
matrix = (long**)malloc(rows * sizeof(long*));
/* create the array of columns (array of longs at each row) */
for (i = 0; i < rows; i++)
matrix[i] = (long*)malloc(cols * sizeof(long));
/* ... */
/* free the memory at the end */
for (i = 0; i < rows; i++)
free(matrix[i]);
free(matrix);
Then you can just access the dynamically allocated matrix similar to any other array of arrays.
ie. to set element at the first row (row 0) and fourth column (column 3) to 5:
matrix[0][3] = 5;