Thanks, that was a relief... I thought that I was in trouble for a moment there. It is good to know where I stand. I'll work on it. Thanks, Mr. SRU.
Thanks, that was a relief... I thought that I was in trouble for a moment there. It is good to know where I stand. I'll work on it. Thanks, Mr. SRU.
Yes, Salem, indeed, you are correct.
I was rushing and I neglected to test my algorithm.
Oh well, we live and learn, and over this weekend I did as you requested/suggested.
Here is the partially completed algorithm.
I have tested it and it works.
As you said, the key point is to keep on breaking it down and testing it.
Here:
Now, -I have to get someone to show me how to put these characters (a-to-p) into an array.Code:#include <stdio.h> #include <stdlib.h> void printSpiral(int rows, int cols, char image[rows][cols]) { for (int c = 0 ; c < cols ; c++ ) { printf("%c\n", image[0][c] ); } //Works across ways left to right for (int r = 1; r < rows; r++ ) { printf("%c\n", image[r][4] ); }//Works downwards top to bottom for (int c = cols-1; c > 0 ; c-- ) {// printf("%c\n", image[4][c-1] ); }//Works across ways right to left for (int r = rows-2 ; r >=1; r-- ) { printf("%c\n", image[r][0] ); }//Works upwards bottom to top*/ } int main ( ) { int c, r, cols=5, rows=5; char image[5][5] = { { 'a', 'b', 'c', 'd', 'e' }, { 'p', 'q', 'r', 's', 'f' }, { 'o', 'x', 'y', 't', 'g' }, { 'n', 'w', 'v', 'u', 'h' }, { 'm', 'l', 'k', 'j', 'i' }, }; printSpiral(rows, cols, image); }
Then the next part of the task is to make one full completion of a spiral, and I think that we should work on both these things.
I will get back to you in due course, thanks,
Mr. SRU.
Just swap out the printf statement for a callback eg:
And Salem, what is your deal, you on a power trip or something? Stop deleting my posts for no apparent reason, if there IS a tangible reason at least highlight it in a PM so I can see it myselfCode:typedef (*print_pixel_cb)( unsigned int pixel ); void printSpiral( unsigned int *img, int rows, int cols, print_pixel_cb print ) { ... for (int c = 0 ; c < cols ; c++ ) print( (image + (cols * y))[c] ); ... }
Last edited by awsdert; 10-02-2022 at 12:07 AM.
> printf("%c\n", image[r][4] );
> printf("%c\n", image[4][c-1] );
In generalised code, you only have expressions involving rows and cols.
If you pass in a different sized image, this isn't going to work just by using 4.
1. Storing in an array
You need the following snippets.
Wherever you print, you do thisCode:void printSpiral(int rows, int cols, char image[rows][cols], char *result)
Then a main like so.Code:*result++ = image[0][c]; // substitute what you print
I changed the dimensions to be #defines so that we can do arithmetic on the sizes and still have valid code.
2. Completing the spiral.Code:int main ( ) { #define rows 5 #define cols 5 char image[rows][cols] = { { 'a', 'b', 'c', 'd', 'e' }, { 'p', 'q', 'r', 's', 'f' }, { 'o', 'x', 'y', 't', 'g' }, { 'n', 'w', 'v', 'u', 'h' }, { 'm', 'l', 'k', 'j', 'i' }, }; char result[(rows*cols)+1] = { 0 }; // +1 because we treat it as a string printSpiral(rows, cols, image, result); printf("%s\n", result ); }
Imagine your grid as looking like this.
On the first pass, you want all the 1's.Code:{ '1', '1', '1', '1', '1' }, { '1', '2', '2', '2', '1' }, { '1', '2', '3', '2', '1' }, { '1', '2', '2', '2', '1' }, { '1', '1', '1', '1', '1' },
On the second pass, you want all the 2's.
On the third pass, you want all the 3's.
Notice how the start position lies on a diagonal.
1's start at 0,0
2's start at 1,1
3's start at 2,2
Also notice there is a pattern to how many elements there are on the respective ring, based on the starting position. There's two less for each step in towards the centre.
Now consider a function with a prototype of
And a main that doesCode:void printSpiral(int rows, int cols, char image[rows][cols], int startx, int starty)
Can you get a-p then q-x ?Code:int main ( ) { int c, r, cols=5, rows=5; char image[5][5] = { { 'a', 'b', 'c', 'd', 'e' }, { 'p', 'q', 'r', 's', 'f' }, { 'o', 'x', 'y', 't', 'g' }, { 'n', 'w', 'v', 'u', 'h' }, { 'm', 'l', 'k', 'j', 'i' }, }; printSpiral(rows, cols, image, 0, 0); printSpiral(rows, cols, image, 1, 1);
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
If at first you don't succeed, try writing your phone number on the exam paper.
@awdert, stop posting your overly complicated drivel!
WFT - callbacks - sheesh.
Read the posts, ursellsarn has barely got past hello world in terms of skill.
Help the poster, not show off how 'smart' you are.
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
If at first you don't succeed, try writing your phone number on the exam paper.
What's overly complicated about a callback? I'm sure they've already encountered typedefs before, I just showed them another usage of it, as for trying to "show off", that wasn't my aim, rarely is and when it is it's usually in a dedicated thread and caught & brought back to reality by peops who've spotted the bugs I haven't.
If the ursellsarn is still here, I want to show them light at the end of the tunnel.
There is a really simple file format "Portable Pixel Map" (a.k.a "PPM") that is a great way to do simple image manipulation programs like what you want to do. See Netpbm - Wikipedia.
PPM files are well supported on Linux, however if you are on Windows you can use online viewers like Online NetPBM Viewer to view the output, and may need a tool to convert your input image into a PPM file - on Linux you can use the "jpegtoppm" command line program.
Have a read through that Wikipedia page on that image format, to get a grasp on what we are about to do, then come back here.
Here's a C program to generate a very simple 512x512 image file (called "output.ppm").
As written, this code isn't directly useful for your project - it generates each pixel one by one - so they are not held in memory so you can reorder them.Code:///////////////////////////////////////////////// // Program to generate the simplest 512x512 image ///////////////////////////////////////////////// #include <stdio.h> int main(int argc, char *argv[]) { FILE *f; // The size of the image int width = 512; int height = 512; f = fopen("output.ppm","w"); if(f == NULL) { fprintf(stderr, "Failed to open output.ppm for writing\n"); return EXIT_FAILURE; } // Output the file header fprintf(f,"P6\n"); // The file type - P6 is a PPM file with binary RGB data fprintf(f,"%i %i\n", width, height); fprintf(f,"255\n"); // The maximum pixel value // Output the pixel data for(int y = 0; y < height; y++) { // For each line in the image for(int x = 0; x < width; x++) { // For each column in the image // Make up some pixel colour values int red = x; // A red fade horizontally int green = x+y; // A green diagonal fade int blue = y; // A blue fade vertically // Output the pixel Red/Green/Blue values putc(red, f); putc(green, f); putc(blue, f); } } fclose(f); return EXIT_SUCCESS; }
So here's an improved version., where a structure called "Image" can hold all the pixels for an image (up to 1024x1024) and has a separate function to write the image out to a PPM file:
Have a look at that, and work through what it is doing. Play with it a bit changing the image size and the colours.Code://////////////////////////////////////////////////// // Program to generate an image //////////////////////////////////////////////////// #include <stdio.h> #include <stdlib.h> ////////////////////////////////////////////////////// // The maximum size images this program will work with ////////////////////////////////////////////////////// #define MAX_IMAGE_HEIGHT 1024 #define MAX_IMAGE_WIDTH 1024 ///////////////////////////////////////////////////// // Structures used in this program to hold the image ///////////////////////////////////////////////////// // A structure to hold a pixel's colour values struct Pixel { unsigned char red; unsigned char green; unsigned char blue; }; // A structure to hold the image size and pixels; struct Image { int width; int height; struct Pixel pixels[MAX_IMAGE_HEIGHT][MAX_IMAGE_WIDTH]; }; //////////////////////////////////////////////////////// // Function prototypes //////////////////////////////////////////////////////// // 'Prototype' for the image write function. int image_write(struct Image *image, char *file_name); /////////////////////////////////////////////////////////////// // main(): Generate a 400x300 image and then write it to a file /////////////////////////////////////////////////////////////// int main(int argc, char *argv[]) { // Set aside space for our image on the stack // Not the best idea, but it will work! struct Image image; // Set the width and height of the image image.width = 400; image.height = 300; // Fill the image's pizels for(int y = 0; y < image.height; y++) { // For each line in the image for(int x = 0; x < image.width; x++) { // For each column in the image image.pixels[y][x].red = x; // A red fade horizontally image.pixels[y][x].green = x+y; // A green diagonal fade image.pixels[y][x].blue = y; // A blue fade vertically } } // Write the image out to a file if(image_write(&image,"output.ppm")) return EXIT_SUCCESS; else return EXIT_FAILURE; } //////////////////////////////////////////////////////// // A function to write an image to a PPM file //////////////////////////////////////////////////////// int image_write(struct Image *image, char *file_name) { FILE *f; f = fopen(file_name,"w"); if(f == NULL) { fprintf(stderr, "Failed to open output.ppm for writing\n"); return 0; // logical false = failed to write image } // Output the file header fprintf(f,"P6\n"); // The file type - P6 is a PPM file with binary RGB data fprintf(f,"%i %i\n", image->width, image->height); fprintf(f,"255\n"); // The maximum pixel value // Output the pixel data for(int y = 0; y < image->height; y++) { // For each line in the image for(int x = 0; x < image->width; x++) { // For each column in the image // Output the pixel Red/Green/Blue values putc(image->pixels[y][x].red, f); putc(image->pixels[y][x].green, f); putc(image->pixels[y][x].blue, f); } } fclose(f); return 1; // Success! } //////// END OF PROGRAM //////////
You should then be able to see a clear path for how you can progress your program:
- You will need to add a function to read in an image (from a PPM file) into an "Image" structure. This might be harder than you think.
- Then a function to build a new image, using data from the image you have just read in. Maybe start small with flipping or rotating the image.
- The you will need to write the manipulated image out - exactly the way the code above does.
Hopefully that offers some insight into what you need to do, and the level of complexity you will be working at.
Mr. SRU says:
I have been giving this some thought about what Salem said, and, and yes, indeed, it is a case of the spiral array printing from:
11111
12221
12321
12221
11111
...to give:
1111111111111111222222223.
I played around with the code and I managed, (after quite a few tries), (using Code:Blocks), -to get:
I have tested the code, and yes, it works...Code:#include <stdio.h> #include <stdlib.h> int c, r, cols=5, rows=5; int top=0, bottom=5, left=0, int right=5, llimiter=0, rlimiter=0, blimiter=0, int tlimiter=0; int llimiter_2=0, rlimiter_2=0, blimiter_2=0, tlimiter_2=0, llimiter_3=0, rlimiter_3=0, blimiter_3, tlimiter_3=0; char image[5][5] = { { 'a', 'b', 'c', 'd', 'e' }, { 'p', 'q', 'r', 's', 'f' }, { 'o', 'x', 'y', 't', 'g' }, { 'n', 'w', 'v', 'u', 'h' }, { 'm', 'l', 'k', 'j', 'i' }, }; void printSpiral(int rows, int cols, char image[rows][cols]) { while(left<right && top<bottom) { for (int c = 0 + llimiter_3 ; c < (cols - rlimiter); c++ ) { printf("%c\n", image[(0 + tlimiter_2)][c] ); } //Works across ways left to right right--; rlimiter++; tlimiter_2++; llimiter_3++; for (int r = (1+tlimiter_3); r < (rows - blimiter); r++ ) { printf("%c\n", image[r][4 - rlimiter_2] ); }//Works downwards top to bottom bottom--; blimiter++; rlimiter_2++; tlimiter_3++; for (int c = (cols-2-rlimiter_3); c > llimiter ; c-- ) {// printf("%c\n", image[(4 - blimiter_2)][c] ); }//Works across ways right to left left++; llimiter++; blimiter_2++; rlimiter_3++; for (int r = rows-1-blimiter_3; r >=(1 + tlimiter); r-- ) { printf("%c\n", image[r][(0+llimiter_2)] ); }//Works upwards bottom to top*/ top++; tlimiter++; llimiter_2++; blimiter_3++; } } int main ( ) { printSpiral(rows, cols, image); return 0; }
Now, what is needed, is for someone to tell me EXACTLY how to print these characters to a 1 by 25 array (1X25), (-essentially a row type array).
I mean, I know how to print from an array's cells, but to print from "one 2D array to another 1D array", is there a special way to do this?
Surely it would it just be a matter of stating:
image[r][c]=image_2[1][r_2]?
I am unsure how to instruct the computer to do this...
Obviously we are going to have to declare the array (image_2), but we should use the print function, (perhaps?) to print the row-array image_2.
So, -we may have to modify the code, and here, I take the first for loop of the main printSpiral function, to give:
I need to print out the matrix's cells to a row, rather than a column, and, of course, I will need to declare a new variable for this (r_2).Code:for (int c = 0 + llimiter_3 ; c < (cols - rlimiter); c++ ) { image[(0 + tlimiter_2)][c]=image_2[1][r_2]; printf("%c\n", image_2[1][(r_2]); } //Works across ways left to right right--; rlimiter++; tlimiter_2++; llimiter_3++; r_2++//This must be placed within all for loops.
It will be good practice for me, as I need all the practice that i can get.
At a later stage we need to apply row array print to a style of a zig-zag to print to a matrix.
Thanks,
Mr. S R U.
These should all be local variables inside the function.Code:int c, r, cols=5, rows=5; int top=0, bottom=5, left=0, int right=5, llimiter=0, rlimiter=0, blimiter=0, int tlimiter=0; int llimiter_2=0, rlimiter_2=0, blimiter_2=0, tlimiter_2=0, llimiter_3=0, rlimiter_3=0, blimiter_3, tlimiter_3=0;
> printf("%c\n", image[r][4 - rlimiter_2] );
...
> printf("%c\n", image[(4 - blimiter_2)][c] );
As I said in post #19, using 4 here limits you to only a 5x5 image.
You need to use only expressions derived from the input parameters of rows and cols.
> Now, what is needed, is for someone to tell me EXACTLY how to print these characters to a 1 by 25 array (1X25), (-essentially a row type array).
Again, in post #19, read
"1. Storing in an array"
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
If at first you don't succeed, try writing your phone number on the exam paper.
Well you can just expand your function like this:
and just set the contents directly, using cap as the limit to stop printing, you can call it like this:Code:printSpiral( int rows, int cols, char img[rows][cols], char *dst, int cap ) { ... }
Code:int main() { #define rows 5 #define cols 5 int x, y, sep; char img[rows][cols] = { ... }; char dst[rows][cols] = {{0}}; printSpiral( rows, cols, img, &(dst[0][0]), rows * cols ); /* Confirmation print */ for ( x = 0; x < rows; ++x ) { sep = 0; for ( y = 0; y < cols; ++y ) { printf("%c%c", sep, dst[x][y] ); sep = ' '; } putchar('\n'); } }