arrays of pointers to pointers

Posted on 1997-05-07
Last Modified: 2010-04-15
I am a Pascal programmer learning C. To help me I am converting
programs I have written to C. My editor uses an array of
pointers to strings to make it possible to edit text files
larger than 64K. I can do it in Pascal, but I am having
trouble figuring out how to make an array of pointers to
strings. Here's the code so far, it compiles, but will not
load files more than a two or three lines long.

//LED project conversion from Turbo Pascal
//May 7, 1997 Stephen E. Wright, PhD
//This version is a only text file viewer for large files
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

const MaxCharPerLine=1024;       /*max string length*/
const MaxLines=16000;            /*max number of lines*/
const PageSize=25;               /*PC screen height in lines*/

FILE *inputf;                    /*file to read*/
char file_name[79];              /*name of file to read*/
char string[MaxCharPerLine];     /*define a string*/
char *s = string;                /*pointer to a string*/
typedef char** str;              /*pointer to a pointer to a char*/
typedef str tLines[MaxLines];    /*define an array of above*/
tLines *t;

int keystroke, arrowkey;         /*used to identify keys pressed*/
unsigned int i, j, k;            /*counters*/
unsigned int MaxLineNumber;      /*number of lines read */

enum boolean {FALSE, TRUE};      /*simulate Pascal "boolean"*/
boolean ESCpressed, ScrChanged;  /*flags*/

void LoadTheFile(void)
   /*open a text file for reading*/
   do {
      puts("File: ");
      if ((inputf = fopen(file_name, "rt") ) == NULL )
       printf("Error in file name : '%s'\n", file_name);
   } while (inputf==NULL);

   /*get memory for array of pointers to strings*/
   t = (tLines*) malloc(MaxLines * sizeof(*s));
   for (i=0; i<MaxLines; i++, *t[i]=NULL);

   /*read file and copy lines to memory */
   j = 0;
   while (!feof(inputf))
      fgets(s, MaxCharPerLine, inputf);
      *t[j] = (char**) malloc(strlen(s)+1);
      strcpy(**t[j], s);
   /* if (last line does not end with newline) */
   if (s[strlen(string)-1] != 10) j++;

void EnterText(void)
   int refreshCounter;
   int Topline;

   Topline = 1;

   while (!ESCpressed)
      if (ScrChanged) /*update display*/

         if (PageSize > MaxLineNumber)               /*just one page*/
         if (MaxLineNumber-PageSize < Topline)       /*last page*/
         else refreshCounter=Topline+PageSize-1;     /*all other pages*/

         /*note that screen coords out of sync with array coords*/
         for ( j=Topline-1; j<refreshCounter-1; j++)
            strcpy(s, **t[j]);
            printf("%s", s);

      keystroke=getch();                       /*get a keystroke*/
      if (keystroke == 0) arrowkey = getch();  /*extended key pressed*/

      switch (keystroke)
         case 27: ESCpressed=TRUE; break; /*ESC pressed*/
         case 0:
            switch (arrowkey)
               case 81:                  /*PgDn*/
                  if (MaxLineNumber<PageSize)
                     Topline = 1;
                     if ( (Topline+(2*PageSize)-1) < MaxLineNumber )
                        Topline = Topline+PageSize-1;
                        Topline = MaxLineNumber-PageSize+1;

               case 73:                  /*PgUp*/
                  if (Topline-PageSize < 1)
            } /*switch arrowkey*/
         break; /*case 0: */
         default: break;  /*do nothing with any other key pressed*/
      } /*switch keystroke*/
   } /*while !EndofFile */

int main(void)
   return 0;
Question by:swright243
1 Comment

Accepted Solution

LucHoltkamp earned 300 total points
ID: 1250290
Youre code is a mess! While browsing I noticed several errors. I strongly advice you to buy a GOOD book. The best I've ever read is "The C Programming Language" by Kernighan and Ritchie
I will give some pointer examples here:
int a;     // an int
int *b;    // a pointer to int
int c[3];  // an array of int's
int **d;   // a pointer to a pointer of int;
int *e[2]; // an array of int pointers

b = c;   // Yes c is in fact an pointer to int.
a = *b;  // assign the thing wich points to to a
b = &a;  // assign the adress of a (a pointer) to b
b = (int*)malloc(3*sizeof(int)); // create a array of int dynamically
d = e;   // Yes e is in fact an pointer to a pointer to int
b = *d;  // Right... (*d) is a pointer to int (just as b)
b = *e;  // Again, in fact b is now the first element of the array e
b = e[0]; // Exacly the same as b = *e;

Let me give you an example of how it should be done:
First: a character string is a array of chars, so it's type is: char *
Second: a array of strings is {a array of (strings)} is a {array (of arrays of char)} is {a array of (char *)} is {(char *)* }

So a array of strings should be:
char **arrayOfStrings;
char **arrayOfStrings;
// first lets allocate space for the array of strings
arrayOfStrings = (char **)malloc(NOLINES * sizeof(char *));
// initialize array
for (int i = 0; i < NOLINES; i++) arrayOfString[i] = NULL;

// second lets read in every line
char buffer[256];
while (fgets(buffer, 255, in))
  // strdup allocates space for the string AND copies the buffer
  // into it.
  arrayOfStrings[i] = strdup(buffer);

// Do what you have to with the arrayOfStrings

// cleanup
for (int i = 0; i < NOLINES; i++)
  if (arrayOfStrings[i] != NULL) free(arrayOfStrings[i]);

Now lets look at the most SEVERE errors in you code
First the declaration nightmare:

typedef char** str; /*pointer to a pointer to a char*/
typedef str tLines[MaxLines]; /*define an array of above*/
tLines *t;

Ok so str is a char ** (an array of char* = array of strings)
What's tLines ?? it's an array of str, wich is an array of char ** so it's an char ***. And t is  a pointer to such a thing. So its in fact a char **** (could be: an array of an array of an array of array of chars (What a file browser THIS is gonna be, a superdimensional one! ;) )
The bottomline is: don't use typedefs on these simple structures, it makes things more complicated, especially if you're a beginner.

Second: your allocation:

/*get memory for array of pointers to strings*/
t = (tLines*) malloc(MaxLines * sizeof(*s));

In fact you have to use malloc like this:
Type *t = (Type*) malloc(N *sizeof(Type));

But you use sizeof(*s), and (*s) is not of type tLines but of char !! In fact you allocate MaxLines bytes, but you should allocate MaxLines*4 bytes (MaxLines pointers). This is certainly gonna crash.
Also is the tLines not a type for an array of strings, but I explained that before.

// AAAAAAAAARGHHHH what's this:
*t[j] = (char**) malloc(strlen(s)+1);
strcpy(**t[j], s); // <- Crashhhhh :(

first you allocate space strlen(s)+1 bytes. You cast this to char** So in fact you using your space for pointers to char*
(youre making an array of char*). But the type you cast to an the sizecalculation in malloc are out of sinc. It should always be:
(Type*)malloc(no * sizeof(Type)). I guess you fiddled with your program until the compiler stopped complaining ;)

Well I hope I helped you a little, but I strongly advice you to buy Kernighan an Ritchie (believe me it's the best) before trying to code any further.

Good Luck, Luc

Featured Post

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
mixing C++ and C code elegantly 10 156
C simple state machine for client server handshake 4 298
Problem to save 10 163
c++ getting the first 10 characters of a char* string 11 93
An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use for-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.

816 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now