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;
}
}
Related
I'm trying to solve a CodeWars problem called "Training on Binary Genetic Algorithms." There is a fitness function that is preloaded. When the program is run, a test function creates a random 35-bit string and it uses my run function which is supposed to return the same 35-bit string. This string is supposed to be found using a genetic algorithm.
Here is my code:
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
typedef double fitness_t (const char *, ...);
extern fitness_t fitness;
void generate (size_t length, char * s)
{
for (size_t i = 0; i < length; i++)
s[i] = rand() % 2 + 48;
}
double sum(size_t n, double ar[n])
{
double sum = 0;
for (int i = 0; i < n; i++)
sum += ar[i];
return sum;
}
void select (int size, char* population[size], double fitnesses[size])
{
double probabilities[size]; // normalized to 1
double r; // random number
int s1, s2;
int i;
for (i = 0; i < size; i++)
probabilities[i] = fitnesses[i] / sum(size, fitnesses);
// select first chromosome
r = (double)(rand() % 1000000) / 1000000; // generates a random float between 0 and 1
for (i = 0; i < size && r > 0; i++)
r -= probabilities[i];
s1 = i;
// select second chromosome
s2 = s1;
while (s2 == s1) // ensures the two chromosomes aren't the same
{
r = (double)(rand() % 1000000) / 1000000; // generates a random float between 0 and 1
for (i = 0; i < size && r > 0; i++)
r -= probabilities[i];
s2 = i;
}
// places these two chromosomes on top
char * temp = population[0];
population[0] = population[s1];
population[s1] = temp;
temp = population[1];
population[1] = population[s2];
population[s2] = temp;
}
void crossover (size_t n, char* s1, char* s2)
{
int r = rand() % n; // select a random bit to cross over at
char temp;
for (size_t i = r; i < n; i++) // swap every bit from bit r to bit n
{
temp = s1[i];
s1[i] = s2[i];
s2[i] = temp;
}
}
void mutate (size_t n, char* s, double p)
{
double r;
for (size_t i = 0; i < n; i++) // for each bit
{
r = (double)(rand() % 1000000) / 1000000; // random float between 0 and 1
if (r <= p) // if random number is less than probability
{
if (s[i] == '1') s[i] = '0'; // swap 0s and 1s
else s[i] = '1';
}
}
}
void bubbleSortPop(int size, char * population[size], double fitnesses[size])
{
int i, j;
char * temp_chrome;
double temp_fitness;
for (i = 0; i < size - 1; i++)
// Last i elements are already in place
for (j = 0; j < size - i - 1; j++)
if (fitnesses[j] < fitnesses[j + 1])
{
temp_chrome = population[j];
population[j] = population[j+1];
population[j+1] = temp_chrome;
temp_fitness = fitnesses[j];
fitnesses[j] = fitnesses[j+1];
fitnesses[j+1] = temp_fitness;
}
}
// this function changes the population.
// select, crossover, mutate
void evolve(fitness_t f, size_t size, int length, char * population[size],
double fitnesses[size], double p_c, double p_m)
{
char * s1, * s2;
double f1, f2;
char * temp_pop[size+2];
double temp_fit[size+2];
int i;
double r;
// moves two selected parents to the top
select(size, population, fitnesses);
// begin reproduction process; duplicate the chromosomes
s1 = population[0];
s2 = population[1];
// crossover
r = (double)(rand() % 1000000) / 1000000; // random float between 0 and 1
if (r < p_c) // probability of crossing over
crossover(length, s1, s2); // commences with crossover
// mutate
mutate(length, s1, p_m);
mutate(length, s2, p_m);
// calculate fitnesses
f1 = f(s1);
f2 = f(s2);
// merge fitneses
// copy original fitnesses into temp_fit
for (i = 0; i < size; i++)
temp_fit[i] = fitnesses[i];
// add new fitnesses
temp_fit[size] = f1;
temp_fit[size+1] = f2;
// merge children into population
// copy original population into temp_pop
for (i = 0; i < size; i++)
temp_pop[i] = population[i];
// add two children to temp_pop
temp_pop[size] = s1;
temp_pop[size+1] = s2;
// sort fitnesses and population
bubbleSortPop(size+2, temp_pop, temp_fit);
// add first 100 elements of temp_pop and fit to population and fitnesses
for (i = 0; i < size; i++)
{
population[i] = temp_pop[i];
fitnesses[i] = temp_fit[i];
}
}
char* runN (fitness_t f, int length, double p_c, double p_m, size_t iterations) {
}
char* run (fitness_t f, int length, double p_c, double p_m)
{
size_t size = 100;
char * population[size];
double fitnesses[size];
size_t i;
int r;
srand(time(0));
// initialize population array
for (i = 0; i < size; i++)
population[i] = malloc((length+1) * sizeof(char));
// generate original population
for (i = 0; i < size; i++)
{
generate(length, population[i]);
fitnesses[i] = f(population[i]);
printf("[%2d] %s %lf\n", i, population[i], fitnesses[i]);
}
// evolve the population
for (i = 0; i < 10; i++)
evolve(f, size, length, population, fitnesses, p_c, p_m);
// print result
printf("\nAFTER EVOLUTION\n");
for (i = 0; i < size; i++) // generates original population
printf("[%2d] %s %lf\n", i, population[i], fitnesses[i]);
// store best chromosome and free memory
char ret[length+1];
strcpy(ret, population[0]);
for (i = 0; i < size; i++)
free(population[i]);
return ret;
}
The issue is when I run my code, it nearly always comes out with a segfault at some point while printing the contents of population and fitness.
At least these problems:
Attempting to print a non-string with "%s"
Code uses "%s" and passes population[i] as if it points to a string. population[i] does not point to a string as it does not certainly have a null character. Result undefined behavior (UB). Perhaps attempting to access beyond allocated memory.
// Undefined behavior: population[i] not a string
printf("[%2d] %s %lf\n", i, population[i], fitnesses[i]);
Set the null character.
generate(length, population[i]);
population[i][length] = '\0'; // Add this here or equivalent in `generate()`.
Many compiler warnings (20+)
Enable all compiler warnings and fix those.
I found the solution. It was all the places where I tried to copy a string by making a string pointer and assigning it the same address as the pointer I wanted to copy. For example, in 'select', when I tried to move the two strings to the top, I did
char * temp = population[0];
population[0] = population[s1];
population[s1] = temp;
temp = population[1];
population[1] = population[s2];
population[s2] = temp;
I changed this to using strcpy(). I made the same mistake in 'evolve' where I tried to duplicate the chromosomes by just copying their address into variables, rather than the strings themselves:
char * s1, * s2;
// begin reproduction process; duplicate the chromosomes
s1 = population[0];
s2 = population[1];
I changed it to this:
char s1[length+1], s2[length+1];
strcpy(s1, population[0]);
strcpy(s2, population[1]);
After I made this change the segfault went away. Thanks for all your answers.
This is my implementation of BFS in C
void bfs(int* vertices, Edge* edges, int num_vertices, int num_edges){
int level = 0;
int modified;
//continue looping till all vertices have not been updated
do{
modified = 1;
for (int i = 0; i < num_edges; ++i)
{
int first = edges[i].first;
int second = edges[i].second;
if ((vertices[first] == level) &&(vertices[second] == -1))
{
vertices[second] = level + 1;
modified = 0;
}else if (vertices[second]== level && (vertices[first] == -1))
{
vertices[first] = level + 1;
modified = 0;
}
}//end of for
level++;
}while(modified != 0);
}
The code is supposed to write the level of each vertex corresponsding to a starting vertex in a vetices array. The array is initialized using this function.
void initialize_vertices(int* vertices, int size, int start_vertex){
for (int i = 0; i < size; ++i)
{
if(i == start_vertex){
vertices[i] = 0;
}else{
vertices[i] = -1;
}
}
}
An edge is defined as follows
typedef struct Edge{
int first;
int second;
}Edge;
This is my calling main function.
int main(int argc, char** argv){
const int NUM_VERTICES = 128;
const int NUM_EDGES = 128;
const int START_VERTEX = 25;
clock_t begin, end;
double time_spent;
int vertices[NUM_VERTICES];
Edge edges[NUM_EDGES];
//data set
for (int i = 0; i < NUM_EDGES; ++i)
{
edges[i].first = (rand() % (NUM_VERTICES+1));
edges[i].second = (rand() % (NUM_VERTICES+1));
}
initialize_vertices(vertices, NUM_VERTICES, START_VERTEX);
begin = clock();
bfs(vertices, edges, NUM_VERTICES, NUM_EDGES);
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("Time taken: %f\n", time_spent);
for (int i = 0; i < NUM_VERTICES; ++i)
{
printf("%d : %d", i, vertices[i]);
printf(((i % 4) != 3) ? "\t":"\n");
}
return 0;
}
The issue is that the code never terminates. What am I doing wrong, any help appreciated.
Your modified logic is flawed.
By default, you are setting modified to 1, which I guess means that something has been modified.
Then
}while(modified != 0);
correctly loops if anything has been modified.
You want to initially set modified to 0 and change it to 1 in the inner if.
Yo reenter the loop if you don't modify anything. That seems to be your problem.
You set modified = 1 at the beginning of your loop and only change that to 0 if something changed. When you ask in the end modified != 0 it will return true if and only if there was no change.
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.
I try to implement the karger Minimum Cut algorithm (Karger wiki page)
So far, I have tried my algorithm on small examples (input of size 10) and it seems to work. But when I try to have a bigger input, let's say 200. It just crashes.
To store the minimum cut data, I create a 2D array: GraphCut[SIZE_ARRAY][SIZE_ARRAY_2]
SIZE_ARRAY = 200 in this case, but I can't find a good length for SIZE_ARRAY_2.
Issue is, SIZE_ARRAY_2 has to be big as I modify the initial array to merge the different vertices.
If I declare SIZE_ARRAY_2 = 200, the size won't be enough, but if i put SIZE_ARRAY_2 = 1000, the program just crashes.
The thing is, I have to execute the algorithm 100000 times.
Here is parts of the code:
#define ARRAY_SIZE 200
#define ARRAY_SIZE_2 200
int main()
{
int minCut,minMinCut;
for (int k = 0; k < ARRAY_SIZE * ARRAY_SIZE * 4;k++) {
minCut = kargerMinCut(k);
if (k == 0)
minMinCut = minCut;
else if (minMinCut > minCut)
minMinCut = minCut;
}
printf("\n minMinCut = %d\n", minMinCut);
return 0;
}
int kargerMinCut(int k) {
// 1st dimension: each different node
// 2nd dimension: vertices
long graphCut[ARRAY_SIZE + 1][ARRAY_SIZE_2] = {0};
populateIntegerArray(graphCut); // import data from a file
int nodeToMain[ARRAY_SIZE + 1];
int sizeOfMainNode, indexToMerge,initialRand,i,j,m,nodeToMerge,nodeRemaining = ARRAY_SIZE;
for (m = 0;m<ARRAY_SIZE + 1;m++) // initialization of nodeToMain
nodeToMain[m] = m;
while (nodeRemaining > 2) {
i = 0;
j = 0;
srand(time(NULL) + nodeRemaining);// initialise rand
initialRand = nodeToMain[rand()%(ARRAY_SIZE) + 1]; // pick a random initial node, but not a merged one
sizeOfMainNode = sizeOfArray(graphCut[initialRand]); // size of the initial node
srand(time(NULL) + k); // initialise rand
indexToMerge = rand()%sizeOfMainNode;// pick another random node in the linked nodes (its index to be precise)
nodeToMerge = nodeToMain[graphCut[initialRand][indexToMerge]];
for (m = 0;m<ARRAY_SIZE + 1;m++) // update the nodeToMain array, initialRand is now the main node for nodeToMerge
if (nodeToMain[m] == nodeToMerge)
nodeToMain[m] = initialRand;
// remove the nodeToMerge numbers from the graphCut[initialRand] (as they are going to be merged)
while(graphCut[initialRand][j] > 0 && j < sizeOfMainNode) {
if (initialRand == nodeToMain[graphCut[initialRand][j]]) {
// if this is the last element, do nothing
while(nodeToMain[graphCut[initialRand][sizeOfMainNode - 1]] == initialRand && j < sizeOfMainNode - 1) {
graphCut[initialRand][sizeOfMainNode - 1] = 0;
sizeOfMainNode--;
}
graphCut[initialRand][j] = nodeToMain[graphCut[initialRand][sizeOfMainNode - 1]];
graphCut[initialRand][sizeOfMainNode - 1] = 0;
sizeOfMainNode--;
}
j++;
}
i = 0;
while (graphCut[nodeToMerge][i] > 0 && sizeOfMainNode < ARRAY_SIZE_2 && i < ARRAY_SIZE_2) { // add each vextex of the nodeTomerge to the merged nodes
if (nodeToMain[graphCut[nodeToMerge][i]] != initialRand) {
graphCut[initialRand][sizeOfMainNode] = nodeToMain[graphCut[nodeToMerge][i]];
sizeOfMainNode++;
}
i++;
}
nodeRemaining--;
}
return sizeOfArray(graphCut[nodeToMain[1]]);
}
I'm sure that the code is not really clean, maybe even really bad (beginner in C). So i Welcome any other advice.
The errors I get with the debugger seems really random.
Error is:
Impossible to divide by 0
it stops in time64.c at line 62
tim = (__time64_t)((nt_time.ft_scalar - EPOCH_BIAS) / 10000000i64);
The change in array size is probably causing a stack overflow. A common default size for the stack is 1MB (1048576 bytes). If you have:
long graphCut[200][1000];
and 4 == sizeof(long) the graphCut array is taking up 200 * 1000 * 4 = 800000 bytes, which leaves 248576 bytes which may not be enough for the stack variables in populateIntegerArray() function (I don't see that function). If 8 == sizeof(long) then the array would require 1600000 bytes, which is greater than 1MB.
If an array of that size is required then allocate (all or part) on the heap instead of the stack. For example:
long* graphCut[ARRAY_SIZE_1];
int i;
for (i = 0; i < sizeof(graphCut)/sizeof(graphCut[0]); i++)
{
graphCut[i] = malloc(ARRAY_SIZE_2 * sizeof(graphCut[0][0]));
memset(graphCut[i], 0, ARRAY_SIZE_2 * sizeof(graphCut[0][0]));
}
for (i = 0; i < sizeof(graphCut)/sizeof(graphCut[0]); i++)
{
free(graphCut[i]);
}
Some possible problems are integer or stack overflow (so you're on the right site) and memory initialization.
This implementation should allocate graphCut on the heap, and zero it every time kargerMin gets called, thus addressing those problems.
int minCut, minMinCut;
// There is a small possibility that ARRAY_SIZE*ARRAY_SIZE*4 exceeds int boundary if 16-bit
long k;
long **buffer;
// Allocate graphCut on the heap
buffer = malloc((ARRAY_SIZE + 1)*sizeof(long *));
for (k = 0; k < ARRAY_SIZE + 1; k++)
buffer[k] = malloc(ARRAY_SIZE_2*sizeof(long));
for (k = 0; k < ARRAY_SIZE * ARRAY_SIZE * 4;k++) {
minCut = kargerMinCut(k, buffer);
if (k == 0)
minMinCut = minCut;
else if (minMinCut > minCut)
minMinCut = minCut;
}
printf("\n minMinCut = %d\n", minMinCut);
// Here we free the buffer. We could do it in any order, but
// as it costs nothing here to do so, we free it in reverse-
// allocation-order to avoid any possible memory fragmentation
// - which is moot anyway, if this is a main() and we're exiting
// the program. In other instances it could be relevant.
for (k = 0; k < ARRAY_SIZE + 1; k++)
{
free(buffer[ARRAY_SIZE-k]); buffer[ARRAY_SIZE-k] = NULL;
}
free(buffer); buffer = NULL;
// The NULLing of the just-freed variables has no purpose except
// to GUARANTEE that any illegal use of them, dangling pointers,
// leftover copies etc. will immediately trigger a core dump and
// be discovered, instead of lurking undetected.
return 0;
}
int kargerMinCut(long k, long **graphCut) {
// 1st dimension: each different node
// 2nd dimension: vertices
// Zero graphCut. If populateIntegerArray rewrites
// the whole of graphCut, these four lines are redundant.
int i, j;
for (i = 0; i < ARRAY_SIZE + 1; i++)
for (j = 0; j < ARRAY_SIZE_2; j++)
graphCut[i][j] = 0;
// otherwise, they make sure that no old value of graphCut
// or uninitialised value is going to linger and potentially
// corrupt calculations later on.
populateIntegerArray(graphCut); // import data from a file
I have implemented the Karger algorithm in C++. My code below works on large files but I have not optimized enough...it still runs fast though..but could be faster..Try this solution.
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <string>
#include <map>
#include <list>
#include <fstream>
#include <sstream>
#include <set>
#include <stdlib.h>
#include <time.h>
int pick_edge(std::map <int, std::list<int>> g2, set<int> myset, int &u, int &v)
{
std::map <int, std::list<int>>::iterator it;
std::list<int> eachRow;
int rand_vertex;
int rand_edge;
srand (time(NULL));
rand_vertex = (rand() + 1) % myset.size() ;
if (rand_vertex == 0)
rand_vertex = 1;
u = get_value_at_i(myset, rand_vertex);
for (it = g2.begin(); it != g2.end(); ++it) {
if (it->first == u) {
eachRow = it->second;
rand_edge = (rand() + 1) % eachRow.size();
if (rand_edge == 0)
rand_edge = 1;
v = get_edge_at_j(eachRow, rand_edge);
break;
}
}
return 0;
}
map <int, std::list<int>> merge_uv(map <int, std::list<int>> g2, int u, int v)
{
std::map <int, std::list<int>>::iterator it_g;
std::map <int, std::list<int>>::iterator it_u;
std::map <int, std::list<int>>::iterator it_v;
std::list<int>::iterator iter_l;
std::list<int> eachRow, uRow, vRow;
std::list<int> newRow;
int vertex;
int j = 0;
map <int, std::list<int>> new_Graph_G;
vRow.clear();
uRow.clear();
eachRow.clear();
newRow.clear();
for (it_g = g2.begin(); it_g != g2.end(); ++it_g) {
vertex = it_g->first;
eachRow = it_g->second;
if (vertex == u) {
uRow = it_g->second;
it_u = it_g;
j++;
continue;
}
if (vertex == v) {
vRow = it_g->second;
it_v = it_g;
j++;
continue;
}
}
if (j == 2) {
uRow.sort();
vRow.sort();
// uRow.merge(vRow);
for (std::list<int>::iterator ite = vRow.begin(); ite != vRow.end(); ++ite) {
if (*ite != u) {
uRow.push_back(*ite);
}
}
g2.erase(v);
g2[u] = uRow;
}
for (it_g = g2.begin(); it_g != g2.end(); ++it_g) {
eachRow = it_g->second;
for (std::list<int>::iterator ite = eachRow.begin(); ite != eachRow.end(); ++ite) {
if (*ite == v && *ite != it_g->first) {
newRow.push_back(u);
} else if (*ite == it_g->first) {
continue;
} else {
newRow.push_back(*ite);
}
}
new_Graph_G[it_g->first] = newRow;
newRow.clear();
}
for (it_g = g2.begin(); it_g != g2.end(); ++it_g) {
eachRow = it_g->second;
if (it_g->first == u) {
for (std::list<int>::iterator ite = eachRow.begin(); ite != eachRow.end(); ++ite) {
if (*ite != u && *ite != v) {
newRow.push_back(*ite);
}
}
new_Graph_G[it_g->first] = newRow;
break;
}
}
return new_Graph_G;
}
int get_min_cut(std::map <int, std::list<int>> g1)
{
int v;
std::list<int> eachRow;
std::map <int, std::list<int>>::iterator it_g;
int min_cut = 0;
for (it_g = g1.begin(); it_g != g1.end(); ++it_g) {
eachRow = it_g->second;
v = it_g->first;
for (std::list<int>::iterator ite = eachRow.begin(); ite != eachRow.end(); ++ite) {
if (*ite != v) {
min_cut++;
}
}
break;
}
return min_cut;
}
int EdgeContractionAlgorithm()
{
std::map <int, std::list<int>>::iterator it;
int min_cut = 0;
int vertex = 1;
std::list<int> eachRow;
std::set<int> myset;
std::set<int>::iterator itSet;
std::map <int, std::list<int>> g2;
int edge;
int n_vertices;
int cnt = 0;
int u, v;
n_vertices = Cal_nVertices(myset, Graph_G);
g2 = Graph_G;
// Contraction algorithm.
while (n_vertices > 2) {
edge = pick_edge(g2, myset, u, v);
g2 = merge_uv(Graph_G, u, v);
n_vertices = g2.size();
myset.erase (myset.find(v));
Graph_G = g2;
}
print_graph(g2);
min_cut = get_min_cut(g2);
return (min_cut);
}
I have a loop that involves a dynamically allocated array in C. For some reason it crashes after flag increments 7 times. This wasn't happening before I was reallocating the size of the array. Here is the code:
for (int i = 0; i < length-1; i++)
{
if (audio_samples[i] > threshold && run)
{
*event_flags = (int*)realloc(*event_flags, sizeof(int)*(flag+1)); // reallocate the size of the array
*event_flags[flag] = i;
// printf("FLAG CREATED! %i\n ", i);
printf("EVENT FLAG %i %i\n",flag, *event_flags[flag] );
if (flag >5) {
printf("%d\n", i);
}
flag++;
run = false;
}
Any ideas? Please keep in mind that the size of the array is indeed the same value as length. Here is an example of my errors:
EDIT 1
FILE ONE:
int *event_positions = (int *) malloc(1 * sizeof(int)); // let us start with 1 and then add more within the method. This should continue until we have all the flags we want.
int number_of_flags = event_extractor(vocal_data, size, event_positions);
FILE TWO:
float g_THRESHOLD_FACTOR = 2.3; // THIS INCREASES THE THRESHOLD VALUE.
int event_extractor (int *audio_samples, unsigned int size_of_audio ,int *event_flags)
{
int length = (int)size_of_audio;
// * * * * * * * * * * * * * * * * * *
// RECTIFY VALUES (MAKE ABSOLUTE) (MAKE ALL POSITIVE)
int *rectified_audio = (int *) malloc(length * sizeof(int)); // I took this line from wave header reader. The number is the number of samples of the hip hop track.
make_values_absolute(audio_samples, length, rectified_audio);
// If I convert to signed ints here would the method run more efficiently?
// * * * * * * * * * * * * * * * * * * * *
// LOW PASS FILTER
int *lopass_samples = (int *) malloc(length * sizeof(int)); // I took this line from wave header reader. The number is the number of samples of the hip hop track.
lopass(rectified_audio, length,0.5, lopass_samples);
int number_of_flags = apply_threshold (lopass_samples, length, &event_flags);
printf("\n\n\n NUMBER OF EVENTS AAAA --- %d\n", number_of_flags);
for (int i = 0; i < number_of_flags; i++) {
printf("FLAG %i -- %d \n", i, event_flags[i]);
}
return number_of_flags;
}
int apply_threshold (int *audio_samples, unsigned int size_of_audio, int **event_flags)
{
int flag = 0; // this will be the number of flags that I have
bool run = true; // this will make sure that a minimum amount of time passes before I grab another flag. It's a guard.
int counter = 0; // this is the counter for the above guard.
printf("\n\nCURRENT MINIMUM TIME: 20100 SAMPLES \n\n");
// event_flags[0] = 1; // this first one is a dud. within the loop we will automatically start adding flags
int threshold = calculate_threshold_value(audio_samples, size_of_audio);
printf("\n\n this is the threshold %d \n\n", threshold);
int length = (int)size_of_audio;
printf("LENGTH OF VOCAL AUDIO %d \n", length );
for (int i = 0; i < length-1; i++)
{
if (audio_samples[i] > threshold && run)
{
// ** is this realloc working ?
// event_flags = (int*)realloc(event_flags, sizeof(int) * (flag+1));
*event_flags = (int*)realloc(*event_flags, sizeof(int)*(flag+1)); // reallocate the size of the array
*event_flags[flag] = i;
// printf("FLAG CREATED! %i\n ", i);
printf("EVENT FLAG %i %i\n",flag, *event_flags[flag] );
if (flag >5) {
printf("%d\n", i);
}
flag++;
run = false;
}
if (!run) {
counter++;
if (counter > 20100) { // hardcode minimum size for now.
counter = 0;
run=true;
}
}
}
printf("\n\n\n NUMBER OF EVENTS --- %d\n", flag);
for (int i = 0; i < flag; i++) {
printf("FLAG %i -- %d\n", i, *event_flags[i]);
}
printf("\nFIVE samples before and after my second flag: \n 0 should indicate a reach in the threshold\n");
for (int i = 0; i <10 ; i++) {
printf("VOCAL SAMPLE %i %i \n", i-5,audio_samples[*event_flags[1]+i-5] );
}
return flag;
}
First you shouldn't cast the return of realloc.
Then if I suppose that the type of that variable is int*
*event_flags[flag] = i;
There is one * too much no?
Edit: After your remark on leaving out the cast.
So if your event_flags is effectively int**, you are really on the wrong track. Seeing your use, I would guess you simply want an array of int instead. If you do that and then
event_flags[flag] = i;
without * everywhere, your problem should go away.
If you really need that indirection, you'd have to allocate not only the array event_flags but also all the individual arrays these pointers are pointing to, with something like
for (size_t j = startvalue; j < something; ++j)
event_flags[j] = malloc(whatever);
I think you may have a problem with the precedence of the * operator versus the [] operator. That is *event_flags[flag] and (*event_flags)[flag] do not reference the same memory location. The first one correspond to **(event_flags + flag) (probably not accessible), while the second one correspond to *((*event_flags) + flag) (what you want).
So, you should rewrite your code to:
int** event_flags;
// ...
*event_flags = realloc(*event_flags, sizeof(int) * (flag + 1));
(*event_flags)[flag] = i;