Regarding spatial resolution conversion programming - bmp image - c

I want to ask something about simple spatial resolution manipulating just by using c language. I have done my programming below, it managed to be compiled but for some reasons the program stucked in the middle when I try to run it. Really hope you guys can help. I am extremely beginner on this.
#include<stdio.h>
#define width 640
#define height 581
int main(void)
{
FILE *fp;
unsignedchar header[54];
unsignedchar img_work[width][height][3];
char input_file[128],output_file[128];
int v, h, w, i, c, s, ave_w[width], ave_h[height], average_h, average_w;
/*------------Reading image------------*/
printf("Enter name of the file¥n---");
scanf("%s",input_file);
printf("The file that would be processed is %s.¥n", input_file);
fp=fopen(input_file,"rb");
fread(header,1,54,fp);
fread(img_work,1,width*height*3,fp);
fclose(fp);
/*------------Spatial Resolution Program------------*/
printf ("enter level of spatialization-- ");
scanf ("%d", &v);
for (i=0; i<v; i++) {
s = s + s;
}
for(c=0; c<3; c++){
for(h=0; h<height; h++){
for(w=0; w<width; w=w+s){
average_w = 0;
for (i=0; i<s; i++) {
ave_w = img_work[w+i][h][c] / s;
average_w = average_w + ave_w;
}
for (i=0; i<width; i=i+s) {
img_work[w+i][h][c] = average_w;
}
}
}
}
for(c=0; c<3; c++){
for(w=0; w<width; w++){
for(h=0; h<height; h=h+s){
average_h = 0;
for (i=0; i<s; i++) {
ave_h = img_work[w][h+i][c] / s;
average_h = average_h + ave_h;
}
for (i=0; i<height; i=i+s) {
img_work[w][h+i][c] = average_h;
}
}
}
}
/*------------Writing File------------*/
printf("Enter the name of the file that would be saved.¥n---");
scanf("%s",output_file);
printf("Name of the file that would be saved is %s.¥n",output_file);
fp=fopen(output_file,"wb");
fwrite(header,1,54,fp);
fwrite(img_work,1,width*height*3,fp);
fclose(fp);
printf("End.¥n");
return 0;
}
I am really a beginner, so, sorry if this is lacking too much.

