Hey guys so Im trying to do a homework and I cant find the fatal error on my program all day long.Let me explain :
Firstly,you give the number of rows,col then the cells of the array (only "." for free spaces and "*" for mines, all in one row without spaces) then the crashing happens.
main(){
int i,col,row,count,N,M,j;
char **p;
printf("Give number of rows\n");
scanf("%d",&N);
printf("Give number of columns\n");
scanf("%d\n",&M);
p=malloc(N*sizeof(char *)); //Saving room for the array
if (p==NULL)
return -1;
for (i=0;i < N ; ++i){
p[i] = malloc (M * sizeof(char));
if (*(p+i) == NULL)
return -1;
}
for (i=0; i< N;++i){
for ( j = 0 ; j < M ;++j)
scanf("%c",&p[i][j]); //Insert "*" for mines and the rest with "."
}
for (row=1; row<= N;++row){ //Here the things get messy
for ( col = 1 ; col <= M ;++col){
if(p[row][col]=='.'){
count = 0 ;
if(p[row][col+1]=='*' && col < M)
count=count+1;
if(p[row][col-1]=='*' && col > 1)
count=count+1;
if(p[row+1][col]=='*' && row < N)
count=count+1;
if(p[row-1][col]=='*' && row > 1)
count=count+1;
if(p[row+1][col+1]=='*' && (row < N && col < M))
count=count+1;
if(p[row+1][col-1]=='*' && (row < N && col > 1))
count=count+1;
if(p[row-1][col+1]=='*' && ( row > 1 && col < M))
count=count+1;
if(p[row-1][col-1]=='*' && ( row > 1 && col > 1))
count=count+1;
printf("%d ", count);
}
printf("* ");
}
printf("\n");
}
printf("\n");
for (i=0; i< N;++i){
for ( j = 0 ; j < M ;++j)
printf("%c ",p[i][j]);
printf("\n");
}
for (i = 0 ; i <N ; ++i)
free(p[i]);
free(p);
}
Firstly, here's what I did to debug (actually I saw the problem in the code and just verified this way, but this will be useful to you).
Add #include <stdio.h> and #include <stdlib.h> at the head of the file.
gcc -Wall -O0 -g x.c -o x to compile with debug and no optimisation.
I then used following to run within gdb:
gdb x
...
(gdb) run
Starting program: /home/amb/so/x
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7ffff7ffa000
Give number of rows
1
Give number of columns
1
.
Program received signal SIGSEGV, Segmentation fault.
0x00000000004007d4 in main () at x.c:25
25 if(p[row][col]=='.'){
(gdb) print row
$1 = 1
(gdb) print col
$2 = 1
(gdb)
See how in less than 10 seconds it showed me where the error was?
You have two problems:
for (row=1; row<= N;++row){ //Here the things get messy
for ( col = 1 ; col <= M ;++col){
if(p[row][col]=='.'){
The SEGV appears here as you access p[N][M], but the indices of p can only go from 0 to N-1 and 0 to M-1 respectively. This loop should probably read:
for (row=0; row < N;++row){ //Here the things get messy
for ( col = 0 ; col < M ;++col){
if(p[row][col]=='.'){
(note change to start at row=0, and row < N not row <= M and similarly for col).
The second problem you have is to do with what to do at the edges:
Lines like this:
if (p[row][col-1]=='*' && col > 1)
count=count+1;
should have the col > 1 condition first so they don't evaluate the array element unless the condition is true. Also, as col goes 0..M-1, you want
if ((col > 0) && (p[row][col-1]=='*'))
count=count+1;
Note I've put in some brackets to avoid any ambiguity.
The same applies when looking at the other edges:
if (p[row][col+1]=='*' && col < M)
count=count+1;
should be:
if ((col < M-1) && (p[row][col+1]=='*'))
count=count+1;
That should get you going. But learn to use a debugger.
Related
I printed V using * in specific rows and columns. I had lots of if statements. I am sharing my code below.
Is there any optimised way to print the V pattern in 10X10 row column? (without many if conditions)?
#include <stdio.h>
int main() {
int row, column;
for (row = 1; row <= 10; row++) {
for (column = 1; column <= 10; column++) {
if (row == 1 && (column == 1 || column == 10)
|| row == 3 && (column == 2 || column == 9)
|| row == 5 && (column == 3 || column == 8)
|| row == 7 && (column == 4 || column == 7)
|| row == 10 && column == 5)
printf("*");
else
printf(" ");
}
printf("\n");
}
return 0;
}
A reasonable option when you need to output arbitrary amounts of spaces is to use printf string width specifier to left-pad with spaces:
printf("%*s*", spaces, "");
The above will output the empty string, padded up to a width of the integer value spaces, and then output a *. Note that the format string %*s means that you specify both a width and then a string as extra arguments. The * in that part has nothing to do with an actual *. We add that onto the end of the format string.
So, for the V shape, each line has two * characters on it, except the last line (if the width is odd). One way to do this intuitively is to track the position of the left and the right part of the V for each line, and then do the math for determining how much padding to add.
Example:
void v(int width)
{
int l = 0, r = width;
for (; l < r; l++, r--)
{
printf("%*s*%*s\n", l, "", r-l, "*");
}
if (l == r)
printf("%*s*\n", l, "");
}
If you really want more condensed code, you can elect to roll that last line into the loop. In this case, when l == r you want to only output a single asterisk. Otherwise you want two. So you could output the string &"*"[l==r] -- that will mean that when l==r is true, you'll skip over the asterisk and it will look like an empty string (because you land on the NUL terminator).
Note this is not great style. It sacrifices readability for compactness.
void v(int width)
{
for (int l = 0, r = width; l <= r; l++, r--)
{
printf("%*s*%*s\n", l, "", r-l, &"*"[l==r]);
}
}
So, this is "efficient" in terms of compact code and not many function calls. If you instead are concerned about the format parsing of printf then you can avoid it entirely. Below, we use the same left/right bounds and just walk through each row using loops. This essentially does what our printf is doing internally, except it's more obvious what's going on:
void v(int width)
{
int l = 0, r = width-1;
for (; l <= r; l++, r--)
{
int x = 0;
for (; x < l; x++) putchar(' ');
putchar('*');
if (x < r)
{
for (x++; x < r; x++) putchar(' ');
putchar('*');
}
putchar('\n');
}
}
Now for some fun...
As an exercise, here is the printf approach but with no loops (using recursion):
void vv(int width, int row) {
if(width >= 0) {
printf("%*s*%*s\n", row, "", width, &"*"[width==0]);
vv(width-2, row+1);
}
}
void v(int width) {
vv(width, 0);
}
And here is that idea turned into an intentionally horrendous mess that looks cool. ;)
#include <stdio.h>
#define VV int
#define vV "*\0%*s%*s\n"
VV Vv( VV v ,VV
vv){if(v -->0){
printf (vV+2,
vv++ ,vV,v
,vV+ !v);
Vv(-- v,vv
);}} VV V
(VV v){
Vv(v,
1);
}
int main() {
for (int v = 1; v < 12; v++) {
printf("size %d\n", v);
V(v);
}
}
I don't think this is optimized but will be simpler and scalable with SIZE.
#include <stdio.h>
#define SIZE 10
#define MID ((SIZE-1)/2) // midst position of SIZE
#define ABS(x) ((x)<0?-(x):(x)) // absolute value of x
int main()
{
int i, j;
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
if (i % 2 == 0 && ABS(j - MID) == MID - i / 2) putchar('*');
else putchar(' ');
}
putchar('\n');
}
return 0;
}
[Explanation]
Assuming SIZE equals to 10, the value MID is calculated to be 4.
Then the v shaped asterisks will be placed symmetrically wrt the 4th column.
Let's put numbers in columns (j) and rows (i) as follows:
012345678
* * 0 ABS(0 - 4) == 4 - 0, ABS(8 - 4) == 4 - 0
1 skipped as i & 2 != 0
* * 2 ABS(1 - 4) == 4 - 1, ABS(7 - 4) == 4 - 1
3 skipped
* * 4 ABS(2 - 4) == 4 - 2, ABS(6 - 4) == 4 - 2
5 skipped
* * 6 ABS(3 - 4) == 4 - 3, ABS(5 - 4) == 4 - 3
7 skipped
* 8 ABS(4 - 4) == 4 - 4
The equations above are the conditions to put the asterisks.
For instance, in the 0th row, we want to put it on 0th column and 8th.
The condition j - 4 == +/- 4 or ABS(j - 4) == 4 will represent the conditions due to the symmetricity.
If we generarize the condition across rows, we can describe it as
i % 2 == 0 && ABS(j - MID) == MID - i / 2.
This code considers the relation between the row and the position of the *, if you are in the first row, then we want the column 0 and colum 9 to print *, then second row, we want column 1 and column 8 and so on. Thus, I used an iterator for the rows and iterator for columns to know in a concrete row which column I'm printing.
#include <stdio.h>
int main()
{
int matrix_size = 10; //Assuming is squared matrix 10x10
int counter = 0;
int i,j;
for(i=0;i<(int)(matrix_size/2);i++) {
for(j=0;j<matrix_size;j++) {
if(j==i || j==(matrix_size-1-i)) {
printf("*");
}else{
printf(" ");
}
}
printf("\n");
}
return 0;
}
EDIT: compared to tshiono solution, I write the V in just 5 rows and he prints it in 10 rows but assuming an space line between each line. Boths solutions are ok depending on what u want.
For the V shape to be symmetric, the number of rows and columns should be odd. Here is a simpler method:
#include <stdio.h>
#include <stdlib.h>
int main() {
for (int n = 11, row = 0; row < n; row++) {
for (int column = 0; column < n; column++)
putchar(" *"[2 * abs(column - n / 2) == n - 1 - row]);
printf("\n");
}
return 0;
}
Output:
* *
* *
* *
* *
* *
*
For a thicker V shape:
#include <stdio.h>
#include <stdlib.h>
int main() {
for (int n = 11, row = 0; row < n; row++) {
for (int column = 0; column < n; column++)
putchar(" *"[abs(2 * abs(column - n / 2) - (n - 1 - row)) <= 1]);
printf("\n");
}
return 0;
}
Output:
* *
** **
* *
** **
* *
** **
* *
** **
* *
***
*
Other answers take into account the specific shape of V and optimize around that.
I suggest an optimized solution for any shape.
This involves a lookup table containing all the locations of * characters composing the shape.
struct { int row,col; } shape[] = {
{1,1}, {1,10}, {3,2}, {3,9}, {5,3}, {5,8}, {7,4}, {7,7}, {10,5},
{-1,-1}
};
The last location ({-1,-1}) has the same purpose as terminating '\0' for strings.
I'm trying to implement my own version of the sum of subsets problem, using backtracking, to get all the possible solutions of obtaining a given sum from an array of elements. At the moment, I'm getting output stuck in an infinite, the output adds up to the sum that I want, but it exceeds the number of elements of a type available in the array. I'm not sure why this happens, because I put some stopping conditions. The code:
#include <stdio.h>
#define MAX 1024
int coins_array[] = {1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,10,10,10,10,10,15,15,15,15,15,15};
int N = sizeof(coins_array) / sizeof(coins_array[0]);
int S = 27, Sol[MAX], sum, sol;
int acceptable(int step)
{
int i = 0, sum = 0;
for(i = 1; i <= step; i++)
{
sum += Sol[i];
}
if((sum <= S) && (step <= N))
return 1;
return 0;
}
int solution(int sum)
{
if (sum == S)
return 1;
return 0;
}
void print_solution(int step)
{
int i;
for(i = 1 ; i <= step ; ++i)
printf("%d ",Sol[i]);
printf("\n");
}
void back(int step)
{
int i;
for(i = 0; i < N; i++)
{
Sol[step] = coins_array[i];
sum += coins_array[i];
if(acceptable(step) == 1)
{
if(solution(sum) == 1)
{
print_solution(step);
}
else
back(step+1);
}
sum -= coins_array[i];
}
}
int main()
{
back(1);
return 0;
}
Output (in an infinite loop):
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3
So, the numbers add up to the desired sum, however it exceeds the number of available 1's, and doesn't make use of 10 or 15. I ran to this in the debugger and I believe the problem for the loop is at back(step+1). Any idea how I could fix this?
Not sure this covers all problems in your code but it's at least its one bug that needs to be fixed.
Your current code uses the same coin several times. For instance if you set the target to be 2 (i.e. S = 2), your code will generate a solution where coins_array[0] is used twice.
This happens because your back function always starts looking at the coins_array from index zero.
void back(int step)
{
int i;
for(i = 0; i < N; i++)
^^^^^
Always starting from zero is wrong
Instead you need to start from the "next unused" coin. Unfortunately your current code doesn't track that so you need to redesign your solution.
To show the above described problem I made some minor changes to your program - 1) Reduced the available coins 2) Changed the target value 3) Added an array to track which coin (aka index) was used 4) printed the index
So with these change your code looks like:
#define MAX 1024
int coins_array[] = {1,1,3};
int N = sizeof(coins_array) / sizeof(coins_array[0]);
int S = 2, Sol[MAX], IndexUsed[MAX], sum, sol;
int acceptable(int step)
{
int i = 0, sum = 0;
for(i = 1; i <= step; i++)
{
sum += Sol[i];
}
if((sum <= S) && (step <= N))
return 1;
return 0;
}
int solution(int sum)
{
if (sum == S)
return 1;
return 0;
}
void print_solution(int step)
{
int i;
for(i = 1 ; i <= step ; ++i)
printf("%d (%d) ",Sol[i], IndexUsed[i]);
printf("\n");
}
void back(int step)
{
int i;
for(i = 0; i < N; i++)
{
Sol[step] = coins_array[i];
IndexUsed[step] = i;
sum += coins_array[i];
if(acceptable(step) == 1)
{
if(solution(sum) == 1)
{
print_solution(step);
}
else
back(step+1);
}
sum -= coins_array[i];
}
}
int main()
{
back(1);
return 0;
}
and generates the output (with my comments added):
1 (0) 1 (0) // Illegal - coin at index 0 used twice
1 (0) 1 (1) // Legal - coin at index 0 and 1 used to reach the sum 2
1 (1) 1 (0) // Illegal - this combination have already been used
1 (1) 1 (1) // Illegal - coin at index 1 used twice
As you can see, your code prints 4 solutions but it should only have printed 1. As already stated, this happens because your code always start from index zero in the function back
i am writing a simple simulator of spilling eggs in а pan with the flood fill algorithm in C. So the pan is a char matrix, and with '#' are his walls,'.' means that the place is empty and 'O' that it has a egg that will spill.
That is an example of what that program should do.
10 10
..##......
.#O.#.....
.#..#..#..
..##..#.#.
.......#..
..#####...
..#...#...
..#...##..
...##..#..
....####..
⇨
..##......
.#OO#.....
.#OO#..#..
..##..#.#.
.......#..
..#####...
..#***#...
..#***##..
...##**#..
....####..
i have written that:
#include <stdio.h>
void food_fill(int,int,char [1000][1000],int,int,char);
int main(){
int row,col,rows,cols;
scanf("%d %d",&rows,&cols);
getchar();
char matrix [rows][cols];
for(row = 0;row < rows;row++){
for(col = 0;col < cols;col++){
scanf("%c",&matrix[row][col]);
}
getchar();
}
int foodX=0,foodY=0;
char foodChar='s';
for(row=0;row<rows;row++){
for(col = 0;col < cols;col++){
if(matrix[row][col] == 'O'){
foodX = row;
foodY = col;
foodChar = matrix[row][col];
}
}
}
food_fill(rows,cols,matrix,foodX,foodY,foodChar);
for(row = 0;row < rows;row++){
for(col = 0;col <cols;col++){
printf("%c",matrix[row][col]);
}
printf("\n");
}
return 0;
}
void food_fill(int rows,int cols,char matrix[rows][cols],int foodX,int foodY,char foodChar){
int r=rows,c=cols;
if(matrix[foodX][foodY] == '#')return;
if(foodX < 0 || foodX >= rows || foodY < 0 || foodY >= cols)return;
matrix[foodX][foodY] = foodChar;
food_fill(r,c,matrix,foodX+1,foodY,foodChar);
food_fill(r,c,matrix,foodX-1,foodY,foodChar);
food_fill(r,c,matrix,foodX,foodY+1,foodChar);
food_fill(r,c,matrix,foodX,foodY-1,foodChar);
}
It is not completed yet but the food_fill() function resulted in segmentation fault and i don't know why.
if(matrix[foodX][foodY] == '#')return;
if(foodX < 0 || foodX >= rows || foodY < 0 || foodY >= cols)return;
Order is wrong. As a result you are accessing invalid indices. Giving you segmentation fault. Correct one would be
if(foodX < 0 || foodX >= rows || foodY < 0 || foodY >= cols)return;
if(matrix[foodX][foodY] == '#')return;
Also there are bugs on many levels.
You are having an infinite loop due to repetitive similar calls.
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
void food_fill(int rows,int cols,char matrix[][cols],int foodX,int foodY,char foodChar){
matrix[foodX][foodY] = foodChar;
for(int i=0;i<4;i++){
if( foodX+dx[i]>=0 && foodX+dx[i]<rows && foodY+dy[i] >=0 && foodY+dy[i]<cols && matrix[foodX+dx[i]][foodY+dy[i]] != '#' && matrix[foodX+dx[i]][foodY+dy[i]]!=foodChar){
food_fill(rows,cols,matrix,foodX+dx[i],foodY+dy[i],foodChar);
}
}
}
The main condition change is
if( foodX+dx[i]>=0 && foodX+dx[i]<rows && foodY+dy[i] >=0 && foodY+dy[i]<cols && matrix[foodX+dx[i]][foodY+dy[i]] != '#' && matrix[foodX+dx[i]][foodY+dy[i]]!=foodChar){
do you know the minesweeper game of windows . well , the following problem is the same , you will input m and n ...
0 < n,m <= 100
n : colons , m : rows
input :
4 4
*...
....
.*..
....
output :
*100
2210
1*10
1110
and , that is my code .
#include <stdio.h>
#include <stdlib.h>
char ms[100][101] ;
int m , n;
void input(){
for(int r = 0 ; r < m ; r++)
for(int c = 0 ; c <= n ; c++){
scanf("%c",&ms[r][c]);
if('.' == ms[r][c])
ms[r][c] += 2 ;
}
}
void calc(int m , int n){
for(int r = m ; r <= (m+2) ; r++)
for(int c = n ; c <= (n+2) ; c++)
if(r >= 0 && c >= 0 && ms[r][c] != '*')
ms[r][c] += 1 ;
}
void solve(){
for(int r = 0 ; r < m ; r++)
for(int c = 0 ; c < n ; c++)
if( '*' == ms[r][c])
calc(r-1 , c-1);
}
void output(){
for(int r = 0 ; r < m ; r++)
for(int c = 0 ; c <= n ; c++)
printf("%c ", ms[r][c]);
}
int main()
{
scanf("%d%d" , &m , &n);
input();
solve();
output();
return 0;
}
when running my code , if the input have * at the first as follows :
4 4
*...
....
.*..
....
the output is :
important to see it .. click here
note: i tried to print the value of the symbol that appeard in the picture and it is 11 in ascii code which is vertical tab.
and , another problem if the * is at the last as follows :
4 4
...*
....
....
...*
000*
0000
0000
000*
but my code works well when the * is at the middle as follows :
4 4
....
..*.
.*..
....
0111
12*1
1*21
1110
so , what's the problem with my code ?
In this line you can go out of bounds:
if(r >= 0 && c >= 0 && ms[r][c] != '*')
ms[r][c] += 1 ;
You only test if r and c are not negative, but you should also test they are not too large.
The thing becomes more complicated because you have global variables m and n which are the dimensions of your array, but they are not available in the calc function, because there you have local variables with the same name.
So you better use different variable names. And then you should test that r<m and c<n, as follows:
void calc(int p , int q){
for(int r = p ; r <= (p+2) ; r++)
for(int c = q ; c <= (q+2) ; c++)
if(r >= 0 && c >= 0 && r < m && c < n && ms[r][c] != '*')
ms[r][c] += 1 ;
}
Now the reason you saw an ASCII 11 is explained by the fact that ASCII 10 is the line feed character that marks the end of a row. Then when your code performs ms[r][c] += 1 on it (because it goes too far), it becomes that funny character.
That you have that ASCII 10 in your array is explained by how you read the input (see #pmg's answer). If you would not have read those white space characters, you would still overrun, and probably touch data in a next row of data, which is not what you want to happen.
scanf("%d", ...);
leaves whitespace (the ENTER) in the input buffer. Then
scanf("%c", ...);
reads that whitespace into the variable.
You need to ignore the whitespace before (and during) reading the stars and dots.
Use
scanf(" %c", ...);
// ^^^ ignore whitespace
Note: the conversion specifier "%d" (and many others) already includes ignoring whitespace; the exceptions are "%c", "%[", and [for different reasons] "%n").
So for my assignment I have to take the inputs of length and width and print out patterns of "*" based on the inputs. The minimum height is 7 and only goes up by odd integers and width is any multiple of 6.
The basic format of the output using a height of 7 and width of 12:
************
************
*** ***
*** ***
*** ***
************
************
So basically the first and last 2 lines are straight through the entire width, with the odd numbered rows containing 3 asterisks followed by 3 spaces, until it reaches the end of the width. The even numbered rows start off with 3 spaces.
I've figured out how to print the first two lines using the following code:
do
{
printf("*");
++i;
}while(i<width);
printf("\n");
do
{
printf("*");
++j;
}while(j<=width);
printf("\n");
But for the life of me, I cannot come up with the correct way to use basic nested loops to print out the inside pattern. I asked a programmer friend who is unfamiliar with C but wrote up a basic program in Java. I don't know Java and have tried to translate it but notice some big discrepancies in the logic between the two languages that is causing me headaches. Here is his code:
// LOGGING
var consoleLine = "<p class=\"console-line\"></p>";
console = {
log: function (text) {
$("#console-log").append($(consoleLine).html(text));
}
};
// PATTERN PARAMETERS
var rows = 6;
var cols = 7;
// hard code a space so html respects it
var space = " "
console.log("cols: " + cols + " rows: " + rows);
for (y = 0; y < rows; ++y) {
var line = "";
for (x = 0; x < cols; ++x) {
// First two and last two rows do not have patterns and just print filled
if (y == 0 || y == 1 || y == rows - 1 || y == rows - 2) {
line += "*";
} else {
if (y % 2 == 0) {
// Even row
line += x % 6 < 3 ? "*" : space;
} else {
// Odd row
line += x % 6 >= 3 ? "*" : space;
}
}
}
console.log(line);
}
Please help me or point me in the right direction!! I've searched online but can't seem to find a solution that's worked yet!
Edit- forgot to mention that all "printf" uses can only print one character at a time... Such as a single *
Edit edit- I GOT IT WORKING!!!! Thank you all so, so much for your input and guidance! Here's what I have that is working perfectly:
for (y = 0; y < height; ++y)
{
printf("\n");
for (x = 0; x < width; ++x)
{
// First two and last two rows do not have patterns and just print filled lines
if (y == 0 || y == 1 || y == height - 1 || y == height - 2)
{
printf("*");
}
else
{
if (y % 2 == 0)
{
if(x%6<3)
{
printf("*");
}
else
{
printf(" ");
}
} else {
// Odd row
if(x%6>=3)
{
printf("*");
}
else
{
printf(" ");
}
}
}
}
printf("\n");
Write a function with 3 arguments n,a,b that prints n groups of 3 of each argument a and b alternately. You can call this function to print the 4 different kinds of lines. You can make a loop to print the middle section repeatedly. Have fun!
A simpler alternative:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int row, col, height = atoi(argv[1]), cols = atoi(argv[2]);
for (row = 0; row < height; row++) {
for (col = 0; col < cols; col++) {
putchar(row < 2 || row >= height - 2 ||
col % 6 / 3 == row % 2 ? '*' : ' ');
}
putchar('\n');
}
}