0

I'm a newb at programming, especially at C; just trying to scratch an itch.

Trying to use ncurses to do an ASCII-art man doing jumping jacks, trying for the past three days, but I'm just not getting "Strings" in C (I understand that strings aren't really a C concept, just arrays of chars), and I'm not really getting pointers, and I'm not really getting pointers to char arrays, etc.

Forgive the art; it's just a proof of concept.

And I'm not trying to do the animation (or even use ncurses) at this point (that part's easy); I'm just trying to figure out how to use arrays to store my animation frames (though I'm open to other ideas of doing it, if they are conceptually simpler).

#define NumOfFrames      4  // Num of animation frames
#define WidthOfFrames   15  // Characters per animation line
#define FrameHeight  5  // Frame is this many lines tall.

const char *D51[NumOfFrames][FrameHight][WidthOfFrames] = {{
    " \\ 0 /  ",
    "  \\|/   ",
    "   |     ",
    "  / \\   ",
    "_/   \\_ "
},
{
    "         ",
    " __0__   ",
    "/  |  \\  ",
    "  / \\   ",
    " _\\ /_  "
},
{
    "         ",
    "   o     ",
    " /\\ /\\ ",
    " |/ \\|  ",
    " _\\ /_  "
},
{
    "         ",
    "         ",
    "   __  ",
    "  /_\\\\0_  ",
    " _\\\\/_  \\_"
}};

void main(int argc, char *argv[]) {

    FILE *f = fopen("log.txt","w");
    if (f == NULL) {
    printf("Error opening file!\n");
    exit(1);
    }

    // Try to print each frame to a text file to wrap
    // my brain around how this works.
    for (int x=0;x<NumOfFrames;x++) {
        for (int y=0;y<FrameHeight;y++) {
            for (int z=0;z<WidthOfFrames;z++) {
                fprintf(f, "%c", D51[x][y][z]);
            }
            fprintf(f,"\n");
        }
    }

    fclose(f);
}

In this code I'm just trying to figure out how to manipulate the strings, writing the images to a text file. Once I understand the concepts, I'll convert it to ncurses "graphical" format; that part is easy, and is not reflected in this sample code.

My problem is that no matter what permutations I try in my experiments -- a * here and not there, or there and here, or there but not here, or two indexes instead of three, or this or that -- I can't figure out what's going on under the hood. I can find examples on the web of what I need if I'm using integers, but using chars/strings/pointers adds a whole 'nuther level of complexity that I'm just not getting. Any help in better understanding the concepts I need would be much appreciated.

  • You don't need the 3rd array dimension. – Mark Benningfield Apr 19 '19 at 05:07
  • Thank you, Mark. I started out without it, thinking I didn't need it, but after two days of failure, I thought I'd try it. But hearing from someone more knowledgeable than I, that I don't need it, narrows the possibilities, and helps a great deal. Thanks! – Debian_Fanatic Apr 19 '19 at 05:11
  • Arrays are already pointers in some respect. So char arr[N][O][P] should work pretty well, you don't need asterisk here. – purec Apr 19 '19 at 05:30
  • I think this answer could help get you moving: https://stackoverflow.com/a/1095006/8060691 – ejohnso49 Apr 19 '19 at 05:31
  • ejohnso49, yes, I've run across that page several times in the past three days. – Debian_Fanatic Apr 19 '19 at 05:41
  • Mark Benningfield gave me a big push in the right direction. I've modded my code, and it now appears to work. The new version has this: ``` const char *D51[NumOfFrames][FrameHeight] = {{ . . . for (int x=0;x – Debian_Fanatic Apr 19 '19 at 05:44
  • Well, I can't seem to produce clean code in these comments. It seems that my basic understanding of arrays, chars, pointers, strings is close to correct; I just couldn't get all my ducks in a row, I reckon, so I thought my understanding must be incorrect. I think I'm on my way, though. – Debian_Fanatic Apr 19 '19 at 06:00
  • I still can't understand why don't use const char D51[NumOfFrames][FrameHeight][WidthOfFrames] = .... if you have predefined number of frames, strings and characters in a single string? Pure pointer is something that you have to bother about malloc'ing and free'ing; arrays are much simpler to use. – purec Apr 19 '19 at 06:56
  • purec, the reason I don't do X is because I still don't truly comprehend the under-the-hood nature of C arrays/pointers/strings. I'm getting closer, but it's like trying to speak French after two lessons when all you've known all your life is English. – DebianFanatic Apr 22 '19 at 12:46

1 Answers1

0

What i thought was having each figure in an array of char pointers

const char *D51 [FrameHeight] = {
" \\ 0 /  ",
"  \\|/   ",
"   |     ",
"  / \\   ",
"_/   \\_ "
};

followed by other figures *D52, *D53, *D54. Then we would have a pointer to pointer which would hold the adresses of these figures such as

const char **ptr [NumOfFrames];
*ptr = D51;
*(ptr+1) = D52
..

now that we have the adresses for every single character assigned to **ptr whether directly or indirectly we can go ahead and work on printing the figures. For example this will give us the first figure

for (int i=0; i<5; i++)
printf("%s\n", *(*(ptr)+i));

and to make *(*(ptr)+i) more clear lets break it down **ptr is a pointer to pointer and therefore *ptr will hold an address of a pointer, the reason why there are brackets around *(ptr) is because we want to choose the figure we need, if we want the first figure we call *ptr and if we want the second figure to display we simply call *(ptr+1) and so on.

The +i allows us to specify which line of a figure to call, for example if we want to call the first line we can leave i to be 0 but if we want to call the bottom line of a figure we need i to be 4. Just like *(ptr)+4.

Now that we specified both the figure number and the line number all we have to do is to dereference the pointer by adding the * operator. *(*(ptr)+i)

example code i have written:

..
..

const char *D54 [FrameHeight] = {
"         ",
"         ",
"   __  ",
"  /_\\\\0_  ",
" _\\\\/_  \\_"
};

const char **ptr [NumOfFrames];


int main(){
*ptr = D51;
*(ptr+1) = D52;
*(ptr+2) = D53;
*(ptr+3) = D54;

for(int j=0; j<4; j++)
{
  for (int i=0; i<5; i++)
    printf("%s\n", *(*(ptr+j)+i));
puts (" "); //this is nothing more than a newline character
}
return 0;
}

output:

 \ 0 /
  \|/
   |
  / \
_/   \_


 __0__
/  |  \
  / \
 _\ /_


   o
 /\ /\
 |/ \|
 _\ /_



   __
  /_\\0_
 _\\/_  \_