I am trying to use qsort to sort an array of x-y coordinate structs pointers based on their y value, but q sort is not comparing the correct values. I am baffled at this point, can anyone see what I am doing wrong?
sort function:
23 int sortFunc(const void * firsti, const void * secondi){
24
25 const Coordinate* first = firsti;
26 const Coordinate* second = secondi;
27
28 printf("Comparing %f & %f\n", first->y, second->y);
29 if(first->y < second->y){ return 1;}
30 else if(first->y == second->y){ return 0; }
31 else{ return -1; }
32
33 }
print function:
13 void printArray(Coordinate * array[], int size){
14
15 int x;
16 for(x=0; x < size; x++){
17 printf("Point %i : %f | %f\n", x, array[x]->x, array[x]->y);
18 }
19
20 }
and calling
79 qsort(pointArray, count, sizeof(Coordinate*), sortFunc);
80 printArray(pointArray, count);
yields
Comparing 0.000000 & 0.000000
Comparing 0.000000 & 0.000000
Comparing 0.000000 & 0.000000
Comparing 0.000000 & 0.000000
Comparing 0.000000 & 0.000000
Comparing 0.000000 & 0.000000
Comparing 0.000000 & 0.000000
Point 0 : 103.253334 | -12.472327
Point 1 : -3.283118 | -3.101071
Point 2 : 9.289474 | -0.459975
Point 3 : 14.029107 | -11.844076
Point 4 : -6.465595 | 14.704790
Point 5 : -5.764663 | 8.882765
any idea what's happening?
Your comparison function is written as if you have an array of Coordinate structs, not an array of pointers to Coordinate structs.
Since you have an array of pointers to Coordinate structs, the comparison function will receive pointers to pointers to Coordinate structs as parameters. For this reason your comparison function should look as follows
int sortFunc(const void * firsti, const void * secondi)
{
const Coordinate* const* first = firsti;
const Coordinate* const* second = secondi;
if((*first)->y < (*second)->y){ return 1;}
else if((*first)->y == (*second)->y){ return 0; }
else{ return -1; }
}
Related
for a homework, I need to program two functions to calculate a same mathematics sequence, recursive and iterative version. I succeeded to program the recursive version, but I don't know how to realize the iterative version.
(It's the first time I program with C language.)
the recursive version :
float sequence(int n)
{
float x = 1.0;
if(n>=1)
{
float temp = sequence(n-1);
x = temp+1/temp;
}
return x;
}
if the code works efficiently, I must to find sequence(0) = 1, sequence(1) = 2, sequence(3) = 2.5, sequence(4) = 2.9,..., sequence(100) ~ 14.284066.
Also, according to my professor, it's necessary the code is enough optimized (time complexity?) and without obvious semantic problems (too easy to discover).
Could you help me to realize iterative version with any suggestions?
So, if this question has already been asked, I'm sorry, could you give me the link please.
else I thank you for your time,
Sincerely.
I made it out, apparently it's the Fractional Chromatic Number sequence.
#include <stdio.h>
double seqrec(unsigned n) {
if (n < 2) return 1;
double prev = seqrec(n - 1);
return prev + 1 / prev;
}
double seqiter(unsigned n) {
double numerator = 1, denominator = 1;
for (unsigned k = 2; k <= n; k++) {
double newnumerator = numerator*numerator + denominator*denominator;
denominator = numerator*denominator;
numerator = newnumerator;
// avoid nan, get numbers down to a reasonable level :-)
while (denominator > 2) {
numerator /= 2;
denominator /= 2;
}
}
return numerator / denominator;
}
int main(void) {
for (int k = 1; k < 49; k++) {
printf("%d ==> %f, %f\n", k, seqrec(k), seqiter(k));
}
}
With the following output
1 ==> 1.000000, 1.000000
2 ==> 2.000000, 2.000000
3 ==> 2.500000, 2.500000
4 ==> 2.900000, 2.900000
5 ==> 3.244828, 3.244828
6 ==> 3.553010, 3.553010
7 ==> 3.834462, 3.834462
8 ==> 4.095255, 4.095255
9 ==> 4.339440, 4.339440
10 ==> 4.569884, 4.569884
11 ==> 4.788708, 4.788708
12 ==> 4.997533, 4.997533
13 ==> 5.197631, 5.197631
14 ==> 5.390027, 5.390027
15 ==> 5.575555, 5.575555
16 ==> 5.754909, 5.754909
17 ==> 5.928674, 5.928674
18 ==> 6.097345, 6.097345
19 ==> 6.261351, 6.261351
20 ==> 6.421061, 6.421061
21 ==> 6.576799, 6.576799
22 ==> 6.728848, 6.728848
23 ==> 6.877462, 6.877462
24 ==> 7.022865, 7.022865
25 ==> 7.165257, 7.165257
26 ==> 7.304819, 7.304819
27 ==> 7.441715, 7.441715
28 ==> 7.576093, 7.576093
29 ==> 7.708087, 7.708087
30 ==> 7.837821, 7.837821
31 ==> 7.965407, 7.965407
32 ==> 8.090950, 8.090950
33 ==> 8.214545, 8.214545
34 ==> 8.336280, 8.336280
35 ==> 8.456238, 8.456238
36 ==> 8.574494, 8.574494
37 ==> 8.691119, 8.691119
38 ==> 8.806179, 8.806179
39 ==> 8.919735, 8.919735
40 ==> 9.031846, 9.031846
41 ==> 9.142565, 9.142565
42 ==> 9.251944, 9.251944
43 ==> 9.360029, 9.360029
44 ==> 9.466867, 9.466867
45 ==> 9.572498, 9.572498
46 ==> 9.676964, 9.676964
47 ==> 9.780302, 9.780302
48 ==> 9.882549, 9.882549
Your recursion works deconstructively, starting with n and working backwards with recursive calls until it gets to the base case. For the base case, it returns the known answer, and at each level above the base case it evaluates the equation using returned result.
For iteration, you want to work constructively from the base case up to n. At each iteration, the current value is used to update the result from the previous iteration.
You used the pseudocode tag, so I'm providing this in Ruby (which is practically pseudocode but can be run to check the answers). You can translate it to C for yourself to enforce your understanding.
def recursive(n)
return 1.0 if n < 2
x = recursive(n - 1)
return x + 1 / x
end
def iterative(n)
x = 1.0
if n > 1
(n - 1).times { x += 1.0 / x }
end
return x
end
# Test it out
(0..10000).each { |input| puts "#{recursive(input)}\t#{iterative(input)}"}
I've tested, and both of those return identical answers for n up to 10000.
I'm honestly going nuts here trying to understand why this generic array printer implementation is not working. Well, it works for an array of int's, but not for double's. What am I missing here?
void array_printer(FILE* stream, void* data, size_t data_type_size, size_t nr_rows, size_t nr_cols, char *format){
size_t offset = 0;
for (size_t r=0; r<nr_rows;++r){
for (size_t c=0; c<nr_cols; ++c){
fprintf(stream,format, *((int8_t*)data + offset*data_type_size));
//fprintf(stream,format, *((char*)data + offset*data_type_size)); // same behaviour
offset++;
}
fprintf(stream,"\n");
}
}
void array_print_double_2D(FILE* stream, double* data, size_t nr_rows, size_t nr_cols){
array_printer(stream, data, sizeof(double), nr_rows, nr_cols, " %lf ");
}
void array_print_int_2D(FILE* stream, int* data, size_t nr_rows, size_t nr_cols){
array_printer(stream, data, sizeof(int), nr_rows, nr_cols, " %d ");
}
int main(){
double *data_double = calloc(12, sizeof(double));
data_double[0] = 1;
data_double[1] = 2;
data_double[2] = 3;
array_print_double_2D(stdout, data_double, 3, 4);
/*
0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 what??
0.000000 0.000000 0.000000 0.000000
*/
int*data_int = calloc(12, sizeof(int));
data_int[0] = 1;
data_int[1] = 2;
data_int[2] = 3;
array_print_int_2D(stdout, data_int, 3, 4);
/*
1 2 3 0
0 0 0 0 correct
0 0 0 0
*/
Expression *(int8_t*)(data+...) will return int8_t which is not consistent with printf specifier " %lf ". This results in Undefined behavior.
The problem can be efficiently solved with macros that generate the printers.
#include <stdio.h>
#include <stdlib.h>
#define DEFINE_ARRAY_PRINT_2D(TYPE, FMT) \
void array_print_ ## TYPE ## _2D(FILE* stream, void* data, size_t nr_rows, size_t nr_cols) { \
size_t offset = 0; \
for (size_t r=0; r<nr_rows;++r){ \
for (size_t c=0; c<nr_cols; ++c){ \
fprintf(stream,FMT, ((TYPE*)data)[offset]); \
offset++; \
} \
fprintf(stream,"\n"); \
} \
}
// generate printers
DEFINE_ARRAY_PRINT_2D(int, " %d ")
DEFINE_ARRAY_PRINT_2D(double, " %lf ")
int main(){
double *data_double = calloc(12, sizeof(double));
data_double[0] = 1;
data_double[1] = 2;
data_double[2] = 3;
array_print_double_2D(stdout, data_double, 3, 4);
int *data_int = calloc(12, sizeof(int));
data_int[0] = 1;
data_int[1] = 2;
data_int[2] = 3;
array_print_int_2D(stdout, data_int, 3, 4);
return 0;
}
Produces output:
1.000000 2.000000 3.000000 0.000000
0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000
1 2 3 0
0 0 0 0
0 0 0 0
As expected.
You're casting the memory to int8_t* and dereferencing it, what were you expecting? I'd provide some sort of enumeration to distinguish between the typesand cast to the right one when needed.
I'm trying to read the information I printed to a .txt file from a separate program, and display it in this new program. Although when I run the program, it says the file cannot be found. I suspect its my code, and not the file location as I have double checked my hard code, here is what I have so far, if anyone could point me in the right direction that would be great!
#include <stdio.h>
#include <stdlib.h>
#define ARRAY_SIZE 21
typedef struct data_slice
{
int t; // -> Time
float tp; // -> Valve pressure
float tf; // -> Sodium flow
float tt; // -> Sodium temp in Celsius
} data_slice;
void printIt(data_slice * data);
int main()
{
float num;
FILE *fptr;
data_slice data[ARRAY_SIZE];
if ((fptr = fopen("/Users/captainrogers/Documents/output_data.txt","r")) == NULL){
printf("Error! opening file");
// Program exits if the file pointer returns NULL.
exit(1);
}
fscanf(fptr,"%f \n", &num);
printIt(data);
fclose(fptr);
return 0;
}
void printIt(data_slice * data)
{
// Find the indice holding the time value of -10
int indice = 0;
for (int i = 0; i < ARRAY_SIZE; ++i)
{
if (data[i].t == -10)
{
indice = i;
break;
}
}
// Print results to screen
for (int i = 0, temp = indice; i < ARRAY_SIZE; ++i)
{
printf("%i\t %f\t %f\t %f\n", data[temp].t, data[temp].tp, data[temp].tf, data[temp].tt);
temp = (temp + 1) % ARRAY_SIZE;
}
}
Data I'm trying to print from .txt:
-10 595.000000 15.000000 167.000000
-9 557.000000 17.000000 168.000000
-8 634.000000 17.000000 114.000000
-7 656.000000 10.000000 183.000000
-6 561.000000 13.000000 139.000000
-5 634.000000 17.000000 124.000000
-4 672.000000 19.000000 155.000000
-3 527.000000 14.000000 166.000000
-2 656.000000 11.000000 188.000000
-1 661.000000 18.000000 141.000000
0 689.000000 17.000000 146.000000
1 624.000000 11.000000 104.000000
2 504.000000 20.000000 120.000000
3 673.000000 18.000000 147.000000
4 511.000000 12.000000 114.000000
5 606.000000 14.000000 171.000000
6 601.000000 13.000000 159.000000
7 602.000000 11.000000 127.000000
8 684.000000 10.000000 194.000000
9 632.000000 16.000000 139.000000
10 651.000000 13.000000 168.000000
fptr = fopen("C://Users//captainrogers//Documents//output_data.txt","r"))
try this code if you are sure your document is in the right file.
fopen("/Users/captainrogers/Documents/output_data.txt","r")
If the file can't be found, double-check your path. Maybe first try with the full path including the drive letter.
fscanf(fptr,"%f \n", &num);
Always check the return-value of fscanf(). "%f \n" is probably not the format string you want.
printIt(data);
Main problem: you never read any data into data[].
So right now I am simply trying to take a dummy data file,
1.30640 1
0.91751 1
0.49312 1
0.49312 0
1.79859 1
1.86360 1
0.12313 1
0.12313 0
-0.19091 1
1.82377 1
0.63205 1
0.63205 0
1.23357 1
0.62110 1
0.80438 1
and at the moment store it as a gal_matrix for manipulations later. Below is code which simply at the moment, given a data file name finds out how long it is (i.e. number of rows), initializes a gsl_matrix struct and then try to scan the text file into that matrix, called chain.
#include <stdio.h> // Needed for printf() and feof()
#include <math.h> // Needed for pow().
#include <stdlib.h> // Needed for exit() and atof()
#include <string.h> // Needed for strcmp()
#include <gsl/gsl_matrix.h> // Needed for matrix manipulations
/*------------ Defines -----------------------------------------------------------------*/
#define MAX_SIZE 10000000 // Maximum size of the time series array
#define NUM_LAG 1000 // Number of lags to calculate for
/*
*----------------------------------------------------------------------------------------
* Main program
*----------------------------------------------------------------------------------------
*/
int main(int argc, char* argv[]) {
//--------Initialization--------------------------------------------------------------
double ac_value; // computed autocorrelation value
int i,j; // Loop counter
long int N;
double mean, variance;
gsl_matrix * chains;
char filename[100];
FILE* in_file; // input file
FILE* out_file; // output file
int no_params; // number of parameters to calculate autocorrelation for
int first_column; // Which column first corresponds to a chain
int ch; // to determine number of samples in file
printf("-------------------------------------------------------------------------\n");
//--------Check that there are the correct number of arguments passed-----------------
if(argc != 4) {
printf("usage: ./auto_corr chainfile no_params first_column \n");
exit(1); // 0 means success typically, non-zero indicates an error
}
//--------Extract arguments-----------------------------------------------------------
sprintf(filename,"%s",argv[1]); // convert input file to string
in_file = fopen(filename,"rb"); // open input file for reading
no_params = atoi(argv[2]);
first_column = atoi(argv[3]);
//--------What is the number of samples in chain file?--------------------------------
N = 0; // Initialize count
while(!feof(in_file)) {
ch = fgetc(in_file);
if(ch == '\n'){
N++;
}
}
printf("Number of samples: %li\n", N); // print number of samples
if (N > MAX_SIZE) { // throw error if there are too many samples
printf("ERROR - Too many samples! MAX_SIZE = %i", MAX_SIZE);
exit(2);
}
//--------Generate a gsl matrix from the chains---------------------------------------
printf("%i\n", no_params);
chains = gsl_matrix_alloc(N, no_params); // allocate memory for gsl_matrix(rows, cols)
// print the matrix (for testing)
printf("Chain matrix \n");
for (int m=0;m<N;m++) { //rows
for (int n=0; n<no_params;n++) { // columns
printf("%f ",gsl_matrix_get(chains,m,n));
}
printf("\n");
}
// gsl_matrix_fprintf(stdout,chains,"%f"); // easy way to print, no formatting though
gsl_matrix_fscanf(in_file, chains); // read in chains to the gsl_matrix
fclose(in_file);
The error is occurring in the gsl_matrix_fscanf line, and the output I am seeing is
$ ./auto_corr auto_corr_test_data.dat 2 0
-------------------------------------------------------------------------
Number of samples: 15
2
Chain matrix
0.000000 0.000000
0.000000 0.000000
0.000000 0.000000
0.000000 0.000000
0.000000 0.000000
0.000000 0.000000
0.000000 0.000000
0.000000 0.000000
0.000000 0.000000
0.000000 0.000000
0.000000 0.000000
0.000000 0.000000
0.000000 0.000000
0.000000 0.000000
0.000000 0.000000
0.000000 0.000000
gsl: ./fprintf_source.c:165: ERROR: fscanf failed
Default GSL error handler invoked.
Abort trap: 6
I forgot to rewind the input file after I determined the number of rows.
I'm somewhat well-versed with C and I thought I had pointers all figured out until I ran into this problem. I'm creating an array-implemented stack of structs. Easy enough, but I'm running into a problem when my struct contains a dynamically allocated array.
The struct is:
typedef struct state {
int* S;
double prob;
} state_t;
Now say I'd like to create an array of 10 of those structs, each with an integer array of say 5 integers. I can allocate that array as:
state_t *newContents;
newContents = (state_t *)malloc((sizeof(state_t) + 5 * sizeof(int)) * 10);
And I can create a struct to go in the first slot:
state_t *root = malloc(sizeof *root + 5 * sizeof(int));
root->prob = 1.0;
root->S[0] = 3;
root->S[1] = 5;
root->S[2] = 7;
root->S[3] = 2;
root->S[4] = 0;
newContents[0] = *root;
But when I attempt to add a second struct, Seg fault. It's because the way the array is indexing is by the size of the struct without the int array, meaning each entry is 16 bytes long - 8 for the double + 8 for the pointer. I want it to instead index by 28 - 8 for the double and 4*5 for the ints. Does anyone know a way to access elements of this array correctly?
Thanks!
You're allocating your structs wrong. The struct itself is separate from its dynamically-allocated array and needs to be allocated separately:
// Allocate the structs.
state_t *newContents = malloc(10*sizeof(*newContents));
// Allocate the S array of the first struct.
newContents[0].S = malloc(5*sizeof(int));
newContents[0].S[0] = 3;
...
If you want a struct that actually contains an array of runtime-determined length, rather than pointing to one as your current struct does, you need a flexible array member:
struct state_t {
double prob;
int S[]; // No length specified!
};
Then you can malloc(sizeof(state_t) + n*sizeof(int)) and actually get a contiguous block of memory where the struct and its array are together. However, you can't put make an array of state_ts properly if you do this, since the compiler would have no idea where one struct ends and another begins.
Do this:
state_t *newContents;
newContents = malloc(sizeof(state_t)*10);
int i;
for (i=0;i<10;i++)
(newContents+i)->S=malloc(5 * sizeof(int));
If you want newContents to be an array of structs of size 10, then it should allocate size equal to sizeof(state_t)*10. The int *s within each struct should be allocated explicitly.
Using
Arrays of Length Zero and GCC extensions of it
proper type casting
proper pointer arithmetic
you could get what you want, more or less.
Here is my testing program (compiling with gcc -std=c99):
#include <stdio.h>
#include <stdlib.h>
typedef struct state {
double prob;
int S[];
} state_t;
int main(void) {
size_t stateSize;
state_t *newContents;
stateSize = sizeof(state_t) + 5*sizeof(int);
newContents = malloc(stateSize * 10);
for (int i = 0; i < 10; i++) {
state_t *state = (state_t *)((char *)newContents + i * stateSize);
state->prob = i;
for (int j = 0; j < 5; j++) {
state->S[j] = i * j;
}
}
for (int i = 0; i < 10; i++) {
state_t *state = (state_t *)((char *)newContents + i * stateSize);
printf("[%d] prob: %f\n", i, state->prob);
for (int j = 0; j < 5; j++) {
printf("\tS[%d]: %d\n", j, state->S[j]);
}
}
}
Run:
$ ./a.out
[0] prob: 0.000000
S[0]: 0
S[1]: 0
S[2]: 0
S[3]: 0
S[4]: 0
[1] prob: 1.000000
S[0]: 0
S[1]: 1
S[2]: 2
S[3]: 3
S[4]: 4
[2] prob: 2.000000
S[0]: 0
S[1]: 2
S[2]: 4
S[3]: 6
S[4]: 8
[3] prob: 3.000000
S[0]: 0
S[1]: 3
S[2]: 6
S[3]: 9
S[4]: 12
[4] prob: 4.000000
S[0]: 0
S[1]: 4
S[2]: 8
S[3]: 12
S[4]: 16
[5] prob: 5.000000
S[0]: 0
S[1]: 5
S[2]: 10
S[3]: 15
S[4]: 20
[6] prob: 6.000000
S[0]: 0
S[1]: 6
S[2]: 12
S[3]: 18
S[4]: 24
[7] prob: 7.000000
S[0]: 0
S[1]: 7
S[2]: 14
S[3]: 21
S[4]: 28
[8] prob: 8.000000
S[0]: 0
S[1]: 8
S[2]: 16
S[3]: 24
S[4]: 32
[9] prob: 9.000000
S[0]: 0
S[1]: 9
S[2]: 18
S[3]: 27
S[4]: 36