There are several issues with your code:
s is uninitialised. Hence, when you access its value in the assignment s = s + s, the result is undefined. s may even be negative. Initialise it: s = 1;
You've got the representation of your image wrong. You read the pixel data verbatim from the file. The BMP format is row major, so your pixel data should be img_work[height][width][3] and all accesses should have their first and second dimensions swapped.
The BMP format also requires padding at the end of each row. Your fixed-size width of 640 doesn't require it, but it's worth keeping in mind when you want to make your implementation more general.
You don't really need the auxiliary variables ave_w and ave_h. Most importantly, you don't need them to be arrays.
Your height isn't evenly divisible by s. That means that in the last pass through the loop, h + i will go out of bounds. (The same applies to the width, but the value 640 is safe up to at least a level of 7.) You could calculate an "actual s" that would be adjusted for the top and right sides.
When you calculate the average, it is better to sum the values first and then divide by s once. You are dealing with integers and integer division truncates. For example 3/4 is zero. Consequently, (3/4 + 3/4 + 3/4 + 3+4) is also zero, but (3 + 3 + 3 + 3) / 4 is 3. You can notice the effect for larger levels of reduction, where a predominantly white imagfe becomes darker if you divide on summation.
Here's a program based on yours, that puts the points raised above into practice:
#include <stdio.h>
#define width 640
#define height 581
int main(void)
{
FILE *fp;
unsigned char header[54];
unsigned char img_work[height][width][3];
char input_file[128];
char output_file[128];
int v, h, w, i, c, s;
/*------------Reading image------------*/
printf("Enter name of the file\n---");
scanf("%s",input_file);
printf("The file that would be processed is %s.\n", input_file);
fp=fopen(input_file,"rb");
fread(header,1,54,fp);
fread(img_work,1,width*height*3,fp);
fclose(fp);
/*------------Spatial Resolution Program------------*/
printf("enter level of spatialization-- ");
scanf("%d", &v);
s = 1;
for (i = 0; i < v; i++) {
s = s + s;
}
for (c = 0; c < 3; c++) {
for (h = 0; h < height; h++) {
for (w = 0; w < width; w = w + s) {
int average_w = 0;
int ss = s;
if (w + ss > width) ss = width % s;
for (i = 0; i < ss; i++) {
average_w = average_w + img_work[h][w + i][c];
}
for (i = 0; i < ss; i++) {
img_work[h][w + i][c] = average_w / ss;
}
}
}
}
for (c = 0; c < 3; c++) {
for (w = 0; w < width; w++) {
for (h = 0; h < height; h = h + s) {
int average_h = 0;
int ss = s;
if (h + ss > height) ss = height % s;
for (i = 0; i < ss; i++) {
average_h = average_h + img_work[h + i][w][c];
}
for (i = 0; i < ss; i++) {
img_work[h + i][w][c] = average_h / ss;
}
}
}
}
/*------------Writing File------------*/
printf("Enter the name of the file that would be saved.\n---");
scanf("%s",output_file);
printf("Name of the file that would be saved is %s.\n",output_file);
fp=fopen(output_file,"wb");
fwrite(header,1,54,fp);
fwrite(img_work,1,width*height*3,fp);
fclose(fp);
printf("End.\n");
return 0;
}
That's still a quick-and-dirty program with fixed image sizes. It doesn't enforce that the actual size of the image, which can be read from the header, and the fixed sizes match or that the colour depth is the same or that you even get enough pixel data, for which you should check the return value of fread.

Related

Can't figure out what's wrong with my code for a HackerRank problem in C

