Undefined functions in header file - c

I am trying to create a sudoku solver and want to divide my project into different files.
I want my board.c file to handle the creation and printing of the board while the solver.c file will have the solver functions and such.
I currently have three three files. sudokuSolver.c, board.c, board.h
Have I defined the header files incorrectly or am I missing something else?
sudokuSolver.c:
#include <stdio.h>
#include <stdlib.h>
#include "board.h"
int main()
{
int** board;
board = createBoard();
printBoard(board);
free(board);
return 0;
}
board.h:
#ifndef BOARD_H_
#define BOARD_H_
int ** createBoard();
void printBoard(int**);
#endif
board.c:
#include <stdio.h>
#include <stdlib.h>
#include "board.h"
int** createBoard(){
int array[9][9] = {
{3, 0, 0, 6, 0, 2, 0, 0, 4},
{0, 0, 0, 0, 7, 9, 8, 0, 3},
{0, 1, 0, 0, 0, 0, 7, 0, 0},
{0, 0, 0, 0, 6, 0, 0, 0, 2},
{0, 4, 1, 7, 0, 8, 0, 0, 0},
{7, 0, 6, 0, 0, 0, 4, 0, 0},
{9, 0, 7, 2, 8, 5, 3, 4, 0},
{0, 8, 0, 0, 0, 0, 2, 9, 0},
{1, 2, 3, 0, 4, 7, 5, 6, 0}
};
int k, **board;
board = malloc(9*sizeof(int *));
for(k = 0 ; k < 9 ; k++)
board[k] = malloc(9*sizeof(int) );
for (size_t i = 0; i < 9; i++)
{
for (size_t j = 0; j < 9; j++)
{
board[i][j] = array[i][j];
}
}
return board;
}
void printBoard(int** board){
for (size_t i = 0; i < 9; i++)
{
for (size_t j = 0; j < 9; j++)
{
printf("%d ", board[i][j]);
}
printf("\n");
}
return;
}
EDIT: When I try to compile the code with gcc sudokuSolver.c board.h board.c in the terminal.
After compiling I now have an executable a.exe file that runs the program correctly.
Now I run into a new problem. After the code is compiled I try to run the code directly from Visual Studio Code (Ctrl+Alt+N) But still receive this error:
C:\Users\x\AppData\Local\Temp\ccbnvRga.o:sudokuSolver.c:(.text+0xf): undefined reference to `createBoard'
C:\Users\x\AppData\Local\Temp\ccbnvRga.o:sudokuSolver.c:(.text+0x1f): undefined reference to `printBoard'
collect2.exe: error: ld returned 1 exit status

As Some programmer dude pointed out. I had to configure VSCode to be able to compile multiple source files.
I solved this by adding
,
"code-runner.executorMap": {
"c": "cd $dir && gcc *.c -o $fileNameWithoutExt && $dir$fileNameWithoutExt"
}
in settings of the code Runner extension

Related

printing alphabets using star pattern side by side in C

