I am trying to create a c code that will sort an array with multiple threads, so i need to use barriers to synchronize threats
void sort(struct ThreadArguments* args){
struct ThreadArguments* the_args= (struct ThreadArguments*)args;
printf("thread %d started \n", the_args->id);
fflush(stdout);
pthread_barrier_wait (the_args->barrier);
printf("thread %d finished the iteration \n", the_args->id);
fflush(stdout);
}
My arguments structure looks like that
struct ThreadArguments {
unsigned int id;
int* array;
pthread_barrier_t* barrier;
}
And this is how I initialize barriers
pthread_barrier_init (&barrier, NULL, 4);
I expect it to do one iteration of sorting method then wait for all threads finish at the barrier then proceed, but what is does is
thread 0 started
thread 1 started
thread 2 started
thread 3 started
and then get stuck. What might be the problem?
EDIT: Full code
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <pthread.h>
#define MAXFILENAME 64
#define TIMESTEP 200000
#define MAXTHREADS 2046
//Thread arguemnt struct
struct ThreadData {
unsigned int id; //thread's id
int start; //starting index of the workers's part
int step; //step between each consecutive cells
int cells; //how many cells is worker respnsible for
pthread_barrier_t* enter_barrier; //this barrier synchornizes threads to wait till the copy of the array is created
pthread_barrier_t* exit_barrier; //this barrier is used to wait till all threads finished updating
pthread_barrier_t* print_barrier;
int print;
int iter;
int rows; //row dimensions
int columns; //column dimensions
char* array; //pointer to the original array
char* working_array; //pointer to the dublicate array used during each step
};
int readIn(int *rows, int *columns, int *iter, int *num_cells, FILE *fp);
char *initialize(int rows, int columns, int num_cells, FILE *fp);
void printBoard(int rows, int columns, char *cells, int num_cells);
int checkNeighb(int rows, int columns, char *cells, int num_cells, int target);
void evolve(struct ThreadData* args);
void printUsage(int code);
void initializeThreads(int part_type, int num_iter, int print_opt, struct ThreadData* data, int num_threads, int num_rows, int num_cols, char* cells);
int processAgrs(int argc, char **argv, char **filename, int* print_opt, int* num_threads, int* part_type, int* print_per_thread);
// Main method
int main(int argc, char *argv[]) {
int num_rows; //number of rows on the board
int num_cols;
int num_iter;
int num_cells;
int print_opt;
int num_threads;
int part_type;
int print_per_thread;
int i, ret;
char *filename = malloc(MAXFILENAME*sizeof(char));
ret = processAgrs(argc, argv, &filename, &print_opt, &num_threads, &part_type, &print_per_thread);
if(ret == -1)
{
exit(1);
}
FILE *fp = fopen (filename, "rb"); //openning file
if(fp == NULL)
{
perror("Error openning file");
exit(1);
}
if(readIn(&num_rows, &num_cols, &num_iter, &num_cells, fp) == -1) //check that everything was successful
{
printf("Error reading from file \n");
exit(1);
}
char* cells = initialize(num_rows, num_cols, num_cells, fp);
if(cells == NULL)
{
printf("Error initializing board! \n");
exit(1);
}
struct ThreadData *data = malloc(num_threads * sizeof(struct ThreadData));
initializeThreads(part_type, num_iter, print_opt, data, num_threads, num_rows, num_cols, cells);
struct timeval start_time, end_time;
double elapsed = 0;
if(gettimeofday(&start_time, NULL) == -1)
{
printf("Error getting time \n");
elapsed = -1;
}
pthread_t *thread = malloc(num_threads*sizeof(pthread_t));
printf("Start creating threads");
fflush(stdout);
// Launching Threads
for (i=0; i<num_threads; i++) {
printf("Create threads %d \n", i);
fflush(stdout);
ret = pthread_create(&thread[i], NULL,(void *) &evolve,(void *) &data[i]);
if(ret != 0)
{
printf("Error creating thread");
}
}
// Waiting for Threads to Finish
for (i=0; i<num_threads; i++) {
pthread_join(thread[i], NULL);
}
if(gettimeofday(&end_time, NULL) == -1 || elapsed == -1)
{
printf("Time was not calulcated due to error! \n");
}
else{ //print ellapsed time
elapsed = (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_usec - start_time.tv_usec) / 1000000.0;
printf("total time for %d iterations of %dx%d world is %.6f secs \n",num_iter, num_rows, num_cols, elapsed);
}
free(cells);
free(filename);
return 0;
}
void initializeThreads(int part_type, int num_iter, int print_opt, struct ThreadData* data, int num_threads, int num_rows, int num_cols, char* cells)
{
int i, prev;
int num_of_extras; //extras is thread that gets one more line/column
pthread_barrier_t enter_barrier; //this barrier synchornizes threads to wait
//till the copy of the array is created
pthread_barrier_t exit_barrier;//this barrier waits for all threads to finish updating cells
pthread_barrier_t print_barrier;
pthread_barrier_init (&enter_barrier, NULL, num_threads); //initialize barrier for copying array
pthread_barrier_init (&exit_barrier, NULL, num_threads); //initialize exit barrier
pthread_barrier_init (&print_barrier, NULL, num_threads);
char *copy_cells = malloc((num_rows * num_cols) * sizeof(char));
if(copy_cells == NULL) //Checking malloc
{
perror("Error mallocing");
free(copy_cells);
return;
}
for (i = 0; i < num_threads; i++)
{
data[i].enter_barrier = &enter_barrier;
data[i].exit_barrier = &exit_barrier;
data[i].print_barrier = &print_barrier;
data[i].iter = num_iter;
data[i].rows = num_rows;
data[i].columns = num_cols;
data[i].working_array = copy_cells;
data[i].array = cells;
data[i].print = print_opt;
}
if( part_type == 0) //if row-wise paritioning
{
int lines_per_thread = num_rows / num_threads;
num_of_extras = num_rows % num_threads;
prev = 0;
for (i = 0; i < num_threads; i++)
{
data[i].id = i;
data[i].start = prev;
if( num_of_extras == 0)
{
data[i].cells = lines_per_thread * num_cols;
prev+=data[i].cells;
}
else{
data[i].cells = (lines_per_thread + 1) * num_cols;
prev+=data[i].cells;
num_of_extras--;
}
data[i].step = 1;
}
}
else{ //column-wise patitioning
int columns_per_thread = num_cols / num_threads;
num_of_extras = num_cols % num_threads;
prev = 0;
for (i = 0; i < num_threads; i++)
{
data[i].id = i;
data[i].start = prev;
if( num_of_extras == 0)
{
data[i].cells = columns_per_thread * num_rows;
}
else{
data[i].cells = (columns_per_thread + 1) * num_rows;
num_of_extras--;
}
data[i].step = num_cols;
prev++;
}
}
}
int processAgrs(int argc, char **argv, char **filename, int* print_opt, int* num_threads, int* part_type, int* print_per_thread)
{
if (argc < 6) { //reading arguments from command line
printf("Too few arguments!");
printUsage(1);
return -1;
}
else if(argc > 6)
{
printf("Too many arguments!");
printUsage(1);
return -1;
}
else
{
strcpy(*filename, argv[1]);
*print_opt = strtol(argv[2], NULL, 10); //using strtol() to convert string to int
if(*print_opt < 0 || *print_opt > 1)
{
printf("Illiegal prinitng option! \n 1 - Print \n 0 - Don't print \n");
printUsage(1);
return -1;
}
*num_threads = strtol(argv[3], NULL, 10); //using strtol() to convert string to int
if(*num_threads < 1 || *num_threads > MAXTHREADS)
{
if( *num_threads == -1)
{
printf("Having %d thread is not allowed! \n",*num_threads); //for correct grammar print "thread" if user entered -1
}
else{
printf("Having %d threads is not allowed! \n",*num_threads);
}
return -1;
}
*part_type = strtol(argv[4], NULL, 10); //using strtol() to convert string to int
if(*part_type < 0 || *part_type > 1)
{
printf("Illiegal partitioning option! \n");
printUsage(2);
return -1;
}
*print_per_thread = strtol(argv[5], NULL, 10); //using strtol() to convert string to int
if(*print_per_thread < 0 || *print_per_thread > 1)
{
printf("Illiegal prinitng option! \n 1 - Print \n 0 - Don't print \n");
printUsage(1);
return -1;
}
return 0;
}
}
/* #biref this method prints usage infromation for a specified case
* #arg code ths arguemnts sepcifies which help message should be printed, general usage is argument 0
*/
void printUsage(int code)
{
switch( code )
{
case 0:
printf("Usage: \n");
printf(" ./gol print-option number of threads partitioning-type print-per-thread\n");
printf(" Example: \n");
printf(" ./gol file1.txt 0 8 0 1 \n");
printf(" run with config values read from file1.txt, do not print the board after\n each round, create 8 threads, use row-wise partitioning, print per-thread\npartitioning details");
break;
case 1:
printf("Print options are 1 or 0.\n");
printf(" 1 for print \n 0 for do not print");
break;
case 2:
printf("Partitioning orptions are 1 or 0.\n");
printf(" 0 for row-wise partitioning \n 1 for column-wise partitioning");
break;
default :
break;
}
}
/* #biref this method does one step of the game by first calling checkNeighb() and then choosing apporopriate action
* #param rows - number of rows of the field
* #param columns - number of comuns of the filed
* #param cells - pointer to the 1D array representing our field
* #param num_cells - total number of cells
*/
void evolve(struct ThreadData* args)
{
//////////////
struct ThreadData* the_args= (struct ThreadData*)args;
printf("thread %d started", the_args->id);
fflush(stdout);
/* int i;
int neighb;
int start = the_args->start;
int step = the_args->step;
int num_cells = the_args->cells;
int end;
int total_cells = (the_args->columns * the_args->rows);
if(the_args->id == 0) //print the initial state of the board
{ system("clear");
if(the_args->print == 1)
{
printf("Time step: %d \n\n", TIMESTEP);
printBoard(the_args->rows, the_args->columns , the_args->array, total_cells);
usleep(TIMESTEP);
}
}
///Main loop. Each itteration of the loop is a one round of game.
for(i = 0; i < the_args->iter; i++)
{
//DEBUG
end = (start + (num_cells * step));
for(i = start; i < end ; i+=step) //copy cell state to the array
{
the_args->working_array[i] = the_args->array[i];
}
//barrier
printf("at the barrier, %d!", the_args->id);
fflush(stdout);
*/
pthread_barrier_wait (the_args->enter_barrier);
/*
for(i = start; i < end; i+=step)
{
neighb = checkNeighb(the_args->rows, the_args->columns, the_args->array, num_cells, i); //get number of neighbors
if((neighb < 2 || neighb > 3) && the_args->array[i] == 1)
{
the_args->working_array[i] = 0;
}else if( the_args->array[i] == 0 && neighb == 3)
{
the_args->working_array[i] = 1;
}
}
//barrier
pthread_barrier_wait (the_args->exit_barrier);
for(i = start; i < end; i+=step)
{
the_args->array[i] = the_args->working_array[i];
}
//barrier
pthread_barrier_wait (the_args->print_barrier);
if(the_args->id == 0) //first (0th) thread should print the board
{ system("clear");
printf("at the second print \n");
if(the_args->print == 1)
{
printf("Time step: %d \n\n", TIMESTEP);
printBoard(the_args->rows, the_args->columns , the_args->array, total_cells);
usleep(TIMESTEP);
}
}
}
*/
}
/*
* #biref this read in main parameters from text file
* #param num_rows - pointer to the number of rows of the field
* #param num_columns - pointer to the number of comuns of the filed
* #param num_iter - pointer to the number of iterations
* #param num_cells - pointer to the total number of cells
* #param fp - pointer to the open file
* #return returns 0 on success and -1 on error
*/
int readIn(int *num_rows, int *num_columns, int *num_iter, int *num_cells, FILE *fp)
{
if(fscanf(fp, "%d", num_rows) < 1)
return -1;
if(fscanf(fp, "%d", num_columns) < 1)
return -1;
if(fscanf(fp, "%d", num_iter) < 1)
return -1;
if(fscanf(fp, "%d", num_cells) < 1 )
return -1;
return 0;
}
/* #biref this method creates a 1D array and fills it with the corrct data
* #param rows - number of rows of the field
* #param columns - number of comuns of the filed
* #param - which way should the array be asigned by columns or by rows (used to optimize perfomance in a column partitioning)
* #param num_cells - total number of cells
* #param fp - pointer to the open file
* #return - returns pointer to the 1D array
*/
char* initialize(int rows, int columns, int num_cells, FILE *fp)
{
int k = 0;
int i, j, index;
int length = (rows * columns); //total number of elements in the array (area of the board)
char *cells = calloc((rows * columns), sizeof(char));
if(cells == NULL) //checking malloc
{
perror("Error mallocing");
free(cells);
return NULL;
}
while( k < num_cells )
{
if(fscanf(fp, "%d %d",&i ,&j) == 2)
{
index = ((i * columns) + j);
if(index < length)
{
cells[index] = 1;
}
else{ //in case entries are outside of the board
printf("Invalid entry: %d %d is outside the boundaries", i, j);
}
k++;
}
else{
printf("Error reading i j coordinate pair %d", k);
}
}
return cells;
}
/*
* #biref this method counts number of naeighbors of the cell with a given index in a 1D representation
* #param rows - the number of rows of the field
* #param columns - the number of comuns of the filed
* #param cells - pointer to the 1D arrray
* #param num_cells - the total number of cells
* #param target - index of the cell
* #return returns number of neighbors
*/
int checkNeighb(int rows, int columns, char *cells, int num_cells, int target)
{
int count = 0;
if((target % columns) == 0) //left edge
{
if( target == 0 ) //top left corner
{
if( cells[(rows*columns) -1 ] == 1) //up-left 1
{
count++;
}
if( cells[((rows - 1) * columns)] == 1) //up 2
{
count ++;
}
if( cells[((rows - 1) * columns)+ 1] == 1) //up-right 3
{
count ++;
}
}
else{ //if not top left corner
if( cells[target - 1] == 1) //up-left 1.1
{
count++;
}
if( cells[(target - columns)] == 1) //up 2.1
{
count ++;
}
if( cells[(target - columns) + 1] == 1) //up-right 3.1
{
count++;
}
}
if( target == (rows - 1) * columns) //bottom left corner
{
if( cells[(columns)-1 ] == 1) //down-left 4
{
count++;
}
if( cells[0] == 1) //down 5
{
count ++;
}
if( cells[1] == 1) //up-right 6
{
count ++;
}
}
else{
//if not bottom left corner
if( cells[ target + (2 * columns) - 1 ] == 1) //down-left 4.1
{
count++;
}
if( cells[ target + columns ] == 1) //down 5.1
{
count ++;
}
if( cells[ (target + columns) + 1] == 1) //down-right 6.1
{
count ++;
}
}
if( cells[ target + 1] == 1) //right 7
{
count++;
}
if(cells[(target + columns) - 1] == 1) //left 8
{
count++;
}
}
else if(((target +1) % columns) == 0) //right edge
{
if( target == (columns - 1) ) //top right corner
{
if( cells[(rows * columns) - 2 ] == 1) //up-left 1
{
count++;
}
if( cells[(rows * columns) - 1] == 1) //up 2
{
count ++;
}
if( cells[((rows-1) * columns)] == 1) //up-right 3
{
count ++;
}
}
else{ //if not top right corner
if( cells[(target - columns) - 1] == 1) //up-left 1.1
{
count++;
}
if( cells[(target - columns)] == 1) //up 2.1
{
count ++;
}
if( cells[(target - (2 * columns)) + 1] == 1) //up-right 3.1
{
count++;
}
}
if( target == ((rows * columns) -1)) //bottom right corner
{
if( cells[columns - 2 ] == 1) //down-left 4
{
count++;
}
if( cells[ columns - 1 ] == 1) //down 5
{
count ++;
}
if( cells[0] == 1) //down-right 6
{
count ++;
}
}
else{
//if not bottom right corner
if( cells[ (target + columns) - 1 ] == 1) //down-left 4.1
{
count++;
}
if( cells[ target + columns ] == 1) //down 5.1
{
count ++;
}
if( cells[ target + 1 ] == 1) //down-right 6.1
{
count ++;
}
}
if( cells[(target - columns) + 1] == 1) //right 7
{
count++;
}
if(cells[target - 1 ] == 1) //left 8
{
count++;
}
}
else if(target > ((rows-1)*columns)) //bottom edge not corner
{
if(cells[target - 1] == 1) //left 1
{
count++;
}
if(cells[target + 1] == 1) //right 2
{
count++;
}
if(cells[target - columns] == 1) //up 3
{
count++;
}
if(cells[(target - columns) - 1] == 1) //up -left 4
{
count++;
}
if(cells[(target - columns) + 1] == 1) //up -right 5
{
count++;
}
if(cells[target % columns] == 1) //down 5
{
count++;
}
if(cells[(target % columns) + 1] == 1) //down -right 7
{
count++;
}
if(cells[(target % columns) + -1] == 1) //down -left 8
{
count++;
}
}
else if(target < columns) //top edge not corners
{
if(cells[target - 1] == 1) //left 1
{
count++;
}
if(cells[target + 1] == 1) //right 2
{
count++;
}
if(cells[target + ((rows-1) * columns)] == 1) //up 3
{
count++;
}
if(cells[(target + ((rows-1) * columns)) - 1] == 1) //up -left 4
{
count++;
}
if(cells[(target + ((rows-1) * columns)) + 1] == 1) //up - right 5
{
count++;
}
if(cells[target + columns] == 1) //down 5
{
count++;
}
if(cells[(target + columns) + 1] == 1) //down -right 7
{
count++;
}
if(cells[(target + columns) + -1] == 1) //down -left 8
{
count++;
}
}
else{ //middle
if(cells[target - 1] == 1) //left 1
{
count++;
}
if(cells[target + 1] == 1) //right 2
{
count++;
}
if(cells[target - columns] == 1) //up 3
{
count++;
}
if(cells[(target - columns) - 1] == 1) //up -left 4
{
count++;
}
if(cells[(target - columns) + 1] == 1) //up -right 5
{
count++;
}
if(cells[target + columns] == 1) //down 5
{
count++;
}
if(cells[(target + columns) + 1] == 1) //down -right 7
{
count++;
}
if(cells[(target + columns) + -1] == 1) //down -left 8
{
count++;
}
}
return count;
}
// #biref this method prints out the board
void printBoard(int rows, int columns, char *cells, int num_cells)
{
int i, j;
for( i = 0; i < rows; i++)
{
for( j=0; j < columns; j++)
{
if( cells[ (i * columns) + j ] == 1)
{
printf("# "); //if 1
}
else{
printf("- "); //if 0
}
}
printf("\n");
}
printf("\n");
return;
}
The barrier
pthread_barrier_t enter_barrier; //this barrier synchornizes threads to wait
is a local object in the function initializeThreads(). The lifetime of this object ends when initializeThreads() finishes, which is before the threads start and call pthread_barrier_wait (the_args->enter_barrier). It's no wonder that waiting on a non-existent barrier doesn't work.
Related
I am having difficulty creating thread when using pthread_create, I have tried changing functions to void* and such but it keeps throwing a segmentation fault.
Any help towards fixing this problem would be appreciated, I have tried researching this problem but to no avail I have yet to find a solution
Here is my code below:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <ctype.h>
#include <getopt.h>
#include <stdbool.h>
void readSudoku(int x[][9], FILE *in);
void printSudoku(int x[][9]);
int validateRows(int x[9][9]);
int validateCols(int x[9][9]);
int validateSubGrids(int x[9][9]);
void *vr(int x[9][9]);
void *vc(int x[9][9]);
void *vs(int x[9][9]);
bool validSudokuGrid(int x[][9]);
/* These are the only two global variables allowed in your program */
static int verbose = 0;
static int use_fork = 0;
// This is a simple function to parse the --fork argument.
// It also supports --verbose, -v
void parse_args(int argc, char *argv[])
{
int c;
while (1)
{
static struct option long_options[] =
{
{"verbose", no_argument, 0, 'v'},
{"fork", no_argument, 0, 'f'},
{0, 0, 0, 0}};
int option_index = 0;
c = getopt_long(argc, argv, "vf", long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 'f':
use_fork = 1;
break;
case 'v':
verbose = 1;
break;
default:
exit(1);
}
}
}
int main(int argc, char *argv[])
{
// Commented this out because this will be used later
// parse_args(argc, argv);
// if (verbose && use_fork) {
// printf("We are forking child processes as workers.\n");
// } else if (verbose) {
// printf("We are using worker threads.\n");
// }
// printf("Test");
// Initializing sudoku grid to parse file grid
int sudoku_grid[9][9];
if (argc == 1)
{
printf("File successfully opened!\n");
}
readSudoku(sudoku_grid, stdin);
printSudoku(sudoku_grid);
// validateRows(sudoku_grid);
// validateCols(sudoku_grid);
if (validSudokuGrid(sudoku_grid))
{
printf("The input is a valid Sudoku. \n");
}
else
{
printf("The input is not a valid Sudoku. \n");
}
return 0;
}
void readSudoku(int x[][9], FILE *in)
{
fseek(in, -1, SEEK_CUR); // Seek to start off the current position of the file ptr
char entry;
int i, j, totalVals = 0;
while ((fread(&entry, 1, 1, in)) > 0 && totalVals < 81)
{ // Read 81 digits from stdin file
if (entry != '\n')
{ // Ignore newline
if (isdigit(entry))
{
++totalVals;
x[i][j] = entry - '0'; // Store integer representation
++j;
if (j == 9)
{
j = 0;
++i;
}
}
}
}
}
void printSudoku(int x[][9])
{
int i = 0, j = 0; // i = rows, j = cols
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
{
// if we are on the third or fifth number of sub-grid
// we make a space between nums
if (2 == j || 5 == j)
{
printf("%d ", x[i][j]);
}
// if we are on the last num of row we make a space
else if (8 == j)
{
printf("%d\n", x[i][j]);
}
// anything else we make a space
else
{
printf("%d ", x[i][j]);
}
}
// if we are on row 3 or row 5 we make a space
if (2 == i || 5 == i)
{
printf("\n");
}
}
}
// Used to validate rows per 3x3 grid
int validateRows(int x[9][9])
{
for (int i = 0; i < 9; i += 3)
{
for (int j = 0; j < 9; j += 3)
{
int subgridValidate[9] = {0};
for (int k = i; k < i + 3; k++)
{
for (int m = j; m < j + 3; m++)
{
int currVal = x[k][m];
if (subgridValidate[currVal - 1] == 0)
{
subgridValidate[currVal - 1] = 1;
}
// else
// {
// // printf("row: %d, col: %d", k+1, m+1);
// // printf("Row: %d does not have required values \n", k + 1);
// // printf("Column: %d does not have required values \n", m + 1);
// return 0;
// }
else if((subgridValidate[currVal - 1] == 1) && (k >= 0 && k <=2)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if ( m >= 3 && m <= 5 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if ( m >= 6 && m <= 8 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 3 && k <=5) ) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 6 && k <=8)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
}
else //all subgrid have correct values.
{
return 1; // true
}
}
}
}
}
}
// Validating columns in the 3x3 grid *BACK UP*
// Fixing column tracking
// int validateCols(int x[9][9]) {
// int col = 0;
// // Traversing Rows
// for(int i = 0; i < 9; i++) {
// // Initialzing array to detect for duplicate values
// int colValidate[9] = {0};
// // Traversing columns
// for(int j = 0; j < 9; j++) {
// // Holds current value depending on row / col
// int currVal = x[i][j];
// // If the index is filled with a zero
// // that means the index is not taken
// if(colValidate[currVal - 1] == 0) {
// colValidate[currVal - 1] = 1; // fill index with 1 (true)
// } else { // Checks if dupllicate or out of bounds
// printf("Column: %d does not have the required values\n", j + 1);
// return 0;
// }
// } col ++;
// }
// }
// Function to check 3x3 Sub-Grids
int validateCols(int x[9][9])
{
for (int i = 0; i < 9; i += 3)
{
for (int j = 0; j < 9; j += 3)
{
int subgridValidate[9] = {0};
for (int k = i; k < i + 3; k++)
{
for (int m = j; m < j + 3; m++)
{
int currVal = x[k][m];
if (subgridValidate[currVal - 1] == 0)
{
subgridValidate[currVal - 1] = 1;
}
// else
// {
// // printf("row: %d, col: %d", k+1, m+1);
// // printf("Row: %d does not have required values \n", k + 1);
// // printf("Column: %d does not have required values \n", m + 1);
// return 0;
// }
else if((subgridValidate[currVal - 1] == 1) && (k >= 0 && k <=2)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if ( m >= 3 && m <= 5 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if ( m >= 6 && m <= 8 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 3 && k <=5) ) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 6 && k <=8)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
}
else //all subgrid have correct values.
{
return 1; // true
}
}
}
}
}
}
// Needs intense fixing
int validateSubGrids(int x[9][9])
{
for (int i = 0; i < 9; i += 3)
{
for (int j = 0; j < 9; j += 3)
{
int subgridValidate[9] = {0};
for (int k = i; k < i + 3; k++)
{
for (int m = j; m < j + 3; m++)
{
int currVal = x[k][m];
if (subgridValidate[currVal - 1] == 0)
{
subgridValidate[currVal - 1] = 1;
}
// else
// {
// // printf("row: %d, col: %d", k+1, m+1);
// // printf("Row: %d does not have required values \n", k + 1);
// // printf("Column: %d does not have required values \n", m + 1);
// return 0;
// }
else if((subgridValidate[currVal - 1] == 1) && (k >= 0 && k <=2)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("The top left subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if ( m >= 3 && m <= 5 ){
printf("The top mid subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if ( m >= 6 && m <= 8 ){
printf("The top right subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 3 && k <=5) ) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("The left subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("The left mid subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("The left right subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 6 && k <=8)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("The bottom left subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("The bottom mid subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("The bottom right subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
}
else //all subgrid have correct values.
{
return 1; // true
}
}
}
}
}
}
void *vr(int x[9][9]) {
validateRows(x);
}
void *vc(int x[9][9]) {
validateCols(x);
}
void *vs(int x[9][9]) {
validateSubGrids(x);
}
bool validSudokuGrid(int x[][9])
{
int numThreads = 2;
pthread_t tid [2];
for(int i = 0; i < 1; i++) {
if(i == 0) {
pthread_create(&tid[i], NULL, vr(x), NULL);
} else if(i == 1) {
pthread_create(&tid[i], NULL, vc(x), NULL);
} else {
pthread_create(&tid[i], NULL, vc(x), NULL);
}
printf("OOOGA BOOGA");
}
printf("OOOGA BOOGA");
for (int i = 0; i < numThreads; i++) {
pthread_join(tid[i], NULL);
printf("Thread %10x joined\n", tid[i]);
fflush(stdout);
}
printf("All Four Threads have exited using join(), exiting program....\n");
fflush(stdout);
exit(EXIT_SUCCESS);
return validateRows(x) + validateCols(x) + validateSubGrids(x); // if all true = valid 9x9, else = not valid 9x9
// return validateSubGrids(x);
}
Pthreads expect a callback function of the form void* func (void*), period. You cannot invent your own function format and expect it to work.
Furthermore the vr(x) etc parameters are function calls - you call the function once then use the result of that to tell pthread_create that it's a pointer to a callback function, which it isn't - it's just nonsense.
Also a function with a return type must always return something.
All of these problems could be avoided early on by configuring the compiler correctly, so that it gives errors upon encountering blatant bugs and invalid C, see What compiler options are recommended for beginners learning C? Correct use of functions is very fundamental stuff and something you need to grasp before moving on to more advanced topics like multi-threading.
Correct use, as was told in the friendly man:
void* vr (void* x) {
validateRows(x);
return NULL;
}
...
pthread_create(&tid[i], NULL, vr, x);
I am not sure if your code compiles but if it does then what will happen is this: When the program runs, then in pthread_create() function, it will call your function vr() and use the return value of vr() as the pointer to the function that should be called when the thread is created.
But vr() does not return any value but it is not of significance here.
The return value of any function is stored somewhere (register, etc.) according to the system. Let's assume that the return value is stored in a register called A. So, vr(x) will be called and then the value in register A will be read and the code will then assume that this value is the pointer to the function that should be called. But A can have any value (because the function vr(x) doesn't return any value and hence it didn't update A) - 0x0, 0x1, 0x75745, etc. And mostly this will be an invalid address (may be it will point to a restricted memory area, or to read only memory, etc.) and so the hardware will raise a memory access violation interrupt/signal which then results in segmentation fault.
Run the following code and you will understand what I am saying.
#include <stdio.h>
#include <pthread.h>
void *f(void *g)
{
printf("Called f().\n");
}
void *x(void *v)
{
printf("Called x().\n");
return (void *)(f);
}
int main(void)
{
pthread_t pt;
pthread_create(&pt, NULL, x((void *)5), NULL);
// join pthread.
pthread_join(pt, NULL);
return 0;
}
Both functions x() and f() will get called when you run the above code.
The output will be:
Called x().
Called f().
I am VERY new to C, but I thought that I'd learn it while I'm learning basic data structures. Anyway, I'm having a problem wrapping my head about how/where errors are coming up in my code.
Basically, I'm getting two different kinds of errors:
Segmentation Faults (# binary heap length 2 and 3) when subtracting from heap.
Malloc/Realloc errors when I add to binary heap enough to make it to length 4 (and beyond), and then subtract to length 2 (I get a non-valid binary heap structure # length 3 when I do this as well).
Basically, I just want to see what exactly I'm doing wrong to get this behavior. Also, if there's anything in my code that is downright appaling, I'd like to know that too.
So, here's my code:
void printArray(int array[], int size) {
printf("[");
for (int i = 0; i < size; i++) {
if (i == (size - 1)) {
printf("%d", array[i]);
} else {
printf("%d, ", array[i]);
}
}
printf("]\n");
}
int getLeftChild(int h_array[], int p_index, int size) {
/* Summary: Obtains the `left child` of Parent at given parent index (p_index)
*
* Input: `h_array` - The binary heap
* `p_index` - The index of the parent that we are currently looking at
* `size` - The size of the binary heap.
*
* Return: `0` if the index given points out of bounds of the array. Returns the child of parent at p_index if not
*/
int child = 0;
if (p_index * 2 + 1 < size) {
child = h_array[p_index * 2 + 1];
}
return child;
}
int getRightChild(int h_array[], int p_index, int size) {
/* Summary: Obtains the `right child` of Parent at given parent index (p_index)
*
* Input: `h_array` - The binary heap
* `p_index` - The index of the parent that we are currently looking at
* `size` - The size of the binary heap.
*
* Return: `0` if the index given points out of bounds of the array. Returns the child of parent at p_index if not
*/
int child = 0;
if ((p_index * 2 + 2) < size) {
child = h_array[p_index * 2 + 2];
}
return child;
}
void heapSort(int h_array[], int size, int min_max) {
/* Summary: Performs a heap sort on a binary heap array; parents with 2 children maximum.
* This could be used to implement a priority queue, as the node with the highest (or lowest)
* priority will be at the root of the list.
* Input: `h_array` - the heap array to sort
* `size` - The size of the heap array
* `min_max` - an input that will tell whether or not we want to return a 'maxed', or a 'min'd' binary heap.
* maxed will have highest priority at the root, and min'd will have the lowest priority at the root
*
* Returns: Does not return. Performs all sorting operations on input array.
**/
int parent, leftChild, rightChild, p_holder, i = 0;
while (i < (size / 2)) {
parent = h_array[i];
leftChild = getLeftChild(h_array, i, size);
rightChild = getRightChild(h_array, i, size);
if (min_max == 0 ) {
while (parent < leftChild || parent < rightChild) {
p_holder = parent;
if (parent < leftChild) {
h_array[i] = leftChild;
h_array[(i * 2) + 1] = p_holder;
} else if (parent < rightChild) {
h_array[i] = rightChild;
h_array[(i * 2) + 2] = p_holder;
}
i = 0;
parent = h_array[i];
leftChild = getLeftChild(h_array, i, size);
rightChild = getRightChild(h_array, i, size);
}
i++;
} else {
while ((leftChild != 0 && parent > leftChild) || (rightChild != 0 &&parent > rightChild)) {
p_holder = parent;
if ((leftChild != 0) && parent > leftChild) {
h_array[i] = leftChild;
h_array[(i * 2) + 1] = p_holder;
} else if ((rightChild != 0) && parent > rightChild) {
h_array[i] = rightChild;
h_array[(i * 2) + 2] = p_holder;
}
i = 0;
parent = h_array[i];
leftChild = getLeftChild(h_array, i, size);
rightChild = getRightChild(h_array, i, size);
}
i++;
}
}
}
void heapAdd(int h_array[], int *a_size, int value, int *min_max_ptr) {
/* Summary: Adds a value to the binary heap
* Input: `h_array` - The binary heap array
* `a_size` - The size of the array. A pointer to `size` located in main().
* `value` - The value that is to be inserted in the array
* Returns: Void function. Performs all operations on inputted array.
*/
*a_size += 1;
int * a_copy = h_array;
h_array = realloc(h_array, *a_size * sizeof(int));
memcpy(h_array, a_copy, (*a_size - 2) * sizeof(int));
h_array[*a_size - 1] = value;
heapSort(h_array, *a_size, *min_max_ptr);
}
void heapSub(int h_array[], int *a_size, int *min_max_ptr) {
/* Summary: Subtracts the root value from the binary heap
* Input: `h_array` - The binary heap array
* `a_size` - The size of the array. A pointer to `size` located in main().
* Returns: Void function. Performs all operations on inputted array.
*/
h_array[0] = h_array[*a_size - 1];
int * a_copy = h_array;
h_array = realloc(h_array, *a_size - 1 * sizeof(int));
memcpy(h_array, a_copy, (*a_size - 1) * sizeof(int));
*a_size -= 1; // Put here in order to not do any stupid calculations in the calls.
heapSort(h_array, *a_size, *min_max_ptr);
}
int main(void) {
char * user_input;
int user_value;
int debug = 0;
// min_max = 0 to produce a max-heap, min_max = 1 to produce a min-heap
int min_max = 0;
int *min_max_ptr = &min_max;
int size = 0;
int *size_ptr = &size;
// Binary Heap array, initialized here
int * main_array = malloc(size * sizeof(int));
// Start building binary heap with the following loop.
while (strcmp(user_input, "q") != 0) {
printf("Current Heap:\n");
printArray(main_array, size);
// Debug
if (debug) {
printf("Current Heap Size: %i\n", size);
}
printf("What is your input?: ");
scanf("%s", user_input);
// Debug
if (debug) {
printf("Current user input is: %s\n", user_input);
}
if (strcmp(user_input, "add") == 0) {
printf("What # will you be adding to the heap?: ");
scanf("%i", &user_value);
heapAdd(main_array, size_ptr, user_value, min_max_ptr);
} else if (strcmp(user_input, "sub") == 0) {
printf("Subtracting %i from array\n", main_array[0]);
heapSub(main_array, size_ptr, min_max_ptr);
} else if (strcmp(user_input, "debug") == 0) {
printf("Do you want to toggle debug mode(y/n): ");
scanf("%s", user_input);
if (strcmp(user_input, "y") == 0) {
debug = (debug == 0) ? 1 : 0;
printf("Debug is: %i", debug);
} else {
continue;
}
} else {
printf("Incorrect Input, please read the instructions more\n\n");
}
printf("\n");
}
free(main_array);
return 0;
}
So that's the code, and here are the test cases:
Subtracting highest value from heap # length = 2 test case 1
Subtracting highest values from heap starting # length = 4 and going to length = 2 test case 2
After that it seems like every other test case works fine (past length = 4 I can add and subtract from binary heap just fine and the sorting process works great). Thank you for your help :)
I was able to reach a solution to my problems by making the following changes to my code:
void heapAdd(int h_array[], int *a_size, int value, int *min_max_ptr) {
/* Summary: Adds a value to the binary heap
* Input: `h_array` - The binary heap array
* `a_size` - The size of the array. A pointer to `size` located in main().
* `value` - The value that is to be inserted in the array
* Returns: Void function. Performs all operations on inputted array.
*/
*a_size += 1;
h_array[*a_size - 1] = value;
heapSort(h_array, *a_size, *min_max_ptr);
}
void heapSub(int h_array[], int *a_size, int *min_max_ptr) {
/* Summary: Subtracts the root value from the binary heap
* Input: `h_array` - The binary heap array
* `a_size` - The size of the array. A pointer to `size` located in main().
* Returns: Void function. Performs all operations on inputted array.
*/
h_array[0] = h_array[*a_size - 1];
h_array[*a_size - 1] = 0;
*a_size -= 1; // Put here in order to not do any stupid calculations in the calls.
heapSort(h_array, *a_size, *min_max_ptr);
}
int main(void) {
char * user_input;
int user_value;
int debug = 0;
// min_max = 0 to produce a max-heap, min_max = 1 to produce a min-heap
int min_max = 0;
int *min_max_ptr = &min_max;
int size = 0;
int *size_ptr = &size;
int alloc_size = 1000;
int * main_array = malloc(alloc_size * sizeof(int));
do {
if (alloc_size - size < 2) {
printf("Reallocating the main_array size");
alloc_size += 1000;
main_array = realloc(main_array, alloc_size * sizeof(int));
if (main_array == NULL) {
printf("realloc addition failed, exiting");
exit(1);
}
} else if (alloc_size - size > 1002) {
alloc_size -= 1000;
main_array = realloc(main_array, alloc_size * sizeof(int));
if (main_array == NULL) {
printf("Realloc subtraction failed, exiting");
exit(1);
}
}
printf("Current Heap:\n");
printArray(main_array, size);
// Debug
if (debug) {
printf("Current Heap Size: %i\n", size);
}
printf("What is your input?: ");
scanf("%s", user_input);
// Debug
if (debug) {
printf("Current user input is: %s\n", user_input);
}
if (strcmp(user_input, "add") == 0) {
printf("What # will you be adding to the heap?: ");
scanf("%i", &user_value);
heapAdd(main_array, size_ptr, user_value, min_max_ptr);
} else if (strcmp(user_input, "sub") == 0) {
if (size == 0) {
printf("Can't subtract any more from the heap.\n");
continue;
} else {
printf("Subtracting %i from array\n", main_array[0]);
heapSub(main_array, size_ptr, min_max_ptr);
}
} else if (strcmp(user_input, "debug") == 0) {
printf("Do you want to toggle debug mode(y/n): ");
scanf("%s", user_input);
if (strcmp(user_input, "y") == 0) {
debug = (debug == 0) ? 1 : 0;
printf("Debug is: %i", debug);
} else {
continue;
}
} else {
printf("Incorrect Input, please read the instructions more fully\n\n");
}
printf("\n");
} while (strcmp(user_input, "q") != 0);
free(main_array);
return 0;
}
This is supposed to be a Two-Way insertion sort, but it's not sorting. I'm also supposed to print out the number of assignments for sorting, but right now I just want it to sort.
A separate output array of size 2n+1 is set aside. Initially x[0] is placed into the middle element of the array n.
Continue inserting elements until you need to insert between a pair of elements in the array.
As before you need to make room for the new element by shifting elements. Unlike before,
you can choose to shift all smaller elements one step to the left or all larger elements one step
to the right since there is additional room on both sides of the array. The choice of which
shift to perform depends on which would require shifting the smallest amount of elements.
I can't find much on the internet about this sort except that no one uses it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printArray(int arr[], int len) {
for (int j = 0; j < len; j++)
printf("%d ", arr[j]);
printf("\n");
}
int main() {
FILE *in;
int size_arr = 0;
char ch;
if ((in = fopen("data_a5.txt", "r")) == NULL) {
printf("Error!");
exit(1);
}
do {
ch = fgetc(in);
if (ch == '\n')
size_arr++;
} while (ch != EOF);
rewind(in);
int arr[size_arr];
int sort_arr[2 * size_arr + 1];
int n = 0;
while (!feof(in)) {
fscanf(in, "%d", &arr[n]);
n++;
}
fclose(in);
for (n = 0; n < 2 * size_arr; n++) {
sort_arr[n] = 0;
}
sort_arr[size_arr] = arr[0];
for (n = 1; n < size_arr; n++) {
int index = size_arr;
if (arr[n] <= sort_arr[size_arr]) {
while (!(arr[n] <= sort_arr[index]) && sort_arr[index] != 0 && index >= 0) {
index--;
}
}
if (arr[n] > sort_arr[size_arr]) {
while (!(arr[n] <= sort_arr[index]) && sort_arr[index] != 0 && index < 2 * size_arr) {
index++;
}
}
if (sort_arr[index] == 0) {
sort_arr[index] = arr[n];
} else {
int next_R, next_L = index;
while (sort_arr[next_R] != 0 && next_R <= 2 * size_arr) {
next_R++;
}
while (sort_arr[next_L] != 0 && next_L >= 0) {
next_L--;
}
int R_move = next_R - index;
int L_move = index - next_L;
if (R_move > L_move) {
while (L_move <= index) {
sort_arr[L_move] = sort_arr[L_move + 1];
L_move++;
}
sort_arr[index] = arr[n];
} else {
while (R_move >= index) {
sort_arr[R_move] = sort_arr[R_move - 1];
R_move--;
}
sort_arr[index] = arr[n];
}
}
}
printArray(arr, size_arr);
return 0;
}
I'm not sure this solves all problems but it is a problem you must fix.
This code
int next_R, next_L = index;
while(sort_arr[next_R] != 0 && next_R <= 2*size_arr)
has undefined behavior as next_R is uninitialized.
Maybe you want:
int next_R = index, next_L = index;
^^^^^
while(sort_arr[next_R] != 0 && next_R <= 2*size_arr)
In any case you have to initialize next_R before using it.
I also find this line strange:
printArray(arr, size_arr);
^^^
Seems you are printing the original array instead of the sorted array.
May be you want:
printArray(sort_arr, size_arr);
^^^^^
There are some problems in your code:
when you scan the file in the first pass, you should count the number of integers instead of the number of characters.
when inserting, your loops are off by one: the tests should read while (L_move < index) and while (R_move >= index)
while (!feof(in)) is always wrong, you should instead write while (fscanf(in, "%d", &arr[n]) == 1) {...
you should probably allocate the arrays arr and sort_arr instead of defining them as VLAs with automatic storage to prevent undefined behavior on large input files.
you should use binary search into the sorted portion, otherwise your algorithm has a basic complexity of O(N2) that dwarfs the small gain obtained from the minimisation of the insertion phase.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
void print_array(const int arr[], int len) {
for (int j = 0; j < len; j++)
printf("%d%c", arr[j], " \n"[j == len - 1]);
}
int main(void) {
FILE *in;
int size_arr, n, start;
int value;
if ((in = fopen("data_a5.txt", "r")) == NULL) {
printf("Cannot open input file %s\n", "data_a5.txt");
exit(1);
}
for (size_arr = 0; fscanf(in, "%d", &value) == 1; size_arr++)
continue;
rewind(in);
int *arr = calloc(2 * size_arr + 1, sizeof(*arr));
if (arr == NULL) {
printf("Cannot allocate memory for %d entries\n", size_arr);
exit(1);
}
start = size_arr;
for (n = 0; n < size_arr && fscanf(in, "%d", &value) == 1; n++) {
/* insert value into the sorted array */
int a, b;
for (a = start, b = start + n; a < b;) {
int mid = a + (b - a) / 2;
if (arr[mid] < value) {
a = mid + 1;
} else {
b = mid;
}
}
/* insert value at offset b */
if (b - start < start + n - b) {
/* shift left portion to the left */
for (int i = start--; i < b; i++) {
arr[i - 1] = arr[i];
}
b--;
} else {
/* shift right portion to the right */
for (int i = start + n + 1; --i > b;) {
arr[i] = arr[i - 1];
}
}
arr[b] = value;
}
fclose(in);
print_array(arr + start, n);
free(arr);
return 0;
}
like this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printArray(int arr[], int len){
while(len--)
printf("%d ", *arr++);
printf("\n");
}
int main(void){
int size_arr = 10;
int arr[size_arr];
int sort_arr[2 * size_arr + 1];
for(int i = 0; i < size_arr; ++i)
arr[i] = -50 + rand() % (100 + 1);
puts("before:");
printArray(arr, size_arr);
int left, right;
sort_arr[left = right = size_arr] = arr[0];
for (int n = 1; n < size_arr; ++n){
int v = arr[n];
if(v <= sort_arr[left]){
sort_arr[--left] = v;
} else if(v >= sort_arr[right]){
sort_arr[++right] = v;
} else {
int L = left, R = right, M, MV;
while(L <= R){
M = L + (R-L)/2;
MV = sort_arr[M];
if(MV < v)
L = M + 1;
else if(v < MV)
R = M - 1;
else
break;
}
//M: insert position
enum { LEFT, RIGHT } CHOICE;
if(v == MV){
int ML = M, MR = M;
while(sort_arr[ML-1] == sort_arr[ML])
--ML;
while(sort_arr[MR] == sort_arr[MR+1])
++MR;
if( ML-left >= right-MR){
M = MR+1;
CHOICE = RIGHT;
} else {
M = ML;
CHOICE = LEFT;
}
} else if(v > MV){
++M;
CHOICE = M-left+1 > right-M;// ? RIGHT : LEFT;
} else {
CHOICE = M-left-1 > right-M;// ? RIGHT : LEFT;
}
if(CHOICE == RIGHT){
memmove(sort_arr + M+1, sort_arr + M, (right-M+1)*sizeof(v));
sort_arr[M] = v;
++right;
} else {
memmove(sort_arr + left-1, sort_arr + left, (M-left)*sizeof(v));
sort_arr[M-1] = v;
--left;
}
}
}
puts("after:");
printArray(sort_arr + left, size_arr);
return 0;
}
My functions (init,draw,move and win) are not working properly. Can anyone shed some light on where I am going wrong?
init - should initialer the board and swap 1 and 2.
draw - should draw the current state of the board.
move - should move the tile if not illegal move.
win - should check the board if its in descending order.
/**
* fifteen.c
*
* Computer Science 50
* Problem Set 3
*
* Implements Game of Fifteen (generalized to d x d).
*
* Usage: fifteen d
*
* whereby the board's dimensions are to be d x d,
* where d must be in [DIM_MIN,DIM_MAX]
*
* Note that usleep is obsolete, but it offers more granularity than
* sleep and is simpler to use than nanosleep; `man usleep` for more.
*/
#
define _XOPEN_SOURCE 500
# include < cs50.h > #include < stdio.h > #include < string.h > #include <
stdlib.h > #include < unistd.h >
// constants
#define DIM_MIN 3# define DIM_MAX 9
// board
int board[DIM_MAX][DIM_MAX];
// dimensions
int d;
// prototypes
void clear(void);
void greet(void);
void init(void);
void draw(void);
bool move(int tile);
bool won(void);
void metrytoexchange(int * a, int * b);
int main(int argc, string argv[]) {
// ensure proper usage
if (argc != 2) {
printf("Usage: fifteen d\n");
return 1;
}
// ensure valid dimensions
d = atoi(argv[1]);
if (d < DIM_MIN || d > DIM_MAX) {
printf("Board must be between %i x %i and %i x %i, inclusive.\n",
DIM_MIN, DIM_MIN, DIM_MAX, DIM_MAX);
return 2;
}
// open log
FILE * file = fopen("log.txt", "w");
if (file == NULL) {
return 3;
}
// greet user with instructions
greet();
// initialize the board
init();
// accept moves until game is won
while (true) {
// clear the screen
clear();
// draw the current state of the board
draw();
// log the current state of the board (for testing)
for (int i = 0; i < d; i++) {
for (int j = 0; j < d; j++) {
fprintf(file, "%i", board[i][j]);
if (j < d - 1) {
fprintf(file, "|");
}
}
fprintf(file, "\n");
}
fflush(file);
// check for win
if (won()) {
printf("ftw!\n");
break;
}
// prompt for move
printf("Tile to move: ");
int tile = GetInt();
// quit if user inputs 0 (for testing)
if (tile == 0) {
break;
}
// log move (for testing)
fprintf(file, "%i\n", tile);
fflush(file);
// move if possible, else report illegality
if (!move(tile)) {
printf("\nIllegal move.\n");
usleep(500000);
}
// sleep thread for animation's sake
usleep(500000);
}
// close log
fclose(file);
// success
return 0;
}
/**
* Clears screen using ANSI escape sequences.
*/
void clear(void) {
printf("\033[2J");
printf("\033[%d;%dH", 0, 0);
}
/**
* Greets player.
*/
void greet(void) {
clear();
printf("WELCOME TO GAME OF FIFTEEN\n");
usleep(2000000);
}
/**
* Initializes the game's board with tiles numbered 1 through d*d - 1
* (i.e., fills 2D array with values but does not actually print them).
*/
void init(void) {
// TODO
int i, j;
int k = d * d - 1;
for (i = 0; i < d; i++) {
for (j = 0; j < d; j++) {
board[i][j] = k--;
if (k % 2 != 0) {
break;
} else {
if ((board[i][j] == 2) && (board[i][j - 1] == 1))
metrytoexchange( & board[i][j], & board[i][j - 1]);
}
}
}
}
/**
* Prints the board in its current state.
*/
void draw(void) { // TODO
int k = d * d - 1;
for (int i = 0; i < d; i++) {
for (int j = 0; j < d; j++) {
board[i][j] = k--;
if (board[i][j] == 0) {
printf("_");
} else
printf("%d \t", board[i][j]);
}
printf("\n");
}
}
void metrytoexchange(int * a, int * b) {
int temp = * a; *
a = * b; *
b = temp;
}
/**
* If tile borders empty space, moves tile and returns true, else
* returns false.
*/
bool move(int tile) {
int k = d * d - 1;
int blank_space = 0;
//dont go beyond the grid
for (int i = 0; i < d; i++) {
for (int j = 0; j < d; j++) {
if (tile < k && tile > 0 && tile == board[i][j]) {
continue;
} else {
break;
}
//iterate to check the position of of blank tile;left to right up and down if not return false
if (board[i - 1][j] != blank_space || board[i][j - 1] !=
blank_space || board[i + 1][j] != blank_space || board[i][j +
1
] != blank_space) {
return false;
}
//else swap tile with blank_space
else {
metrytoexchange( & tile, & blank_space);
return true;
}
}
}
return false;
}
/**
* Returns true if game is won (i.e., board is in winning configuration),
* else false.
*/
bool won(void) {
// TODO
// creat a variable that increases as the loop condition increases.let it start from 1 increasing
int win_board[d][d];
for (int i = 0; i < d; i++) {
for (int j = 0; j < d; j++) {
if (win_board[i][j] == board[i][j]) {
return true;
} else {
return false;
}
}
}
return false;
}
I am trying to write a code which gives coordinates of corners of a skyline, it was one of my friends' homework and I am trying it as a practice for myself. So, here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct building
{
int start, height, width;
} BUILDING;
int main()
{
FILE *buildingsptr, *outlineptr;
char karakter;
int satir = 1, i = 0, j = 0, *heights, lastpoint = 0 ;
BUILDING *ptr, *a, temp;
buildingsptr = fopen("buildings.txt", "r");
if (buildingsptr == NULL)
{
printf("An error occured while opening the file.\n");
system("PAUSE");
return 0;
}
while ((karakter = fgetc(buildingsptr)) != EOF)
{
if (karakter == '\n') satir++;
}
ptr = (BUILDING *) malloc(satir * sizeof(BUILDING));
a = ptr;
rewind(buildingsptr);
for (i = 0; i < satir; i++)
{
fscanf(buildingsptr, "%d %d %d", &ptr->start, &ptr->height, &ptr->width);
ptr++;
}
fclose(buildingsptr);
ptr = a; // a is for accessing the first part of the allocated memory,
// compiler gave some errors while I tried to access the first
// block of the array.
for (j = 0; j < satir; j++) //bubble sort to buildings
{
for (i = 0; i < satir; i++)
{
if (ptr[i].start > ptr[i + 1].start)
{
temp = ptr[i];
ptr[i] = ptr[i + 1];
ptr[i + 1] = temp;
}//end of if
}//end of second for
}//end of first for
lastpoint = ((ptr[satir - 1].start + ptr[satir - 1].width) + 1);
heights = (int *)calloc(lastpoint, sizeof(int));
for (j = 0; j < lastpoint; j++) // j travels the x axis
{
for (i = 0; i < satir; i++) // i counts buildings
{
if (j <= (ptr[i].start + ptr[i].width && ptr[i].start <= j))
{
if (ptr[i].height > heights[i])
heights[i] = ptr[i].height;
}
}
}
outlineptr = fopen("outline.txt", "w");
for (i = 0; i < lastpoint; i++) // for every point x,checking the heights
// and transforming them as the coordinates
{
if (heights[i + 1] > heights[i])
{
fprintf(outlineptr, "(%d,%d),", i + 1, heights[i]);
fprintf(outlineptr, "(%d,%d),", i + 1, heights[i + 1]);
}//end if
if (heights[(i + 1)] < heights[i])
{
fprintf(outlineptr, "(%d,%d),", i, heights[i]);
fprintf(outlineptr, "(%d,%d),", i, heights[i + 1]);
}//end if
}//end for
fprintf(outlineptr, "(%d,%d),", lastpoint, heights[lastpoint]);
fprintf(outlineptr, "(%d,%d)", lastpoint, 0);
getch();
return 0;
}
Code is working but it is writing wrong coordinates to the outline.txt. "buildings.txt" is something like:
24 7 4
5 7 11
26 9 7
9 5 5
3 12 4
33 9 6
37 5 7
12 9 10
First integer is starting point of a building, second one is height of the building and third one is width of the building. So, how can I re-write this code? I edited my code to be more proper.
This is a basic example of how the frame of your program should look.
The implementation of the algorithm itself should be up to you.
There is no need for separate line counting.
#include <stdio.h>
#include <stdlib.h>
typedef struct building
{
int start, height, width;
struct building *next;
struct building *prev;
} BUILDING;
int main()
{
FILE *inputFilePtr;
inputFilePtr = fopen("input.txt", "r");
if (inputFilePtr == NULL)
{
printf("An error occured while opening the file.\n");
return EXIT_FAILURE;
}
struct building *build = malloc(sizeof(*build));
struct building *reserve = build;
reserve->prev = NULL;
build->prev = NULL;
char lineBuf[1024];
while (fgets(lineBuf, 1024, inputFilePtr) != NULL)
{
sscanf(lineBuf, "%d %d %d", &(build->start), &(build->height), &(build->width));
build->next = malloc(sizeof(*build));
build->prev = build;
build = build->next;
}
build->next = NULL;
fclose(inputFilePtr);
/////////
// whatever logic comes here
////////
FILE *out = fopen("out.txt","w");
if (out == NULL) return EXIT_FAILURE;
// modify output function to fit your algorithm
while(reserve->next != NULL)
{
fprintf(out, "Build coordinates: (%d, %d, %d)\n", reserve->start, reserve->height, reserve->width);
reserve->prev = reserve;
reserve = reserve->next;
}
fclose(out);
// possible memory cleanup
/*
while(reserve->prev != NULL)
{
reserve = reserve->prev;
free(reserve->next);
}
*/
return 0;
}