I'm sorry to ask help for a HackerRank problem here, I know it's not really the right place but nobody is answering me on HackerRank. Also, I'm new in C, so don't be to rude please.
Problem's description:
You are given n triangles, specifically, their sides a, b and c. Print them in the same style but sorted by their areas from the smallest one to the largest one. It is guaranteed that all the areas are different.
Link to the problem : https://www.hackerrank.com/challenges/small-triangles-large-triangles/problem
We can only edit the sort_by_area function.
First of all, I didn't calculate the triangles' area, I've just calculated the perimeter of each triangle, because the formula is simpler to read and to execute. Normally, that doesn't change anything for the result since a bigger perimeter means a bigger area. Tell me if I'm wrong.
The problem is that I have unexpected results: there's numbers on a line from my output that I really don't know from where they come. See:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct {
int a;
int b;
int c;
} triangle;
void sort_by_area(triangle *tr, int n) {
// Array for storing the perimeter.
int *size = malloc(100 * sizeof(*size));
// Adding perimeters in size array.
for (int i = 0; i < n; i++) {
size[i] = tr[i].a + tr[i].b + tr[i].c;
}
// Sort.
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (size[j] > size[j + 1]) {
// Sort in size array.
int temp = size[j];
size[j] = size[j + 1];
size[j + 1] = temp;
// Sort in tr array.
temp = tr[j].a;
tr[j].a = tr[j + 1].a;
tr[j + 1].a = temp;
temp = tr[j].b;
tr[j].b = tr[j + 1].b;
tr[j + 1].b = temp;
temp = tr[j].c;
tr[j].c = tr[j + 1].c;
tr[j + 1].c = temp;
}
}
}
}
int main() {
int n;
scanf("%d", &n);
triangle *tr = malloc(n * sizeof(triangle));
for (int i = 0; i < n; i++) {
scanf("%d%d%d", &tr[i].a, &tr[i].b, &tr[i].c);
}
sort_by_area(tr, n);
for (int i = 0; i < n; i++) {
printf("%d %d %d\n", tr[i].a, tr[i].b, tr[i].c);
}
return 0;
}
Input:
3
7 24 25
5 12 13
3 4 5
Output:
0 417 0 // Unexpected results on this line.
3 4 5
5 12 13
Expected output:
3 4 5
5 12 13
7 24 25
It seems that an error occurs from the 7 24 25 triangle, but for me, my code seems to be good.... Can you help to find out what's wrong ? I really want to understand before going to another problem.
The assumption that a greater parameter implies a greater area is incorrect. Why? Imagine an isosceles triangle with a base of 1000 units and a height of 1e-9 units. The area is minuscule, compared to an equilateral triangle with unit length whereas the former has a huge perimeter (~2000 units) compared to the latter (3 units). That's just an (extreme) example to convey the flaw in your assumption.
I'd suggest you roll up your own area function. It's even mentioned on the problem page to use Heron's formula. Since it's just to be used in the comparison, then we don't need the exact area but an indicative area. So something like
double area(triangle const* tr) {
if(tr) {
double semiPerimeter = (tr->a + tr->b + tr->c)/2.0;
return semiPerimeter* (semiPerimeter - tr->a) * (semiPerimeter - tr->b) * (semiPerimeter - tr->c);
} else {
return 0;
}
}
Where we don't really need to calculate the square root since we just need to compare the areas across triangles and comparing the square of areas across triangles should be fine.
After this, it's just a matter of plugging this into whatever you did, after correcting the inner j loop to run only till n-1 (as the other answer has also explained)
void sort_by_area(triangle* tr, int n) {
/**
* Sort an array a of the length n
*/
double areaArr[n];
for(size_t i = 0; i < n; ++i) {
areaArr[i] = area(&tr[i]);
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n - 1; j++) {
if (areaArr[j] > areaArr[j + 1]) {
// Sort in area array.
int temp = areaArr[j];
areaArr[j] = areaArr[j + 1];
areaArr[j + 1] = temp;
// Sort in tr array.
triangle tmp = tr[j];
tr[j] = tr[j + 1];
tr[j + 1] = tmp;
}
}
}
}
You could directly use qsort too here since the problem doesn't prohibit using standard functions, something like:
int qsortCompare(void const* a, void const* b) {
triangle const* trA = a;
triangle const* trB = b;
if(trA && trB) {
double areaA = area(trA);
double areaB = area(trB);
return (areaA < areaB) ? -1 :
((areaA > areaB)? 1: 0);
}
return 0;
}
void sort_by_area(triangle* tr, int n) {
qsort(tr, n, sizeof(triangle), &qsortCompare);
}
Also, don't be restricted to add functions in the problem solution. The actual driver code only calls sort_by_area() but you can write other functions in the solution and call them from sort_by_area().
The inner loop does not need to run till n, only till n-1
for (int j = 0; j < n - 1; j++)
Because when j == n, then you are comparing with random junk outside of your respective arrays by accessing size[j+1] and tr[j+1].
Also, when swapping, you don't need to copy the structure members one-by-one. You can simply do:
// Sort in tr array.
triangle tmp = tr[j];
tr[j] = tr[j + 1];
tr[j + 1] = tmp;
Edit: As #CiaPan pointed out:
You have a memory leak. You need to call free() after you are done with using the malloc'd memory.
You are not allocating the right amount of memory. If you are passed more than 100 triangles, your code might behave weirdly or randomly crash.
int *size = malloc(n* sizeof(*size));
Full code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct {
int a;
int b;
int c;
} triangle;
void sort_by_area(triangle *tr, int n) {
// Array for storing the perimeter.
int *size = malloc(n* sizeof(*size));
// Adding perimeters in size array.
for (int i = 0; i < n; i++) {
size[i] = tr[i].a + tr[i].b + tr[i].c;
}
// Sort.
for (int i = 0; i < n; i++) {
for (int j = 0; j < n - 1; j++) {
if (size[j] > size[j + 1]) {
// Sort in size array.
int temp = size[j];
size[j] = size[j + 1];
size[j + 1] = temp;
// Sort in tr array.
triangle tmp = tr[j];
tr[j] = tr[j + 1];
tr[j + 1] = tmp;
}
}
}
}
int main() {
int n;
scanf("%d", &n);
triangle *tr = malloc(n * sizeof(triangle));
for (int i = 0; i < n; i++) {
scanf("%d%d%d", &tr[i].a, &tr[i].b, &tr[i].c);
}
sort_by_area(tr, n);
for (int i = 0; i < n; i++) {
printf("%d %d %d\n", tr[i].a, tr[i].b, tr[i].c);
}
return 0;
}