I am trying to print the initials of My First Name "S S" using * pattern in C. However the patterns are printed one after the other. Is there any way to print the alphabets using * pattern one at the side of the other with a little space in between. I do not want to allot a very big box for both the alphabets. I want to code for individual alphabets and put them side by side with some space in between. My Code and out our is given below:
int k,l,i,j;
for(k=1;k<=7;k++){
for(l=1;l<=4;l++){
if(k==1 && l<=4){
printf("*");
}
else if(k>=2 && k<=3 && l==1){
printf("*");
}
else if(k==4 && l<=4){
printf("*");
}
else if(k>=5 && k<=6 && l==4){
printf("*");
}
else if(k==7 && l<=4){
printf("*");
}
else{
printf(" ");
}
}
printf("\n");
}
for(i=1;i<=7;i++){
for(j=1;j<=4;j++){
if(i==1 && j<=4){
printf("*");
}
else if(i>=2 && i<=3 && j==1){
printf("*");
}
else if(i==4 && j<=4){
printf("*");
}
else if(i>=5 && i<=6 && j==4){
printf("*");
}
else if(i==7 && j<=4){
printf("*");
}
else{
printf(" ");
}
}
printf("\n");
}
return 0;
}
Output:
****
*
*
****
*
*
****
****
*
*
****
*
*
****
However, I want my expected output to be:
**** ****
* *
* *
**** ****
* *
* *
**** ****
The most important thing when approaching problems like this is to decompose your code in smaller pieces, using functions and/or typedefs or structs to organize things. In your case, you can easily separate the "knowledge" of how to print stars and spaces for your letters from the main code (which knows which letters to print in which order) using functions. Refactoring you code that way, we get:
void S(int k, int l) {
if(k==1 && l<=4){
printf("*");
}
else if(k>=2 && k<=3 && l==1){
printf("*");
}
else if(k==4 && l<=4){
printf("*");
}
else if(k>=5 && k<=6 && l==4){
printf("*");
}
else if(k==7 && l<=4){
printf("*");
}
else{
printf(" ");
}
}
int main() {
int k,l,i,j;
for(k=1;k<=7;k++){
for(l=1;l<=4;l++){
S(k, l);
}
printf("\n");
}
for(i=1;i<=7;i++){
for(j=1;j<=4;j++){
S(i, j);
}
printf("\n");
}
return 0;
}
Now you can easily rewrite main to print the letters side by side
int main() {
int k,l,i,j;
for(k=1;k<=7;k++){
for(l=1;l<=4;l++){
S(k, l);
}
printf(" ");
for(j=1;j<=4;j++){
S(k, j);
}
printf("\n");
}
return 0;
}
You could also extend this by writing different letters in different patterns (though having a function for each letter is somewhat verbose -- better would be to store the pixels for all letters in a data structure and print it that way)
Use pattern matrix for every character you want to print. It'll make printing easier. You run through each letter of the string to print for every row in the pattern.
#include <stdio.h>
#include <string.h>
#define ROWMAX 7
#define COLMAX 5
#define CSPACE 1
#define PATTERN '#'
char cCube [26][ROWMAX][COLMAX] = {
{ {0, 1, 1, 1, 1}, // letter S
{1, 1, 0, 0, 1},
{1, 1, 0, 0, 0},
{0, 1, 1, 1, 0},
{0, 0, 0, 1, 1},
{1, 0, 0, 1, 1},
{1, 1, 1, 1, 0}
},
{ {0, 1, 1, 1, 0}, // letter O
{1, 1, 0, 1, 1},
{1, 0, 0, 0, 1},
{1, 0, 0, 0, 1},
{1, 0, 0, 0, 1},
{1, 1, 0, 1, 1},
{0, 1, 1, 1, 0}
},
{ {1, 1, 1, 1, 0}, // letter D
{1, 0, 0, 1, 1},
{1, 0, 0, 0, 1},
{1, 0, 0, 0, 1},
{1, 0, 0, 0, 1},
{1, 0, 0, 1, 1},
{1, 1, 1, 1, 0}
}, //so on for alphabets you want to use
};
int chIndex [256] = {0};
void print_pat_msg (const char* msg) {
int mlen = strlen (msg);
for (int ri = 0; ri < ROWMAX; ++ri) {
for (int mi = 0; mi < mlen; ++mi) {
int chi = chIndex[ (unsigned char) msg[mi]];
for (int ci = 0; ci < COLMAX; ++ci)
(cCube[chi][ri][ci]) ? putchar (PATTERN) : putchar (' ');
for (int spi = 0; spi++ < CSPACE;) putchar (' ');
}
putchar ('\n');
}
printf ("\n");
}
int main () {
// if patterns are indexed alphabetically below initialisation can be omitted
chIndex[ (unsigned char) 'S'] = 0;
chIndex[ (unsigned char) 'O'] = 1;
chIndex[ (unsigned char) 'D'] = 2;
char message [] = "ODDS";
print_pat_msg (message);
return 0;
}
This way you can design/customise the pattern for each letter with ease at one place. Code & pattern can be reused for other messages & names.
Printing here works somewhat like a dot-matrix printer, striping across putting out pattern-line of each letter in the string one at a time.
You can also replace 0/1 flags with pretty much any character to draw ASCII images. You just have to adjust the pattern array, which is easy to follow & change at will.
Come to think of it, this is how fonts work at pixel level, patterns.
My quickie solution:
#include <stdio.h>
static const unsigned char S[] = {0xF0, 0x80, 0x80, 0xF0, 0x10, 0x10, 0xF0};
int main(void) {
for(int i=0; i<sizeof(S); ++i)
{
for(int b=7;b; --b)
{
printf("%c", "* "[!(S[i] & (1<<b))]);
}
for(int b=7;b; --b)
{
printf("%c", "* "[!(S[i] & (1<<b))]);
}
printf("\n");
}
return 0;
}
Output:
Success #stdin #stdout 0s 5548KB
**** ****
* *
* *
**** ****
* *
* *
**** ****

