Yes, this is a well known problem. The last time I solved this is to use an array for each line and rendering each letter separately.
Firstly, I would represent each letter in an array. For example your A would be something like this:
char* letter[8];
letter[0] = " _/_/ ";
letter[1] = " _/ _/";
etc.
(Actually a 2D array would be used where each letter is at a different index.)
The actual render would be in an array as well, something along the lines of:
char* render[8];
and then use concatenation to build each line. A simply nested for loop should do the trick:
for each line, i to render (i.e the height of the letters)
for each letter, j
concatenate line i of letter j to the to char* i in the array
Finally loop though the array and print each line. Actually, you can skip the render array and simply print each line without a carriage return. Something like the following comes to mind:
for each line, i to render : // (i.e the height of the letters)
for each letter, j {
output line i of letter j
}
output a carriage return
}
(My C is a bit rusty, from there the "pseudo" code. However, I think my logic is sound.)
Answer from Jaco Van Niekerk on Stack OverflowYes, this is a well known problem. The last time I solved this is to use an array for each line and rendering each letter separately.
Firstly, I would represent each letter in an array. For example your A would be something like this:
char* letter[8];
letter[0] = " _/_/ ";
letter[1] = " _/ _/";
etc.
(Actually a 2D array would be used where each letter is at a different index.)
The actual render would be in an array as well, something along the lines of:
char* render[8];
and then use concatenation to build each line. A simply nested for loop should do the trick:
for each line, i to render (i.e the height of the letters)
for each letter, j
concatenate line i of letter j to the to char* i in the array
Finally loop though the array and print each line. Actually, you can skip the render array and simply print each line without a carriage return. Something like the following comes to mind:
for each line, i to render : // (i.e the height of the letters)
for each letter, j {
output line i of letter j
}
output a carriage return
}
(My C is a bit rusty, from there the "pseudo" code. However, I think my logic is sound.)
You can try something like the following:
NOTE: Obviously, the following lacks in a lot of things like memory de-allocation, error checking, incomplete code, etc. The idea is to give you a hint!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define ROW 4
#define COL 8
#define CHAR_INDEX_MAX 26
enum alph_enum {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z};
typedef struct _alphabets {
char *line[ROW];
}alphabet;
alphabet chars[26];
init_a(enum alph_enum letter)
{
int i;
for (i=0 ; i<ROW ; i++) {
chars[letter].line[i] = (char *) malloc(COL);
if (chars[letter].line[i] == NULL) {
printf("memory allocation failed \n");
return;
}
}
switch (letter) {
/*0123 4567*/
case H:
strcpy(chars[letter].line[0], "| |");
strcpy(chars[letter].line[1], "|_______|");
strcpy(chars[letter].line[2], "| |");
strcpy(chars[letter].line[3], "| |");
break;
case E:
strcpy(chars[letter].line[0], "|-------");
strcpy(chars[letter].line[1], "|_______");
strcpy(chars[letter].line[2], "| ");
strcpy(chars[letter].line[3], "|_______");
break;
case L:
strcpy(chars[letter].line[0], "| ");
strcpy(chars[letter].line[1], "| ");
strcpy(chars[letter].line[2], "| ");
strcpy(chars[letter].line[3], "|_______");
break;
/* for all the other alphabets */
}
return;
}
print_str(char word[])
{
int i, j;
printf("\n");
for (i=0; i<ROW; i++) {
for (j=0 ; j<strlen(word) ; j++) {
printf("%s", chars[word[j] % 'A'].line[i]);
}
printf("\n");
}
printf("\n");
return;
}
int main(void)
{
init_a(H);
init_a(E);
init_a(L);
/* print_str("HELLO"); */
print_str("HELL");
return 0;
/* free the memory for HEL here */
}
The output will be as follows:
> gcc test.c -o print
> print
| ||-------| |
|_______||_______| |
| || | |
| ||_______|_______|_______
>
TODO:
- You can include numbers, special characters (like !, @, #, $, etc), blank space, may be all ASCII chars makes sense.
- You can support bold, italics, underline and highlight for the characters
- You can support foreground and background colors
- You can support animation
Hope this helps!
library - ASCII art generator in C - Code Review Stack Exchange
Convert images to ASCII art
How do you work with ASCII art in C?
C Ascii Art | Overclockers UK Forums
Videos
fonts/Makefile
Each object depends only on the corresponding source. It means that header modifications wouldn't trigger recompilation. You may fix it by explicitly spelling out dependencies:
whimsy.o: whimsy.c whimsy.h core.hIn general it is a good habit to have dependencies auto generated: even in your not very complicated case it is easy to miss the
core.hdependency. Take a look at-Mfamily ofgccoptions.include/whimsy.h
Do not define objects (like
struct font whimsy) in the header file. You never know how many times the client would happen to#include "whimsy.h"in different places of their project. Better practice is to have the definition in the.cfile, and declare it in the header asextern struct font whimsy;DRY?
Unfortunately, you didn't show your font file. Also, I'm 95% sure the
initandprintfiles are identical modulo font name. If I'm correct, you need to unify them, and have the unified version incore.c.Allocation
Allocating glyphs dynamically and copying them from a static area looks like a waste for me (it would make sense should you read glyphs from the text file instead). I would have a
struct glyph { int width; char * appearance; };(strictly speaking,
glyph.widthis redundant: given a font height and appearance length you may calculate width at runtime); an array of glyphs as a part ofstruct font:struct font { .... struct glyph typeface[128]; .... }and a static initialization of each font like
static struct font whimsy = { .... .typeface = { .... ['a'] = (struct glyph) { .width = 10, .appearance = " " " " " " " d888b8b " "d8P' ?88 " "88b ,88b " "`?88P'`88b" " " " " " "; }, .... }, .... };Beware that such partial array initialization is a gcc extension.
More abstraction
Now you may take advantage of
appearancebeing default initialized to anNULL, and conclude that such glyph is not implemented. Anallowedmethod becomes a trivial test, and is easily abstracted out of the font specifics.
Try to format you code properly. Things like these are hard to read:
struct font{ unsigned int c; unsigned int *r; unsigned int d_n; int (*allowed)(int); int (*index)(int); int (*init)(void); int (*exit)(void); int (*print)(const char*); char ***d; };Hard to read code is more difficult to maintain and you're more likely to miss a bug.
Use braces consistently. Things like these just lead to trouble in the long run and don't make the code any easier to read.
for(int i=0;i<whimsy.d_n;i++) for(int j=0;j<whimsy.c;j++) free(whimsy.d[i][j]);Adding additional braces and formatting makes it very explicit what the scope of each loop is and adding additional statements you're less likely to accidentally forget to add a brace.
for (int i = 0; i < whimsy.d_n; i++) { for(int j = 0; j < whimsy.c; j++) { free(whimsy.d[i][j]); } }The use of defines for
font_allocandd_mallocare a pretty bad abuse of the pre-processor. You just use it as an automated copy-n-paste mechanism and copy-n-paste code is bad.#definehas it's uses but in this case it's the wrong choice.
Hello, I made this program as my first C project. I have some experience programming in Python.
https://github.com/JosefVesely/Image-to-ASCII
I'm looking for advice and criticism. :)
so i was given this assignment and i have to compress and expand ascii work with a code, and i have no clue on how to go on about this, google hasn't helped me much, so i'm just looking for tips on how to go ahead with this assignment.
i'm not sure how to explain this but from
',,,,,,]F 8,'
into
',,6*]F 48*8,'
i'm sorry if this doesn't make sense but i'm so confused lol, any articles or examples on how to work on this would be great
is there a way to use Ascii Faces like༼ つ ◕_◕ ༽ or ʕ•ᴥ•ʔ in a C code Program? I want to make a simple game that shows these, but the characters are not read properly.
Im just doing stuff like
Printf("ʕ•ᴥ•ʔ");
and i get this xD : ╩òÔÇóß┤ÑÔÇó╩ö
am i doing something wrong?