Face detector program in C via arrays

So I need to make a "face detector" program in C. Basically I need to input the number of "face detections", resolution height and width (max 120), and the coordinates of the "face". Then the input is three h*w arrays which serve as RGB values.
The output of the program should be the same RGB values from the input, but with a green rectangle connecting the coordinates (thus highlighting the face on the picture), and the alpha values in the rectangle being 255 (the rest being alpha=127).
The issue I have is that the outputs are completely wrong. The first test case, which is a 5x5 black square with false coordinates, works fine. But the other test cases are actual pictures with 100x80 resolution. In those cases instead of a green rectangle, its random green lines and dots around the picture. The alpha value is simmilarly wrong, where its randomly 127 and randomly 255. I've tried rewriting my code several times, but the result is the same every time, just random values for alpha and G.
#include <stdio.h>
#define MAX 120
int main() {
FILE* fin = fopen("input.txt", "r");
FILE* fout = fopen("output.txt", "w");
int R[MAX][MAX], G[MAX][MAX], B[MAX][MAX], x1[MAX], y1[MAX], x2[MAX],
y2[MAX], A[MAX][MAX];
int h, w, n, i, j, k;
fscanf(fin, "%d %d %d", &n, &h, &w);
for (i = 0; i < n; i++) {
fscanf(fin, "%d %d %d %d", &x1[i], &y1[i], &x2[i], &y2[i]);
}
for (i = 0; i < w; i++) {
for (j = 0; j < h; j++) {
fscanf(fin, "%d ", &R[i][j]);
}
}
for (i = 0; i < w; i++) {
for (j = 0; j < h; j++) {
fscanf(fin, "%d ", &G[i][j]);
}
}
for (i = 0; i < w; i++) {
for (j = 0; j < h; j++) {
fscanf(fin, "%d ", &B[i][j]);
}
}
for (i = 0; i < w; i++) {
for (j = 0; j < h; j++) {
A[i][j] = 127;
}
}
for (k = 0; k < n; k++) {
for (i = x1[k]; i <= x2[k]; ++i) {
G[i][y1[k]] = 255;
G[i][y2[k]] = 255;
A[i][y1[k]] = 255;
A[i][y2[k]] = 255;
R[i][y1[k]] = 0;
R[i][y2[k]] = 0;
B[i][y1[k]] = 0;
B[i][y2[k]] = 0;
}
for (j = y1[k]; j <= y2[k]; ++j) {
G[x1[k]][j] = 255;
G[x2[k]][j] = 255;
A[x1[k]][j] = 255;
A[x2[k]][j] = 255;
R[x1[k]][j] = 0;
R[x2[k]][j] = 0;
B[x1[k]][j] = 0;
B[x2[k]][j] = 0;
}
}
for (k = 0; k < n; k++) {
for (i = x1[k] + 1; i <= x2[k] - 1; i++) {
for (j = y1[k] + 1; j <= y2[k] - 1; j++) {
A[i][j] = 255;
}
}
}
fprintf(fout, "/image %d %d RGBA\n", h, w);
for (i = 0; i < w; i++) {
for (j = 0; j < h; j++) {
fprintf(fout, "%d %d %d %d ", R[i][j], G[i][j], B[i][j], A[i][j]);
}
}
return 0;
}
I don't see anything wrong with the logic you have so I would step through your solution with testcases like yano suggested to see if you are having issues reading things in.
You do make the mistake of not setting the R and B values to 0 when you set the G value to 255 for the rectangle.
Next I would do two things: sanitize your inputs and simplify your loops.
For sanitizing your inputs just make sure that your with, height, and number of faces are less than your max. The coordinates you receive for each face rectangle should all be less than w and h, but greater than 0. Also double check that your face rectangles are always in the format of: [bottom-left x val, bottom-left y val, top-right x val, top-right y val] like you assume when you do all of these calculations. If there were an input problem here, that would be my guess at the most likely to cause hidden issues.
You can simplify your loops to avoid touching anything outside of your rectangles when coloring the Alpha and Green.
For the Green values, just loop over the sides. Loop through all of the faces (n) like you are doing, but just do:
for (i = x1[n]; i <= x2[n]; ++i) { G[i][y1[n]] = 255; G[i][y2[n]] = 255; // Also set A to 255 as well as R and B to 0 here }
for (j = y1[n]; j <= y2[n]; ++j) { G[x1[n]][j] = 255; G[x2[n]][j] = 255; // Also set A to 255 as well as R and B to 0 here }
And then cover the Alpha values inside the rectangle by looping from x1[n] + 1 to x2[n] - 1 and y1[n] + 1 to y2[n] - 1. This will not only make your program quicker, but should stop any erroneous green or alpha values to show up anywhere outside of your given points.
After fixing those things it should be much easier to debug and see where errors are when you get unexpected behavior.
Edit: I missed a case for input sanitation.

How to write a new image and zero pad reference image on that new image in C

I have an image of size MN, now I need to create a new image of size PQ where P=2M-1 and Q=2N-1
Here, f(x,y) is my reference image, and have to place as shown in the figure.
Here's my function of writing to new image
void WritePGM(FILE* fp)
{
int i, j;
int p, q;
p = 2*m-1;
q = 2*n-1;
fprintf(fp, "P5\n%d %d\n%d\n", p, q, 255);
for (j = 0; j<n; j++)
for (i = 0; i<m; i++) {
fputc(image1[m,n], fp);
}
fclose(fp);
}
Can you suggest me the way I should rewrite the loop? Thank you.
There are a few things wrong:
[m,n] isn't valid C code.
[m][n] is but this only writes the bottom right pixel to all output.
Your loops are doing a transpose (I think--most images are matrix[YDIM][XDIM]).
You can do this with one set of nested loops, but it's easier with two. Here is something close to what I think you want [I haven't tested it]. It assumes you want it output in video scan line order (i.e. j is the Y dimension and i is the X dimension):
void
WritePGM(FILE * fp)
{
int i;
int j;
int p;
int q;
p = 2 * m - 1;
q = 2 * n - 1;
fprintf(fp, "P5\n%d %d\n%d\n", p, q, 255);
j = 0;
// write top half of image
for (; j < n; j++) {
i = 0;
// output left half of scan line
for (; i < m; i++)
fputc(image1[j][i], fp);
// output right half of scan line (zeroes)
for (; i < p; i++)
fputc(0, fp);
}
// write bottom half of image (zeroes)
for (; j < q; j++) {
for (i = 0; i < p; i++)
fputc(0, fp);
}
fclose(fp);
}
While writing image1[j][i] it gives error: [Error] subscripted value is neither array nor pointer nor vector. image1 is defined globally as unsigned char *image1;
It's easy to change to a one dimensional array. Also, most video images (i.e. still images like .png, .jpg, etc.) use the y/x nomenclature, so I'm switching to that:
void
WritePGM(FILE * fp)
{
int xcur;
int ycur;
int xmax2;
int ymax2;
unsigned char *scanline;
xmax2 = 2 * xmax - 1;
ymax2 = 2 * ymax - 1;
fprintf(fp, "P5\n%d %d\n%d\n", xmax2, ymax2, 255);
ycur = 0;
// write top half of image
for (; ycur < ymax; ycur++) {
scanline = image1 + (ycur * xmax);
xcur = 0;
// output left half of scan line
for (; xcur < xmax; xcur++)
fputc(scanline[xcur], fp);
// output right half of scan line (zeroes)
for (; xcur < xmax2; xcur++)
fputc(0, fp);
}
// write bottom half of image (zeroes)
for (; ycur < ymax2; ycur++) {
for (i = 0; i < xmax2; xcur++)
fputc(0, fp);
}
fclose(fp);
}
The above should work. Here is the equivalent done a bit faster:
void
WritePGM(FILE * fp)
{
int ycur;
int xmax2;
int ymax2;
unsigned char *scanline;
xmax2 = 2 * xmax - 1;
ymax2 = 2 * ymax - 1;
fprintf(fp, "P5\n%d %d\n%d\n", xmax2, ymax2, 255);
unsigned char zeroline[xmax2];
memset(zeroline,0,sizeof(zeroline));
ycur = 0;
// write top half of image
for (; ycur < ymax; ycur++) {
scanline = image1 + (ycur * xmax);
// output left half of scan line
fwrite(scanline,1,xmax,fp);
// output right half of scan line (zeroes)
fwrite(zeroline,1,xmax2 - xmax,fp);
}
// write bottom half of image (zeroes)
for (; ycur < ymax2; ycur++)
fwrite(zeroline,1,xmax2,fp);
fclose(fp);
}

How to normalize a matrix in C?

How to normalize a matrix?
Suppose I have a 2x3 matrix:
1 2 3
4 5 6
The normalized matrix would be:
1/sqrt(pow(2,2) + pow(3,2)) 2/sqrt(pow(2,2) + pow(3,2)) 3/sqrt(pow(2,2) + pow(3,2))
4/sqrt(pow(5,2) + pow(6,2)) 5/sqrt(pow(5,2) + pow(6,2)) 6/sqrt(pow(5,2) + pow(6,2))
This is my sample code:
#include <stdio.h>
#include <conio.h>
#include <math.h>
int main(){
int rows, cols, rowCounter, colCounter, r, c;
int initial[100], inputMatrix[100][100], rowSum[100] = {0}, norm[100][100], square[100] = {0};
printf("Enter size of a matrix\n");
scanf("%d %d", &rows, &cols);
printf("Enter matrix of size %dX%d\n", rows, cols);
/* Input matrix */
for(rowCounter = 0; rowCounter < rows; rowCounter++){
for(colCounter = 0; colCounter < cols; colCounter++){
scanf("%d", &inputMatrix[rowCounter][colCounter]);
}
}
for(r = 0; r < rows; r++)
{
for(c = 1; c < cols; c++)
{
float a;
a == inputMatrix[r][c];
square[r] += pow(a, 2);
}
printf("%.2lf ", square[r]);
}
for(rowCounter = 0; rowCounter < rows; rowCounter++)
{
for(colCounter = 0; colCounter < cols; colCounter++)
{
norm[rowCounter][colCounter] == (inputMatrix[rowCounter][colCounter]) / sqrt(square[rowCounter]);
}
}
printf("\nNormalized Matrix:\n");
for(rowCounter = 0; rowCounter < rows; rowCounter++)
{
for(colCounter = 0; colCounter < cols; colCounter++)
{
printf("%.3lf ", norm[rowCounter][colCounter]);
}
printf("\n");
}
getch();
return 0;
}
Why are you using == here:
for(r = 0; r < rows; r++)
{
for(c = 1; c < cols; c++)
{
float a;
a == inputMatrix[r][c]; //look here
square[r] += pow(a, 2);
}
It should be:
for(r = 0; r < rows; r++)
{
for(c = 1; c < cols; c++)
{
float a;
a = inputMatrix[r][c];
square[r] += pow(a, 2);
}
The same here:
norm[rowCounter][colCounter] == (inputMatrix[rowCounter][colCounter]) / sqrt(square[rowCounter]);
It should be:
norm[rowCounter][colCounter] = (inputMatrix[rowCounter][colCounter]) / sqrt(square[rowCounter]);
And you should be careful here:
int initial[100], inputMatrix[100][100], rowSum[100] = {0}, norm[100][100], square[100] = {0};
Are you sure about use int for all of this declarations?
I think you should use double or float instead, at least in some of them.
There are some problems in your code, I'll try to address the most important ones.
Your norm matrix is a 2D array of int as inputMatrix, but you have to use an array of float or double to correctly store the result and to perform the right calculation. In C if both of the terms of a division are integers types an integer division (like: 3/2 = 1, not 1.5) is performed, which is not what you need.
Another mistake is to use == instead of = to perform an assignment. In C == is the 'equal to' relational operation.
EDIT
As #chux pointed out it would be wiser to choose a more accurate type for a and square[]. Using long long int will (may) prevent numeric overflow in case the elements of the matrix are too big for their square or the sum of them to be reprensented by an int.
Be aware that if you decide to use double instead there are other subtle numerical issues concernig the sum of small number (and the order in which it is performed) represented by floating point types. So, as a partial remedy, you can use long double (if it really has more precision then double in your environment) for a and square.
EDIT 2
In the question and in comment you say that the first element of each row of the matrix is supposed to be "constant in the matrix" so it doesn't take part to the sum of squares in your code and in the example you gave, but in both of them they are updated in the next loop. I'm not sure of what is going on, so I corrected my code to mimic the behavior of yours.
Here is a working corrected version of your code:
#include <stdio.h>
#include <math.h>
int main() {
int rows, cols, r, c;
// you may think about dynamical allocation here
int inputMatrix[100][100], rowSum[100] = {0};
// it's better to use a type that can manage bigger numbers to avoid numeric overflow
long long int a, square[100] = {0};
// your starting matrix can be a matrix of int but the normalized one need to
// contain floating point numbers
double norm[100][100], k;
printf("Enter size of a matrix\n");
scanf("%d %d", &rows, &cols);
printf("Enter matrix of size %dX%d\n", rows, cols);
/* Input matrix */
for ( r = 0; r < rows; r++) {
for (c = 0; c < cols; c++) {
scanf("%d", &inputMatrix[r][c]);
// ^^ if you are scanning integer numbers...
}
}
printf("\nrows: %d cols: %d elements:\n",rows,cols);
for( r = 0; r < rows; r++) {
for( c = 0; c < cols; c++) {
printf("%d ", inputMatrix[r][c]);
// ... ^^ you should print integer numbers
}
printf("\n");
}
for (r = 0; r < rows; r++) {
for (c = 1; c < cols; c++) {
// ^^^ I don't know why you skip this here
a = inputMatrix[r][c];
//^ You have to assign, not to compare!
square[r] += a * a;
// ^^^^^ no need to call pow()
}
printf("Sum of squares of row %d: %lld\n",r,square[r]);
// square contains int ^^
// It would be nice and safer if you check here if square == 0 to avoid a
// division by zero and probably detect bad input data
}
for ( r = 0; r < rows; r++ ) {
// It's far more efficient to precalculate this term, even if compilers
// could be smart enough to do it for you. You may want to store those
// values in an array of doubles instead of the (sum of) squares
k = 1.0 / sqrt(square[r]);
for( c = 0; c < cols; c++ ) {
norm[r][c] = k * inputMatrix[r][c] ;
// again, ^ assign not compare
}
}
// you can add the printf to the previous loop...
printf("\nNormalized Matrix:\n");
for( r = 0; r < rows; r++) {
for( c = 0; c < cols; c++) {
printf("%.3lf ", norm[r][c]);
// ^^^^^ norm contains double
}
printf("\n");
}
return 0;
}
I keep the input matrix of integer type, but it would be better to use double for that too. As i added a print loop for the original matrix, the final output is:
rows: 2 cols: 3 elements:
1 2 3
4 5 6
Sum of squares of row 0: 13
Sum of squares of row 1: 61
Normalized Matrix:
0.277 0.555 0.832
0.512 0.640 0.768

Program Bugs with large sequences (C) [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am trying to code the Waterman algorithm in C.
Now when the length of the sequence exceeds 35 the program just lags.
I have no idea where to start looking, tried but got nothing worked out.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Max Function Prototype.
int maxfunction(int, int);
// Prototype of the random Sequences generator Function.
void gen_random(char *, const int);
int main(int argc, char *argv[]) {
// Looping variable and Sequences.
int i = 0, j = 0, k = 0;
char *X, *Y;
int length1, length2;
// Time Variables.
time_t beginning_time, end_time;
// Getting lengths of sequences
printf("Please provide the length of the first Sequence\n");
scanf("%d", &length1);
printf("Please provide the length of the second Sequence\n");
scanf("%d", &length2);
X = (char*)malloc(sizeof(char) * length1);
Y = (char*)malloc(sizeof(char) * length2);
int m = length1 + 1;
int n = length2 + 1;
int L[m][n];
int backtracking[m + n];
gen_random(X, length1);
gen_random(Y, length2);
printf("First Sequence\n");
for (i = 0; i < length1; i++) {
printf("%c\n", X[i]);
}
printf("\nSecond Sequence\n");
for (i = 0; i < length2; i++) {
printf("%c\n", Y[i]);
}
// Time calculation beginning.
beginning_time = clock();
// Main Part--Core of the algorithm.
for (i = 0; i <= m; i++) {
for (j = 0; j <= n; j++) {
if (i == 0 || j == 0) {
L[i][j] = 0;
} else
if (X[i-1] == Y[j-1]) {
L[i][j] = L[i-1][j-1] + 1;
backtracking[i] = L[i-1][j-1];
} else {
L[i][j] = maxfunction(L[i-1][j], L[i][j-1]);
backtracking[i] = maxfunction(L[i-1][j], L[i][j-1]);
}
}
}
// End time calculation.
end_time = clock();
for (i = 0; i < m; i++) {
printf(" ( ");
for (j = 0; j < n; j++) {
printf("%d ", L[i][j]);
}
printf(")\n");
}
// Printing out the result of backtracking.
printf("\n");
for (k = 0; k < m; k++) {
printf("%d\n", backtracking[k]);
}
printf("Consumed time: %lf", (double)(end_time - beginning_time));
return 0;
}
// Max Function.
int maxfunction(int a, int b) {
if (a > b) {
return a;
} else {
return b;
}
}
// Random Sequence Generator Function.
void gen_random(char *s, const int len) {
int i = 0;
static const char alphanum[] = "ACGT";
for (i = 0; i < len; ++i) {
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
}
s[len] = 0;
}
Since you null terminate the sequence in gen_random with s[len] = 0;, you should allocate 1 more byte for each sequence:
X = malloc(sizeof(*X) * (length1 + 1));
Y = malloc(sizeof(*Y) * (length2 + 1));
But since you define variable length arrays for other variables, you might as well define these as:
char X[length1 + 1], Y[length2 + 1];
Yet something else is causing a crash on my laptop: your nested loops iterate from i = 0 to i <= m, and j = 0 to j <= n. That's one step too many, you index out of bounds into L.
Here is a corrected version:
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
The resulting code executes very quickly, its complexity is O(m*n) in both time and space, but m and n are reasonably small at 35. It runs in less than 50ms for 1000 x 1000.
Whether it implements Smith-Waterman's algorithm correctly is another question.

Resources