change indexing of array in c

I am stuck in the problem of an array. I want to print something like this in C language.
input= arr[14]={2,0,2,2,0,1,1,4,0,4,2,2,3,3};
output I need is: output=arr2[6]={2022,01,14,04,22,33};
is this possible in the c language. your help will be very appreciated. thanks
arr2[0] = arr[0]*1000 + arr[1]*100 + arr[2]*10 + arr[3]; arr2[1] = arr[4]*10 + arr[5]; ...
or, if you really really want to make a function
#include <stdio.h>
void mix2(int *a, int *b, int alen) {
for (int i = 0; i < alen; i++) {
a[i] = b[2*i]*10 + b[2*i+1];
}
}
int main(void) {
int arr[14] = {2, 0, 2, 2, 0, 1, 1, 4, 0, 4, 2, 2, 3, 3};
int arr2[6];
mix2(arr2, arr + 2, 6); // 22, 01, 14, 04, 22, 33 into arr2
arr2[0] += arr[0]*1000 + arr[1]*100; // add missing terms
printf("arr2:");
for (int i = 0; i < 6; i++) printf(" %d", arr2[i]);
printf("\n");
return 0;
}

Initialize 2D array in C using array of pointers

I have a static array that I want to use to initialize a dynamic array using pointers.
Right now I have this:
boardinit[BOARD_HEIGHT][BOARD_LENGTH] = {
{-4, -2, -3, -5, -6, -3, -2, -4},
{-1, -1, -1, -1, -1, -1, -1, -1},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 1, 1, 1, 1, 1, 1},
{4, 2, 3, 5, 6, 3, 2, 4},
};
int main()
{
int board[BOARD_HEIGHT][BOARD_LENGTH];
initboard(board);
for (int j = 0; j < BOARD_HEIGHT; j++)
{
for (int i = 0; i < BOARD_LENGTH; i++)
printf("%d ", board[j][i]);
printf("\n");
}
return 0;
}
void initboard(int (*pboard)[BOARD_HEIGHT])
{
for(int i = 0;i<BOARD_HEIGHT;i++)
pboard[i] = boardinit + i;
}
I want board[BOARD_HEIGHT][BOARD_LENGTH] to initialize as boardinit[BOARD_HEIGHT][BOARD_LENGTH] by passing board to initboard() using pointers, but can't seem to get it to go.
To copy the contents boardinit to the value of board, just use this:
memcpy(board, boardinit, sizeof(board));
If that does not work, try this:
void initboard(int pboard[BOARD_HEIGHT][BOARD_LENGTH]) {
for (int i = 0; i < BOARD_HEIGHT; i++)
for (int j = 0; j < BOARD_LENGTH; j++)
pboard[i][j] = boardinit[i][j];
}
"I have a static array that i want to use to initialize a dynamic array using pointers."
The problem with arrays of pointers is that each call to [m][c]alloc() is not guaranteed (in fact is not likely) to provide a single contiguous block of memory. i.e., this is a common approach that provide many little areas of memory:
int **array = malloc(sizeof(width * sizeof(int *));
{
for(int i=0; i<width; i++)
{
array[i] = malloc(height*sizeof(int));
}
}
Thus, the initializer would need to be broken into several memory block locations.
A simpler and more efficient way to do this is with a single dynamic memory allocation call, guaranteeing a single contiguous block of memory, then a single memcpy() is possible using the initializer into the pointer location returned from [m][c]alloc(). The only problem then is how to access the memory area with array notation. The example below illustrates how this can be done using *(ptr + index) notation...
//assuming your other code above
int main(void)
{
int elements = BOARD_HEIGHT*BOARD_LENGTH;
int *pArray = calloc(elements, sizeof(int));
if(pArray)
{
memcpy(pArray, boardinit, sizeof boardinit);
for(int i=0; i<BOARD_HEIGHT;i++)
for(int j = 0;j<BOARD_LENGTH;j++)
printf("%d\n", *(pArray + (i + j)));
free(pArray);
}
return 0;
}

Incorrect results when printing out a submatrix of a 2D array in C

I'm new to C and learning about arrays. I've made a function, print2d, to print out a two dimensional array. I've created a 9x9 array, array2d. First, I printed out array2d using print2d, which worked perfectly. Then, I tried to print out a 3x3 submatrix of array2d that consists of elements in the first three rows and first three columns. The 3x3 submatrix is printed out incorrectly.
In main:
int array2d[9][9] = {
{0, 1, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0}
};
print2d(rows,cols,array2d);
print2d(3,3,array2d); // print 3x3 submatrix
void print2d(int rows, int cols, int array[][cols])
{
printf("{");
for (int r = 0; r < rows; r++)
{
printf("{%i",array[r][0]);
for (int c = 1; c < cols; c++)
{
printf(", %i",array[r][c]);
}
printf("}\n");
}
printf("}\n");
}
Output:
The 9x9 matrix array2d is printed out properly, but the 3x3 submatrix is printed out as:
{{0, 1, 0}
{0, 0, 0}
{0, 0, 0}
}
instead of
{{0, 1, 0}
{0, 0, 0}
{1, 1, 0}
}
The first row of the submatrix is correct, but the third row is not. My guess is that by calling print2d(3,3,array2d), the function print2d is expecting a 2d array with 3 columns (int array[][3]), rather than a 9x9 array. I'm not sure what kind of problem that is causing, and why the first row of the output is correct but not the third. Thank you for your help!
You can use double pointer instead of 2D array
void print2d(int rows, int cols, int **array);
Or define the sub array as #Weather_Vane comment above:
void print2d(int rows, int cols, int array[rows][cols], int sub_row, int sub_col) {
for (int r = 0; r < sub_row; r++)
{
...
for (int c = 1; c < sub_col; c++)
{
...
}
...
}
printf("}\n");
}
main function for array with sub array arguments
print2d(9,9,array2d, 9, 9);
print2d(9,9,array2d, 3, 3);
main function for double pointer:
int main() {
int rows, cols, i;
int **array2d;
/* obtain values for rows & cols*/
// allocate the array
array2d = malloc(rows * sizeof(int));
if (!array2d)
return -1;
for (i=0; i<rows; i++) {
array2d[i] = malloc(cols * sizeof *array2d[i]);
if(!array2d[i])
return -1;
}
/*init the values of array here */
print2d(rows,cols,array2d);
for (i=0; i<rows; i++)
free(array2d[rows];
free(array2d);
}

How to fix ' Error: invalid read of size 4'

I'm trying to learn C and am completing different challenges in order to learn faster. The code seems logical to me and should progress. However, I'm getting an invalid read of size four on line 29
I've tried to change the data type that gets parsed through, but it didn't seem to work.
#include <unistd.h>
typedef struct s_grid
{
int x;
int y;
} t_grid;
void set_point(t_grid *coord, int i, int j)
{
coord->x = i;
coord->y = j;
}
//check loccation of next zero
int where_is_zero(int **sudoku)
{
int x;
int y;
t_grid coord;
x = 0;
y = 0;
while (x < 9)
{
y = 0;
while (y < 9)
{
if (sudoku[x][y] == 0) //Here I'm getting the error.
{
set_point(&coord, x, y);
return (0);
}
x++;
}
y++;
}
return (1);
}
int solve_sudoku(int **grid)
{
int row;
int col;
int num;
t_grid coord;
if (where_is_zero(grid) == 1)
return (1);
row = coord.x;
col = coord.y;
//where_is_zero(grid);
num = 1;
while (num <= 9)
{
if (check_number(grid, row, col, num) == 1)
{
grid[row][col] = num;
if (solve_sudoku(grid) == 1)
return (1);
grid[row][col] = 0;
}
num++;
}
return (0);
}
void ft_putchar(char c)
{
write(1, &c, 1);
}
void ft_putstr(char *str)
{
while (*str != '\0')
{
ft_putchar(*str);
str++;
}
}
//my main function
int main(int argc, char **argv)
{
int board[9][9] ={ { 0, 9, 0, 0, 0, 0, 8, 5, 3 },
{ 0, 0, 0, 8, 0, 0, 0, 0, 4 },
{ 0, 0, 8, 2, 0, 3, 0, 6, 9 },
{ 5, 7, 4, 0, 0, 2, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 9, 0, 0, 6, 3, 7 },
{ 9, 4, 0, 1, 0, 8, 5, 0, 0 },
{ 7, 0, 0, 0, 0, 6, 0, 0, 0 },
{ 6, 8, 2, 0, 0, 0, 0, 9, 0 } };
solve_sudoku(board);
return (0);
}
I removed some code just to highlight where the problem is. It should find the next 0 in the table and set the coordinations to my structure.
The problem lies in how you have the loop set up. See my comments below:
while (x < 9)
{
y = 0;
while (y < 9)
{
if (sudoku[x][y] == 0) //Here I'm getting the error.
{
set_point(&coord, x, y);
return (0);
}
x++; // This increments the x index while you're inside the y loop
}
y++; // This increments the y index when you meant to increment the x
}
If you swap both lines, that should work fine and will resolve your out-of-bounds error.
What would also help you write this better is instead of using a while loop, use a for loop. If you haven't covered that topic yet, it's really straightforward:
for(int x = 0; x < 9 ; ++x)
{
for (int y = 0; y < 9; ++y)
{
if (sudoku[x][y] == 0) //Here you won't get the error anymore!
{
set_point(&coord, x, y);
return (0);
}
}
}
What the for loop line means there is this: Start the loop by setting it to 0, at the end of an iteration, increment it. On the next iteration, check if x is still less than 9. If so, proceed with the next iteration.
Your problem is due to mixing types. In main() you declare:
int board[9][9] = { ....
You then pass:
solve_sudoku(board);
board has the type int (*)[9] (a pointer to array of int [9]). See C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3). Your solve_soduku expects a parameter of type int** (pointer to pointer to int).
int solve_sudoku(int **grid) { ...
The type are NOT compatible. (and your compiler should be screaming warnings at you)
board is a pointer to array of int [9], while grid is a pointer to pointer to int. You must make the types compatible. The easiest way is to change solve_sudoku to
int solve_sudoku(int (*grid)[9]) { ...
Otherwise you will need to declare board as int** and allocate and fill in main().

Resources