I'm looking to create a program that creates and stores N random complex numbers. However, it's necessary to use another array (of pointers) which points to every element on the complex array. Then, I have to present it sorted by its norm to the user.
To "sort" it, I just change to where the pointer array is pointing to. Then I just show the "sorted" array of pointers.
But I'm not getting it right. How can I achieve this?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#define FORMATLOG "FORMATLOG: invalid parameters: ex3 <N>"
#define RANGE 18 - 6
enum { true, false };
typedef struct {
double real,
imag,
norm;
} Complex;
void generateComplex(int N) {
int i, test;
Complex vector[N];
for(i = 0; i < N; i++) {
vector[i].real = rand() % RANGE;
do { vector[i].imag = rand() % RANGE; } while(vector[i].imag == 0);
vector[i].norm = sqrt(pow(vector[i].real, 2) + pow(vector[i].imag, 2));
}
Complex *p_vect = &vector;
/* makes array point in order */
while(test == false) {
test == true;
for(i = 0; i < N - 1; i++)
if(vector[i].norm > vector[i + 1].norm) {
*p_vect[i] = &vector[i + 1];
*p_vect[i + 1] = &vector[i];
test = false;
}
}
for(i = 0; i < N; i++)
printf("\t%d -| %2g + %2gi | = %g\n", i, vector[i].real,
vector[i].imag,
vector[i].norm);
printf("********************************\n");
for(i = 0; i < N; i++)
printf("\t%d -| %2g + %2gi | = %g\n", i, p_vect[i].real,
p_vect[i].imag,
p_vect[i].norm);
}
int main(int argc, char **argv) {
if(argc != 2) {
puts(FORMATLOG);
return false;
}
srand(time(NULL));
int i, N = atoi(argv[1]);
generateComplex(N);
return true;
}
Complex *p_vect = &vector;
This creates a pointer to the existing array. The requirement is to create an array of pointers, not a pointer to an array.
Complex *p_vect[N];
for (i = 0; i < N; i++) {
p_vect[i] = &vector[i];
}
If you start with this, you can then sort p_vect without touching vector. Your sorting code, when written correctly, will make no mention of vector at all.
Related
So I'm trying to teach myself , and Ive been doing online lab exercises to learn it. I wrote a program that goes into pretty good detail of arrays and structures. It uses random numbers to monitor for a spike of 100 psi, and then prints that as a 0 point, and prints the previous 10 seconds of the array and the next 10, as if I was collecting data. The next part of this exercise is to take the program's print statement, and have it write to an external file and have it print there. My thought process is to populate an array in the printout function that holds the values read from the file and then print from the array to screen. But I'm not sure how this would look, or really how to accomplish it. If anyone could point me in the right direction or give a good explanation it would be greatly appreciated!
My code so far:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
#define MAX_CHANGE 100
#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;
// Function Declarations
void get_values(float * pressure, float * flow, float * temp);
void printIt(data_slice * data);
void initializeArray(data_slice * data);
bool spikeValueRecorded(data_slice * data, int outputIndex);
int main()
{
srand((unsigned int)time(NULL));
data_slice data[ARRAY_SIZE];
int index = -1;
while (1)
{
// Initialize the entire array
initializeArray(data);
// If there's a spike.....
if (spikeValueRecorded(data, index))
{
// Set the previous "time" in array to negatives
int temp = index;
for (int i = 0; i >= -10; --i)
{
data[temp].t = i;
temp = temp - 1;
if (temp < 0)
temp = temp + ARRAY_SIZE;
}
// Record for 10 more seconds
for (int i = 0; i <= 10; ++i)
{
data[index].t = i;
index = (index + 1) % ARRAY_SIZE; // Increment the index of the circular array
get_values(&data[index].tp, &data[index].tf, &data[index].tt); // "Record" the values
}
break;
}
}
// Print the finished recording
printIt(data);
}
// Return: void
// in - Values of the data_slice struct
//
// Description: The three values of the struct (data_slice) to be filled in
void get_values(float * pressure, float * flow, float * temp)
{
*pressure = (float)(rand() % (700 - 500 + 1) + 500); // Range: 500 - 700
*flow = (float)(rand() % (20 - 10 + 1) + 10); // Range: 10 - 20
*temp = (float)(rand() % (200 - 100 + 1) + 100); // Range: 100 - 200
}
// Return: void
// in - The array of data_slice
//
// Description: Prints the entire array being passed in
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;
}
}
for (int i = 0; i < ARRAY_SIZE; ++i)
{
printf("%i\t %f\t %f\t %f\n", data[indice].t, data[indice].tp, data[indice].tf, data[indice].tt);
indice = (indice + 1) % ARRAY_SIZE;
}
}
// Return: void
// in - The array of data_slice
//
// Description: Initializes the entire array to random values and their times to 0
void initializeArray(data_slice * data)
{
for (int i = 0; i < ARRAY_SIZE; ++i)
{
data[i].t = 0;
get_values(&data[i].tp, &data[i].tf, &data[i].tt);
}
}
// Return: boolean
// in - The array of data_slice
// out - Indice of the pressure spike
//
// Description: Returns true if a positive spike in pressure has been recorded.
// outputIndex will hold the 0-indice of the pressure spike, else -1
bool spikeValueRecorded(data_slice * data, int outputIndex)
{
float oldValue = data[0].tp;
for (int i = 0; i < ARRAY_SIZE; ++i)
{
if (data[i].tp - oldValue < MAX_CHANGE)
{
outputIndex = i;
return true;
}
}
outputIndex = -1;
return false;
}
You can use the fprintf call exactly like the printf call, with one difference. The first argument will be a pointer to a file handle (FILE*) which you create using a call to fopen("full or relative path","w").
The string format is now the second argument and the variable args list starts at arg 3
This is way you can write to file by using libc API
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;
}
}
//write to file
FILE *fp = fopen("output.txt", "wb"); //Binary mode since the size of array is fixed.
fwrite(data, sizeof(char), sizeof(data), fp);
fclose(fp);
for (int i = 0; i < ARRAY_SIZE; ++i)
{
printf("%i\t %f\t %f\t %f\n", data[indice].t, data[indice].tp, data[indice].tf, data[indice].tt);
indice = (indice + 1) % ARRAY_SIZE;
}
}
I am copying a program whose purpose is to generate and bubble sort a list of random numbers. This is the code:
#include <stdio.h>
#define MAX 10
int a;
int rand_seed=10;
int rand()
{
rand_seed = rand_seed * 1103515245 + 12345;
return (unsigned int)(rand_seed / 65536) % 32768;
}
void main()
{
int i,t,x,y;
//fill array
for (i = 0; i < MAX;i++)
{
a = rand();
printf("%d\n",a);
}
/* bubble sort the array */
for (x = 0; x < MAX-1; x++)
for (y = 0; y < MAX -x - 1; y++)
if (a > a[y+1]) {
t = a;
a = a[y+1];
a[y+1] = t;
}
printf("----------------\n");
for( i = 0; i < MAX;i++)
printf("%d\n",a);
}
I know it's offensive to post the whole thing here but I don't know where the problem is.
I believe your compiler already had the offensive line pointed out. In the code
if (a > a[y+1])
you're trying to use a as an array, while it was defined as an int, earlier
int a;
If you want a to be an array, you have to define it as an array, and populate each member using rand() or similar.
I am pretty sure you wanted a to be an array. In that case try this out:
int a[10];
for (i = 0; i < MAX;i++) {
a[i] = rand();
printf("%d\n",a[i]);
}
And also this part would be changed into:
if (a[y] > a[y+1]) {
t = a[y];
a[y] = a[y+1];
a[y+1] = t;
}
I want to reshape an array of length L to one of MxN, however rather than create new memory by copying the elements over in for loops I'd like to do some pointer casting to allow me to access the array with double subscripting (array[X][Y]) .
I've googled around for ages and couldn't find anything helpful.
Any help would really be appreciated.
EDIT: The array of interest is on the heap not stack.
Pointer casting doesn't seem like a good idea here. But if the number of columns is known before run-time, one option I often encounter is to simply define a macro e.g.
#define arrayName(i,j) arrayName[((i)*N) + (j)]
Or
#define ELEMENT(arrayName, i,j) (arrayName)[((i)*N) + (j)]
if you want it to be more flexible.
unions are your friends:
#include <stdio.h>
#define M 5
#define N 4
typedef union {
int a1[M * N];
int a2[M][N];
} U;
int main()
{
U u;
int i, j;
for (i = 0; i < M * N; ++i)
{
u.a1[i] = i;
}
for (i = 0; i < M; ++i)
{
for (j = 0; j < N; ++j)
{
printf("%8d", u.a2[i][j]);
}
printf("\n");
}
return 0;
}
typedefs are your friends:
#include <stdio.h>
#include <stdlib.h>
#define M 5
#define N 4
typedef int Array1D[M * N];
typedef int Array2D[M][N];
int main()
{
Array1D *a1 = malloc(sizeof(*a1));
Array2D *a2 = (Array2D *)a1;
int i, j;
for (i = 0; i < M * N; ++i)
{
(*a1)[i] = i;
}
for (i = 0; i < M; ++i)
{
for (j = 0; j < N; ++j)
{
printf("%8d", (*a2)[i][j]);
}
printf("\n");
}
free(a1);
return 0;
}
Note: above code has now been updated to use heap allocation so as not to break strict aliasing rules.
By the way if you want it super dynamic (as in no sizes are known at compile-time) you can do this by not copying all the values but by creating an index for the 2nd dimension like so:
#include <stdio.h>
#include <stdlib.h>
const int FULL = 100;
const int X = 10;
const int Y = 10;
int *dim1;
int **nested;
int main(void) {
dim1 = malloc(sizeof(int)*FULL);
nested = malloc(sizeof(int*)*X);
for(int i=0; i<X;i++)
{
nested[i] = &dim1[Y*i];
}
dim1[15] = 42;
printf("nested[1][5]: %d",nested[1][5]);
free(nested);
free(dim1);
return 0;
}
Coming from some experience with Java/C#, I'm struggling to get my head around some parts of C. I have an array of structs. These structs, at the moment, have only one member (I'll be adding others down the track) - an array of chars. This array is a string of 6 characters - two letters, four digits (e.g. XY1234).
The follow code produces the objectCode I'm looking for:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define LETTERS_IN_ALPHABET 26
typedef struct object {
char objectCode[6];
} object_t;
void GetRandomSeed() {
srand((unsigned)time(NULL));
}
char RandomLetter() {
return 'A' + rand() % LETTERS_IN_ALPHABET;
}
int RandomDigit() {
return rand() % 10;
}
int main() {
GetRandomSeed();
object_t object1;
for (int i = 0; i < 2; i++) {
object1.objectCode[i] = RandomLetter();
}
for (int i = 2; i < 6; i++) {
object1.objectCode[i] = '0' + RandomDigit();
}
// Print objectCode string to screen
for (int i = 0; i < 6; i++) {
printf("%c", object1.objectCode[i]);
}
printf("\n");
return 0;
}
I'm trying to wrap the for loops (the ones randomly generating the code) in a function. However, the print out of my attempt to do this is just gibberish:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define LETTERS_IN_ALPHABET 26
typedef struct object {
char objectCode[6];
} object_t;
void GetRandomSeed() {
srand((unsigned)time(NULL));
}
char RandomLetter() {
return 'A' + rand() % LETTERS_IN_ALPHABET;
}
int RandomDigit() {
return rand() % 10;
}
void GenerateCode(object_t object) {
for (int i = 0; i < 2; i++) {
object.objectCode[i] = RandomLetter();
}
for (int i = 2; i < 6; i++) {
object.objectCode[i] = '0' + RandomDigit();
}
}
int main() {
GetRandomSeed();
object_t object1;
// Print objectCode string to screen
for (int i = 0; i < 6; i++) {
printf("%c", object1.objectCode[i]);
}
printf("\n");
return 0;
}
I'm bit of an infant when it comes to C so I really appreciate any help you can give. Thanks.
You're missing the call to GenerateCode on main, that's the reason the print output is gibberish.
However another issue is that on the GenerateCode function, the parameter is by value and the function won't modify the original struct on main. In C, all and every parameters are by value. You should pass a pointer to the struct:
void GenerateCode(object_t* object) {
for (int i = 0; i < 2; i++) {
object->objectCode[i] = RandomLetter();
}
for (int i = 2; i < 6; i++) {
object->objectCode[i] = '0' + RandomDigit();
}
}
int main() {
// ...
object_t object1;
GenerateCode(&object1);
}
Because you pass in an object by value to GenerateCode() the function modifies only the value on the stack (ie: the parameter itself), not the actual object you want to change. use a pointer:
void GenerateCode(object_t* object) {
for (int i = 0; i < 2; i++) {
object->objectCode[i] = RandomLetter();
}
for (int i = 2; i < 6; i++) {
object->objectCode[i] = '0' + RandomDigit();
}
}
and call it like:
GenerateCode(&object1);
I'm working through an algorithms MOOC and have a small program that takes an array A of ints in arbitrary order, counts the number of inversions (an inversion being the number of pairs (i,j) of array indices with i<j and A[i] > A[j]).
Below is the code I've written. I'm trying to tackle it using a "divide and conquer" approach where we recursively split the input array into two halves, sort each half individually while counting the inversions and then merge the two halves.
The trick is I need to keep track of the number of inversions and sort the arrays, so I pass the original array around the various recursive calls as an argument to the function and pass the count of inversions as a return value.
The code executes correctly through the first set of recursive calls that successively divide and sort [1,5,3], however when I get to the 3rd invocation of mergeAndCountSplitInv it crashes at the line:
sortedArrayLeft = realloc(sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
with the error:
malloc: *** error for object 0x100103abc: pointer being realloc'd was not allocated
I can't see where I'm not using malloc correctly and I've combed through this checking to see I'm doing the pointer arithmetic correctly and can't spot any errors, but clearly error(s) exist.
Any help is appreciated.
// main.c
// inversionInC
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// function to help with debugging array/pointer arithmetic
void logArrayLenAndContents (char *arrayName, int arrayToPrint[], int arrayLen){
printf("%s\n", arrayName);
printf("len:%d\n", arrayLen);
for (int idx = 0; idx < arrayLen; idx++) {
printf("array[%d]: %d\n", idx, arrayToPrint[idx]);
}
}
int mergeAndCountSplitInv(int sortedArrayLeft[], int leftLen, int sortedArrayRight[], int rightLen)
{
printf("Calling mergeAndCount with sortedArrayLeft:\n");
logArrayLenAndContents("left Array", sortedArrayLeft, leftLen);
printf("...and sortedArrayRight:\n");
logArrayLenAndContents("right Array", sortedArrayRight, rightLen);
int i = 0;
int j = 0;
int k = 0;
int v = 0; // num of split inversions
int* outArray;
outArray = malloc((leftLen + rightLen) * sizeof(int));
while (i < leftLen && j < rightLen) {
if (sortedArrayLeft[i] < sortedArrayRight[j]) {
outArray[k] = sortedArrayLeft[i];
i++;
} else{
outArray[k] = sortedArrayRight[j];
v += leftLen - i;
j++;
}
k++;
}
// if at the end of either array then append the remaining elements
if (i < leftLen) {
while (i < leftLen) {
outArray[k] = sortedArrayLeft[i];
i++;
k++;
}
}
if (j < rightLen) {
while (j < rightLen) {
outArray[k] = sortedArrayRight[j];
j++;
k++;
}
}
printf("Wrapping up mergeAndCount where outArray contains:\n");
logArrayLenAndContents("outArray", outArray, k);
sortedArrayLeft = realloc(sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
return v;
}
int sortAndCount(int inArray[], int inLen){
printf("Calling sortAndCount with:\n");
logArrayLenAndContents("inArray", inArray, inLen);
if (inLen < 2) {
return 0;
}
int inArrayLenPart1 = ceil(inLen/2.0);
int inArrayLenPart2 = inLen - inArrayLenPart1;
int* rightArray = malloc(sizeof(int) * inArrayLenPart2);
rightArray = &inArray[inArrayLenPart1];
int x = sortAndCount(inArray, inArrayLenPart1);
printf("sortAndCount returned x = %d\n\n", x);
int y = sortAndCount(rightArray, inArrayLenPart2);
printf("sortAndCount returned y = %d\n\n", y);
int z = mergeAndCountSplitInv(inArray, inArrayLenPart1, rightArray, inArrayLenPart2);
printf("mergeAndCount returned z = %d\n", z);
return x+y+z;
}
int main(int argc, const char * argv[])
{
static int* testArray;
testArray = malloc(5 * sizeof(int));
for (int i = 0; i<=4; i++) {
testArray[0] = 1;
testArray[1] = 5;
testArray[2] = 3;
testArray[3] = 2;
testArray[4] = 4;
}
int x = sortAndCount(testArray, 5);
printf("x = %d\n", x);
return 0;
}
This happens because the value of sortedArrayLeft gets lost as soon as the function returns. The realocated value does not make it to the caller, so inArray of the sortAndCount may be pointing to freed memory if realloc needs to reallocate and copy.
In order to fix this, pass a pointer to the pointer, letting sortedArrayLeft to propagate back to inArray of sortAndCount:
int mergeAndCountSplitInv(int **sortedArrayLeft, int leftLen, int sortedArrayRight[], int rightLen) {
...
*sortedArrayLeft = realloc(*sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
return v;
}
...
int sortAndCount(int **inArray, int inLen) {
...
int z = mergeAndCountSplitInv(inArray, inArrayLenPart1, rightArray, inArrayLenPart2);
}
...
int x = sortAndCount(&testArray, 5);