Solved

arrays of pointers to pointers

Posted on 1997-05-07
1
450 Views
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: ");
      gets(file_name);
      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);
      j++;
   }
   /* if (last line does not end with newline) */
   if (s[strlen(string)-1] != 10) j++;
   MaxLineNumber=j;
   fclose(inputf);
}

void EnterText(void)
{
   int refreshCounter;
   int Topline;

   Topline = 1;
   ScrChanged=TRUE;
   ESCpressed=FALSE;

   while (!ESCpressed)
   {
      if (ScrChanged) /*update display*/
      {
         clrscr();

         if (PageSize > MaxLineNumber)               /*just one page*/
            refreshCounter=MaxLineNumber;
         else
         if (MaxLineNumber-PageSize < Topline)       /*last page*/
            refreshCounter=MaxLineNumber;
         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*/
                  ScrChanged=TRUE;
                  if (MaxLineNumber<PageSize)
                     Topline = 1;
                  else
                     if ( (Topline+(2*PageSize)-1) < MaxLineNumber )
                        Topline = Topline+PageSize-1;
                     else
                        Topline = MaxLineNumber-PageSize+1;
               break;

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

int main(void)
{
   LoadTheFile();
   EnterText();
   return 0;
}
0
Comment
Question by:swright243
1 Comment
 
LVL 3

Accepted Solution

by:
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;
...ETCETERA...

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;
Usage:
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]);
free(arrayOfStrings);



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
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
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.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.

708 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

16 Experts available now in Live!

Get 1:1 Help Now