Parse Text File in C - Skip Lines - Repeated Calculation - c

I have been spinning my wheels for a while trying to figure this out but have not been able to. Hope you can help!
I am currently working on a program that solves Sudoku. The current code that I am showing below takes in as input a 9x9 grid of integers (the Sudoku puzzle) and then generates a solution. This is working fine.
#include <stdio.h>
int isAvailable(int puzzle[][9], int row, int col, int num)
{
int rowStart = (row/3) * 3;
int colStart = (col/3) * 3;
int i, j;
for(i=0; i<9; ++i)
{
if (puzzle[row][i] == num) return 0;
if (puzzle[i][col] == num) return 0;
if (puzzle[rowStart + (i%3)][colStart + (i/3)] == num) return 0;
}
return 1;
}
int fillSudoku(int puzzle[][9], int row, int col)
{
int i;
if(row<9 && col<9)
{
if(puzzle[row][col] != 0)
{
if((col+1)<9) return fillSudoku(puzzle, row, col+1);
else if((row+1)<9) return fillSudoku(puzzle, row+1, 0);
else return 1;
}
else
{
for(i=0; i<9; ++i)
{
if(isAvailable(puzzle, row, col, i+1))
{
puzzle[row][col] = i+1;
if((col+1)<9)
{
if(fillSudoku(puzzle, row, col +1)) return 1;
else puzzle[row][col] = 0;
}
else if((row+1)<9)
{
if(fillSudoku(puzzle, row+1, 0)) return 1;
else puzzle[row][col] = 0;
}
else return 1;
}
}
}
return 0;
}
else return 1;
}
int main()
{
int i, j;
int row,column;
int puzzle[9][9];
//printf("Enter your input:\n");
for (row=0; row <9; row++){
for(column = 0; column <9; column ++){
scanf("%d",&puzzle[row][column]);
}
}
//PRINT INPUT PUZZLE
printf("Original Puzzle:");
printf("\n+-----+-----+-----+\n");
for(i=1; i<10; ++i)
{
for(j=1; j<10; ++j) printf("|%d", puzzle[i-1][j-1]);
printf("|\n");
if (i%3 == 0) printf("+-----+-----+-----+\n");
}
printf("\n");
//PRINT OUTPUT PUZZLE
printf("Solved Puzzle:");
if(fillSudoku(puzzle, 0, 0))
{
printf("\n+-----+-----+-----+\n");
for(i=1; i<10; ++i)
{
for(j=1; j<10; ++j) printf("|%d", puzzle[i-1][j-1]);
printf("|\n");
if (i%3 == 0) printf("+-----+-----+-----+\n");
}
printf("\n");
}
else printf("\n\nNO SOLUTION\n\n");
return 0;
}
I now want to use a text file from Project Euler (https://projecteuler.net/project/resources/p096_sudoku.txt) and have my program generate all 50 of these solutions. The text file has the following format:
Grid 01
003020600
900305001
001806400
008102900
700000008
006708200
002609500
800203009
005010300
Grid 02
200080300
060070084
030500209
000105408
000000000
402706000
301007040
720040060
004010003
...
and so on for 50 total grids.
My question is: What is the best way to parse through this file to
Skip over the "Grid ##" line
Read in the next 9 lines for input
Continue on through the file to repeat the program until the end of the file
EDIT:
Between steps 2 & 3, this is what would happen:
After I read in 9 lines of numbers, I'll use that as input to the program and have the program run and generate a solution, and then look back to the input file and get the next set of numbers and run another iteration of the program.
Thank you for any input and guidance you can provide me!
-Colton

When data in a text file is line formatted, strongly recommend using fgets().
Consider each group of 10 lines as a record. They belong together, if 1 part is in error, the whole group is invalid.
// return 0 on success, -1 on EOF and 1 on format failure
int ReadPuzzle(FILE *inf, int puzzle[][9], int *Grid) {
char buffer[20]; // About 2x expected need
if (fgets(buffer, sizeof buffer, inf) == NULL)
return -1; // File EOF or IO error occurred.
if (sscanf(buffer, "Grid %d", Grid) != 1)
return 1;
for (int row = 0; row < 9; row++) {
if (fgets(buffer, sizeof buffer, inf) == NULL)
return 1; // If Grid line exists, 9 lines _should_ follow
char *p = buffer;
for (int col = 0; col < 9; col++) {
// Use %1d to limit scanning to 1 digit
if (sscanf(p, "%1d", &puzzle[row][col]) != 1)
return 1;
p++;
}
}
return 0;
}
Checks could be added to insure extra data is not on the lines.

You probably want to do some stuff between steps 2 & 3, but what you outline sounds reasonable.

Related

"If statement" is not working properly in c

I have written a program with a function that looks at a two dimensional array ir_data[60][768].
The While loop should call the "Hotspotberechnung" function only when there is a value that equals or is over 30 in a given row.
"Hotspotberechnung" should store the given row in an array[24][32] and then print the array.
The problem is that the program prints an array without any values equal or over 30.
Unfortunately, I cannot find the mistake on my own.
The While Loop:
int8_t Temperatur[768] = {0};
while (get_ir_data( &Temperatur[0], sizeof(Temperatur)/sizeof(Temperatur[0])) == 0)
{
for(int k=0; k<768; k++)
{
if(Temperatur[k] >= 30)
{
Hotspotberechnung(Temperatur,bild);
}
}
}
The function :
bool Hotspotberechnung(int8_t tabelle1[768],int8_t tabelle2[24][32])
{
int i=0, j=0, x=0, y=0;
for(j=0; j<24; j++) //Tabellen werden gefüllt
{
for(i=0; i<32; i++)
{
tabelle2[j][i] = tabelle1[(j*24)+i];
}
}
for(j=0; j<24; j++)
{
for(i=0; i<32; i++)
{
printf("%d.%d=%d\n",j,i,tabelle2[j][i]);
}
}
get_ir_data :
int8_t get_ir_data(int8_t* data, int n)
{
static uint8_t idx = 0;
if (n != 24 * 32) {
printf("Invalid size of array data!\n");
return -1;
}
memcpy(data, ir_data[idx], n);
idx++;
if (idx >= sizeof(ir_data) / sizeof(*ir_data))
return -2;
return 0;
}
tabelle1[(j*24)+i]
This index calculation is wrong. You need
tabelle1[(j*32)+i]
To verify, calculate the maximal value of (j*24)+i, given the ranges of j (0 to 23) and j (0 to 31). Is it 767?

Why I can't assign a function return to a matrix element?

Ok, so I need to input a matrix of n elements and to replace each composite number with the closest prime number. I made functions for reading the matrix, showing the matrix, finding if a number is prime or not and finding the closest prime number to a number and they work.
Here is what I did and the problem is that the replacement does not work and I get the error: Process terminated with status -1073741510 (0 minute(s), 18 second(s))
#include <stdio.h>
#include <stdlib.h>
int n;
int readMatrix(int **matrix)
{
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
printf("matrix[%d][%d]=", i, j);
scanf("%d", &matrix[i][j]);
}
}
return matrix;
}
void showMatrix(int **matrix)
{
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
int prime(int a)
{
int c = 0;
for (int i=1; i<a; i++) {
if (a % i == 0) {
c++;
}
}
if (c == 1) {
return 1;
} else return 0;
}
int nearPrime(int b)
{
int lp, bp, ok = 0, p;
lp = b - 1;
bp = b + 1;
while (ok != 1) {
if (prime(lp) == 1) {
ok = 1; break;
}
lp--;
}
ok = 0;
while (ok != 1) {
if (prime(bp) == 1) {
ok = 1; break;
}
bp++;
}
if ((b-lp) < (bp-b)) {
p = lp;
} else p = bp;
return p;
}
int main()
{
int **matrix, aux;
printf("n=");
scanf("%d", &n);
matrix = malloc(n*sizeof(int *));
if (matrix == NULL) exit(1);
for (int i=0; i<n; i++) {
matrix[i] = malloc(n*sizeof(int));
if (matrix[i] == NULL) exit(1);
}
readMatrix(matrix);
showMatrix(matrix);
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
if (prime(matrix[i][j]) == 0 && matrix[i][j] != 1) {
matrix[i][j] = nearPrime(matrix[i][j]);
}
}
}
showMatrix(matrix);
for (int i=0; i<n; i++) free(matrix[i]);
free(matrix);
return 0;
}
Can you tell me why it is not working?
UPDATE
I think I solved it. When checking if a matrix number is prime I also added the condition that it needs to be different than 1 because the program will return 0 when checking if 1 is prime number and it needs to return 1 since 1 is actually a prime number.
Thanks for all the tips!
I think I may have found the issue in your code. The problem lies in your nearPrime function. It will work for most numbers that it takes in as an argument but that is not the case if you input the number 1 for this function. Consider what will happen if it does take in the number 1.
Then, your variable lp = (1 - 1) = 0. When you then further input this into the prime function, it will not return 1 because of the way it is implemented. You then keep on decreasing this number if no prime is found and since the number is now negative, it will never even enter in the for loop in the prime function and the prime function will then always return 0. Thus, you will get stuck in the while(ok != 1) loop for a really long time and that is why your process terminates. To fix this, make sure you check that lp != 0 before proceeding to enter the loop. Since you are also checking for the nearest prime, you also need to check if lp is 0 before returning a value. In short, make the following change to your code.
int nearPrime(int b)
{
int lp, bp, ok = 0, p;
lp = b - 1;
bp = b + 1;
if (lp != 0)
{
while (ok != 1) {
if (prime(lp) == 1) {
ok = 1; break;
}
lp--;
}
}
ok = 0;
while (ok != 1) {
if (prime(bp) == 1) {
ok = 1; break;
}
bp++;
}
if (((b - lp) < (bp - b)) && lp != 0) {
p = lp;
}
else p = bp;
return p;
}
One other thing: your readMatrix function seems to expect a return type of int but you are returning the argument matrix, which is of type int**. Furthermore, in your main code, you are not actually doing anything with your returned value so probably change the return type of your readMatrix function to void (and don't return matrix, of course).

How do I print an "x" shape?

I needed some help with my homework. I've spent about 2 hours on this but I can't get my head around it (c programming). I have to print an x like so:
* *
* *
* *
* *
*
* *
* *
* *
* *
The steps of the program should work like this.
1. User inputs a single number which is the size (this single number is basically the width and height). Also we can assume the user always puts an odd number (so we don't need conditions for that).
2. It draws the X in respect to that size.
However, I can only use while loops, and if statements, scanf and printf. Nothing else.
This is what I can get so far (just a diagonal)
row = 0;
while (row < size) {
column = 0;
while (column < size) {
if (row == column) {
printf("*");
} else {
printf(" ");
}
column++;;
}
printf("\n");
row++;
}
this should work
#include <stdio.h>
int main()
{
int size, row, column;
scanf("%d", &size);
row = 0;
while (row < size)
{
column = 0;
while (column < size)
{
if (column == row || column == size - row - 1)
{
printf("x");
}
else
{
printf(" ");
}
column++;
}
printf("\n");
row++;
}
return 0;
}
#include <stdio.h>
int main(void) {
int size = 11; //this should be the size given by user.
char line[size + 1];
int i;
for(i = 0; i < size; i++) line[i] = ' ';
line[size] = '\0';
int se = 0;
int sw = size - 1;
while(se < size && sw >= 0){
line[se] = line[sw] = 'x';
printf("%s\n", line);
line[se++] = line[sw--] = ' ';
}
return 0;
}
Tested on Ideone and worked.
You are checking only one diagonal.To get the required pattern ,change the if condition as follows...
if ((row == column)||(row==(size-column-1)))

Read a matrix from a file

This is my function to read a matrix from a file. In the text file I have on the first line 2 is n and 3 is m and on the next two lines is the matrix.
I don't have erros, but my program "stop working" and I don't know why. Thank you!
In main I have: readmatrix(n,m,a, "text.txt");
int readmatrix(int* n,int *m, int a[*n][*m], char* filename){
FILE *pf;
int i,j;
pf = fopen (filename, "rt");
if (pf == NULL)
return 0;
fscanf (pf, "%d",n);
for (i=0;i<*n;i++)
{
for(j=0;j<*m;j++)
fscanf (pf, "%d", &a[i][j]);
}
fclose (pf);
return 1;
}
If your compiler supports VLAs or you are using C99, then you can do this:
#include <stdio.h>
int readmatrix(size_t rows, size_t cols, int (*a)[cols], const char* filename)
{
FILE *pf;
pf = fopen (filename, "r");
if (pf == NULL)
return 0;
for(size_t i = 0; i < rows; ++i)
{
for(size_t j = 0; j < cols; ++j)
fscanf(pf, "%d", a[i] + j);
}
fclose (pf);
return 1;
}
int main(void)
{
int matrix[2][3];
readmatrix(2, 3, matrix, "file.dat");
for(size_t i = 0; i < 2; ++i)
{
for(size_t j = 0; j < 3; ++j)
printf("%-3d ", matrix[i][j]);
puts("");
}
return 0;
}
file.dat looks like this:
1 2 3
4 5 6
and the output of my program is
$ ./a
1 2 3
4 5 6
Note that this is a basic example, you should always check the return value of
fscanf. If file.dat had one row only, then you would get in trouble. Also
there are not numbers in the file, you would get also undefined values in the
matrix.
I'd advice to read the whole line with fgets and then parse the line using
sscanf or some other function like strtok, then it would be easier to react
to errors in the input file.
edit
A more robust way of reading a file like this would be:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int **readmatrix(size_t *rows, size_t *cols, const char *filename)
{
if(rows == NULL || cols == NULL || filename == NULL)
return NULL;
*rows = 0;
*cols = 0;
FILE *fp = fopen(filename, "r");
if(fp == NULL)
{
fprintf(stderr, "could not open %s: %s\n", filename, strerror(errno));
return NULL;
}
int **matrix = NULL, **tmp;
char line[1024];
while(fgets(line, sizeof line, fp))
{
if(*cols == 0)
{
// determine the size of the columns based on
// the first row
char *scan = line;
int dummy;
int offset = 0;
while(sscanf(scan, "%d%n", &dummy, &offset) == 1)
{
scan += offset;
(*cols)++;
}
}
tmp = realloc(matrix, (*rows + 1) * sizeof *matrix);
if(tmp == NULL)
{
fclose(fp);
return matrix; // return all you've parsed so far
}
matrix = tmp;
matrix[*rows] = calloc(*cols, sizeof *matrix[*rows]);
if(matrix[*rows] == NULL)
{
fclose(fp);
if(*rows == 0) // failed in the first row, free everything
{
fclose(fp);
free(matrix);
return NULL;
}
return matrix; // return all you've parsed so far
}
int offset = 0;
char *scan = line;
for(size_t j = 0; j < *cols; ++j)
{
if(sscanf(scan, "%d%n", matrix[*rows] + j, &offset) == 1)
scan += offset;
else
matrix[*rows][j] = 0; // could not read, set cell to 0
}
// incrementing rows
(*rows)++;
}
fclose(fp);
return matrix;
}
int main(void)
{
size_t cols, rows;
int **matrix = readmatrix(&rows, &cols, "file.dat");
if(matrix == NULL)
{
fprintf(stderr, "could not read matrix\n");
return 1;
}
for(size_t i = 0; i < rows; ++i)
{
for(size_t j = 0; j < cols; ++j)
printf("%-3d ", matrix[i][j]);
puts("");
}
// freeing memory
for(size_t i = 0; i < rows; ++i)
free(matrix[i]);
free(matrix);
return 0;
}
Now file.dat looks like this:
1 2 3 4
4 5 6 5
9 8 8 7
5 5 5 5
1 1 1 1
And the output is
1 2 3 4
4 5 6 5
9 8 8 7
5 5 5 5
1 1 1 1
In this example I calculate the number of columns only for the first column and
use that number for all other columns. If the input file has rows with less
columns that the first row, then the missing values are stored with 0. If it has rows with
more columns than the row will be trimmed.
I calculate the number of rows like this:
while(sscanf(scan, "%d%n", &dummy, &offset) == 1)
{
scan += offset;
(*cols)++;
}
First I declare a pointer scan to point to line, so that I can modify the
pointer without losing the original line. The %n in sscanf is not counted in
the number of successfull conversions, this returns the position of scan where
it stopped reading. I used that to loop the sscanf. I explicitly check that
sscanf returns 1 and if that's the case, I increment the number of columns and
I update scan to update to the point where sscanf stoppped reading. This
allows me to continue scanning until the end of the line is reached. I use a
similar technique to parse all the integers.
If you're not afraid of using goto, an easy-to-read, robust way to read a matrix looks like this:
typedef struct Matrix
{
size_t width, height;
double **data;
} Matrix;
Matrix read_matrix(char const *filename)
{
Matrix matrix;
FILE *file;
if ((file = fopen(filename, "rt")) == NULL)
goto error;
if (fscanf(file, "%zu %zu", &matrix.width, &matrix.height) != 2)
goto error_file;
if ((matrix.data = (double **)calloc(matrix.height, sizeof(double *))) == NULL)
goto error_file;
for (size_t y = 0; y < matrix.height; ++y)
if ((matrix.data[y] = (double *)malloc(matrix.width * sizeof(double))) == NULL)
goto error_matrix;
for (size_t y = 0; y < matrix.height; ++y)
for (size_t x = 0; x < matrix.width; ++x)
if (fscanf(file, "%lf", &matrix.data[y][x]) != 1)
goto error_matrix;
fclose(file);
return matrix;
error_matrix:
for (size_t y = 0; y < matrix.height; ++y)
free(matrix.data[y]);
free(matrix.data);
error_file:
fclose(file);
error:
return (Matrix){0, 0, NULL};
}

8 Queens puzzle with recursive deep search

I'm trying to solve the 8 queens puzzle problem in C. I'm having problems with the recursive search. The program is supposed to start at a given column:
execute(tabuleiro,8,0);
Where the 8 is the number of columns in the board, and 0 is the start column.
This works when I start at column 0. When I send any other column number to the recursive search, the program just counts to the last column. For example, if I choose to start the search from the number 5 column, the code search from the column 5 to 7, after this it should search from 0 to 4, but it doesn't do that.
If I do this:
execute(tabuleiro,8,3);
It fills in only the last 5 colummns, and does not return to column 0 to finish the solution:
Also, how can I select the initial position for the queen in this code? Like I said before, the column is assigned in the code, but I'm not sure how to pick the correct column.
The code has 3 functions: one is to display the board, a second to check if the move is legal (so one queen doesn't attack the other), and the last one to place one queen and recur for the remainder of the board.
#include <stdlib.h>
#include <windows.h>
int sol = 0;
void viewtab(int tab[][8], int N)
{
int i,j;
for( i = 0; i < N; i++)
{
for( j = 0; j < N; j++)
{
if(tab[i][j] == 1)
printf("R\t");
else
printf("-\t");
}
printf("\n\n");
}
printf("\n\n");
system("pause");
printf("\n");
}
int secury(int tab[][8], int N, int lin, int col)
{
// this function is to check if the move is secury
int i, j;
// attack in line
for(i = 0; i < N; i++)
{
if(tab[lin][i] == 1)
return 0;
}
//attack in colune
for(i = 0; i < N; i++)
{
if(tab[i][col] == 1)
return 0;
}
// attack in main diagonal
//
for(i = lin, j = col; i >= 0 && j >= 0; i--, j--)
{
if(tab[i][j] == 1)
return 0;
}
for(i = lin, j = col; i < N && j < N; i++, j++)
{
if(tab[i][j] == 1)
return 0;
}
// attack in main secondary
for(i = lin, j = col; i >= 0 && j < N; i--, j++)
{
if(tab[i][j] == 1)
return 0;
}
for(i = lin, j = col; i < N && j >= 0; i++, j--)
{
if(tab[i][j] == 1)
return 0;
}
// if arrive here the move is secury and return true
return 1;
}
void execute(int tab[][8], int N, int col)
{
int i;
if(col == N)
{
printf("Solution %d ::\n\n", sol + 1);
viewtab(tab, N);
sol++;
return;
}
for( i = 0; i < N; i++)
{
// check if is secury to put the queen at that colune
if(secury(tab, N, i, col))
{
// insert the queen (with 1)
tab[i][col] = 1;
// call recursive
execute(tab, N, col + 1);
// remove queen (backtracking)
tab[i][col] = 0;
}
}
}
int main()
{
int i, j, tabuleiro[8][8];
for (i = 0; i < 8; i = i + 1)
for (j = 0; j < 8; j = j + 1) tabuleiro[i][j] = 0;
execute(tabuleiro,8,0);
return 0;
}
The search always stops in the rightmost column because you specifically tell it to stop there:
void execute(int tab[][8], int N, int col)
{
int i;
if(col == N)
{
printf("Solution %d ::\n\n", sol + 1);
viewtab(tab, N);
sol++;
return;
}
Look at your termination condition: you check the current column against the highest column number, and stop there.
If you want to go back to column 0, you have to change your loop logic. For instance, let col reach N, at which point you reset it to 0, and let it continue until you hit the original value. Another way is to continue until the count of placed queens is N.
You choose the initial point in the same way: you pick the first one and make your recursive call. If that eventually results in a solution, you print it. If not, your top-most call continues to the next row (line) of the board and puts the first queen there.
This is already in your main logic. Just make sure that secury will return true when the board is empty, rather than false or throwing an error.
A. You can place the first Queen at (0,0).
B. And begin the search also from (0,0).
C. I do not see any need to start looking for some other index.
Successfully!!

Resources