K&R 1-24

F

Frank

It's hard for me to really know when to start a new thread. I think,
in general, shorter threads promote better communication and less
arguing or mudslinging. The sixtieth to the eightieth messages will
tend to have the uncharitable exchanges.

I'm having trouble adapting the wiki soln to K&R 1-24 to my fledgling
indent program. The way I see it, I've got line defined in main and
in getline. My compiler disagrees:

F:\gfortran\dan>gcc bb10.c -Wall -o indent.exe
C:\DOCUME~1\dan\LOCALS~1\Temp/ccym7Q6M.o:bb10.c:(.text+0x35):
undefined referenc
e to `line'
C:\DOCUME~1\dan\LOCALS~1\Temp/ccym7Q6M.o:bb10.c:(.text+0x50):
undefined referenc
e to `line'
C:\DOCUME~1\dan\LOCALS~1\Temp/ccym7Q6M.o:bb10.c:(.text+0x62):
undefined referenc
e to `line'
collect2: ld returned 1 exit status

F:\gfortran\dan>type bb10.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>

#define MAXLINE 1000 /* max input line size */



int getline(FILE * p1)
{
int c, i;
extern char line[];

for ( i=0;i<MAXLINE-1 && ( c=fgetc(p1)) != EOF && c != '\n'; ++i)
line = c;
if(c == '\n')
{
line = c;
++i;
}
line = '\0';
return i;

}


int main(int argc, char *argv[])
{
int n;
FILE *fin, *fout;
char *path_exp, *exp_suffix = ".exp";
const char *path;
int c, nc;
char d;
int getline(FILE *);
int len=0;
int t=0;
int brace=0, bracket=0, parenthesis=0;
int s_quote=1, d_quote=1;
char line[MAXLINE]; /*current input line*/

path=argv[2];
if (argc != 3)
{
fprintf(stderr, "usage: \n");
fprintf(stderr, "%s <num> <filename>\n", argv[0]);
return EXIT_FAILURE;
}
errno = 0;
n = strtod(argv[1], NULL);
if (n < 0 || n > 999 )
{
fprintf(stderr, "%s: give me a natural number\
less than 1000\n", argv[0]);
return EXIT_FAILURE;
}
// if detab
if (n == 0)
{
fprintf(stderr, "this will detab your file\n");
fprintf(stderr, "If that's what you want, enter zero again\n");
fprintf(stderr, "To abort, enter anything else\n");
d = getchar();
if (d == '0')
fprintf(stderr, "detabbing %s \n", argv[2]);
else
{
fprintf(stderr, "Aborting");
return EXIT_FAILURE;
}
}
// Process path and open file
nc = strlen (path);
if (nc <= 0 || nc > 999)
{
fprintf(stderr, "%s: nc screwed up\n", argv[0]);
return EXIT_FAILURE;
}
c = strlen (exp_suffix);
path_exp = malloc(strlen(path) + strlen(exp_suffix) + 1);
if (!path_exp)
{
fprintf(stderr, "%s: %s\n", __func__, "malloc error");
return EXIT_FAILURE;
}
strcat(strcpy(path_exp, path), exp_suffix);
fin = fopen(path, "r");
if (!fin)
{
fprintf(stderr, "%s %s\n", "fopen failed to open", argv[2] );
fclose(fout);
return EXIT_FAILURE;
}
// main control
while ((len = getline(fin)) > 0 )
{
t=0;
while(t < len)
{
if( line[t] == '[')
{
brace++;
}
if( line[t] == ']')
{
brace--;
}
if( line[t] == '(')
{
parenthesis++;
}
if( line[t] == ')')
{
parenthesis--;
}
if( line[t] == '\'')
{
s_quote *= -1;
}
if( line[t] == '"')
{
d_quote *= -1;
}
t++;
}
}
if(d_quote !=1)
printf ("Mismatching double quote mark\n");
if(s_quote !=1)
printf ("Mismatching single quote mark\n");
if(parenthesis != 0)
printf ("Mismatching parenthesis\n");
if(brace != 0)
printf ("Mismatching brace mark\n");
if(bracket != 0)
printf ("Mismatching bracket mark\n");
if( bracket==0 && brace==0 && parenthesis==0 && s_quote == 1 &&
d_quote == 1)
printf ("Syntax appears to be correct.\n");



// print some values and exit
printf(" argv1 is %d\n" , n);
printf(" argv2 is %s\n" , path);

fout = fopen(path_exp, "w");
if (!fout)
{
fprintf(stderr, "%s \n", "fout failed");
return EXIT_FAILURE;
}
fclose(fin);
fclose(fout);
free(path_exp);
return EXIT_SUCCESS;
}

// gcc bb10.c -Wall -o indent.exe

F:\gfortran\dan>

My bigger concern here is that I don't see the logic here that would
decide whether these characters occured in quotes or comments. Does
someone else?
 
N

Nick Keighley

It's hard for me to really know when to start a new thread.  I think,
in general, shorter threads promote better communication

I disagree. Lots of thread fragments make it hard to follow things.
and less
arguing or mudslinging.  The sixtieth to the eightieth messages will
tend to have the uncharitable exchanges.

stick with the technical stuff ignore the mud slinging.

I'm having trouble adapting the wiki soln to K&R 1-24 to my fledgling
indent program.  The way I see it, I've got line defined in main and
in getline.  My compiler disagrees:

you're wrong the compiler is right (no surprise there!)
F:\gfortran\dan>gcc bb10.c -Wall -o indent.exe
C:\DOCUME~1\dan\LOCALS~1\Temp/ccym7Q6M.o:bb10.c:(.text+0x35):
undefined referenc
e to `line'
C:\DOCUME~1\dan\LOCALS~1\Temp/ccym7Q6M.o:bb10.c:(.text+0x50):
undefined referenc
e to `line'
C:\DOCUME~1\dan\LOCALS~1\Temp/ccym7Q6M.o:bb10.c:(.text+0x62):
undefined referenc
e to `line'
collect2: ld returned 1 exit status

F:\gfortran\dan>type bb10.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>

#define MAXLINE 1000 /* max input line size */

int getline(FILE * p1)
{
  int c, i;
  extern char line[];

this is a declaration not a definition. You areprobably trying
to make line a "global variable", that is accessible from multiple
functions. Declare it at the top of the program if you really
want to do that. Better would be to pass it as a parameter.
  for ( i=0;i<MAXLINE-1 && ( c=fgetc(p1)) != EOF && c != '\n'; ++i)
    line = c;
  if(c == '\n')
    {
      line = c;
      ++i;
    }
  line = '\0';
  return i;

}

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


yuk! Why so many variables? Your main() has way to many
variables. This is because it is too big. Create more functions.
  int n;
  FILE *fin, *fout;
  char *path_exp, *exp_suffix = ".exp";
  const char *path;
  int   c, nc;
  char d;
  int getline(FILE *);

bad style. If you want a function declaration then put it at the
top of the file. Or better miss it out altogether because the
function definition you did earlier also acts as a declaration.
  int len=0;
  int t=0;
  int brace=0, bracket=0, parenthesis=0;
  int s_quote=1, d_quote=1;
  char line[MAXLINE]; /*current input line*/

  path=argv[2];
  if (argc != 3)
  {
    fprintf(stderr, "usage: \n");
    fprintf(stderr, "%s <num> <filename>\n", argv[0]);
    return EXIT_FAILURE;
  }
  errno = 0;
  n = strtod(argv[1], NULL);
  if (n < 0 || n > 999 )
    {
      fprintf(stderr, "%s: give me a natural number\
 less than 1000\n", argv[0]);
      return EXIT_FAILURE;
    }
  // if detab
  if (n == 0)
    {
    fprintf(stderr, "this will detab your file\n");
    fprintf(stderr, "If that's what you want, enter zero again\n");
    fprintf(stderr, "To abort, enter anything else\n");
    d = getchar();
    if (d == '0')
      fprintf(stderr, "detabbing %s \n", argv[2]);
    else
      {
      fprintf(stderr, "Aborting");
      return EXIT_FAILURE;
      }
    }
  // Process path and open file
  nc = strlen (path);
  if (nc <= 0 || nc > 999)
  {
    fprintf(stderr, "%s: nc screwed up\n", argv[0]);
    return EXIT_FAILURE;
  }
  c = strlen (exp_suffix);
  path_exp = malloc(strlen(path) + strlen(exp_suffix) + 1);
  if (!path_exp)
  {
      fprintf(stderr, "%s: %s\n", __func__, "malloc error");
      return EXIT_FAILURE;
  }
  strcat(strcpy(path_exp, path), exp_suffix);
  fin = fopen(path, "r");
  if (!fin)
  {
    fprintf(stderr, "%s %s\n", "fopen failed to open", argv[2] );
    fclose(fout);
    return EXIT_FAILURE;
  }
  // main control
  while ((len = getline(fin)) > 0 )
  {
    t=0;
    while(t < len)
      {
        if( line[t] == '[')
          {
            brace++;
          }
          if( line[t] == ']')
            {
              brace--;
            }
          if( line[t] == '(')
            {
              parenthesis++;
            }
          if( line[t] == ')')
            {
              parenthesis--;
            }
          if( line[t] == '\'')
            {
              s_quote *= -1;
            }
          if( line[t] == '"')
            {
              d_quote *= -1;
            }

there's some attempt to handle double and single quotes here
          t++;
        }
    }
  if(d_quote !=1)
    printf ("Mismatching double quote mark\n");
  if(s_quote !=1)
    printf ("Mismatching single quote mark\n");
  if(parenthesis != 0)
    printf ("Mismatching parenthesis\n");
  if(brace != 0)
    printf ("Mismatching brace mark\n");
  if(bracket != 0)
    printf ("Mismatching bracket mark\n");
  if( bracket==0 && brace==0 && parenthesis==0 && s_quote == 1 &&
d_quote == 1)
        printf ("Syntax appears to be correct.\n");

  // print some values and exit
  printf(" argv1 is %d\n" , n);
  printf(" argv2 is %s\n" , path);

  fout = fopen(path_exp, "w");
  if (!fout)
  {
    fprintf(stderr, "%s \n", "fout failed");

why are you opening path_exp and then immediatly closing it?
    return EXIT_FAILURE;
  }
  fclose(fin);
  fclose(fout);
  free(path_exp);
  return EXIT_SUCCESS;

}

// gcc bb10.c -Wall -o indent.exe

F:\gfortran\dan>

My bigger concern here is that I don't see the logic here that would
decide whether these characters occured in quotes or comments.  Does
someone else?

at a glance I see no attempt to to detab the file. It checks for
mismatched
brackets and quotes. Did you copy the correct example
 
A

Andrew Smallshaw

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>

#define MAXLINE 1000 /* max input line size */



int getline(FILE * p1)
{
int c, i;
extern char line[];

That does not create a variable: it states that there is a variable
already in scope that we are going to use. The "line" in main() is
not in scope since it is local to another function. You need to
create that "line" outside of a function if you want to access the
variable from anywhere in your program.
while(t < len)
{
if( line[t] == '[')
{
brace++;
}
if( line[t] == ']')
{
brace--;
}
if( line[t] == '(')
{
parenthesis++;
}
if( line[t] == ')')
{
parenthesis--;
}
if( line[t] == '\'')
{
s_quote *= -1;
}
if( line[t] == '"')
{
d_quote *= -1;
}
t++;
}
}

Bad style: use a switch statement instead of all those ifs: it is
clearer and may result in more efficient code (with optimising
compilers nowadays it is generally awkward to say defintively what
is more efficient):

while(t < len)
switch(line[t++])
{
case '[': /* NB: "brace" usually refers to {}, not [] */
brace++;
break;
case ']':
brace--;
break;
case '(':
parenthesis++;
break;
case ')':
parenthesis--;
break;
case '\'':
s_quote *= -1;
break;
case '"':
d_quote *= -1;
break;
}
 
B

Barry Schwarz

You would be much better off if you got your first detab program
working rather than trying to start a whole new project while that one
still has serious problems.
 
N

Nobody

Bad style: use a switch statement instead of all those ifs: it is
clearer and may result in more efficient code (with optimising
compilers nowadays it is generally awkward to say defintively what
is more efficient):

while(t < len)
switch(line[t++])
{
case '[': /* NB: "brace" usually refers to {}, not [] */
brace++;
break;
case ']':
brace--;
break;

[snip]

If all (or nearly all) of the cases are that short, I'd use
one line per case:

switch(line[t++])
{
case '[': brace++; break;
case ']': brace--; break;
case '(': parenthesis++; break;
case ')': parenthesis--; break;
case '\'': s_quote *= -1; break;
case '"': d_quote *= -1; break;
}
 
F

Frank

Bad style: use a switch statement instead of all those ifs: it is
clearer and may result in more efficient code (with optimising
compilers nowadays it is generally awkward to say defintively what
is more efficient):
    while(t < len)
        switch(line[t++])
        {
        case '[':  /* NB: "brace" usually refers to {}, not [] */
            brace++;
            break;
        case ']':
            brace--;
            break;

[snip]

If all (or nearly all) of the cases are that short, I'd use
one line per case:

        switch(line[t++])
        {
        case '[':  brace++;            break;
        case ']':  brace--;            break;
        case '(':  parenthesis++;      break;
        case ')':  parenthesis--;      break;
        case '\'': s_quote *= -1;      break;
        case '"':  d_quote *= -1;      break;
        }

Thanks all for replies. The following purports to be a soln for 1-24
for contemporary C. I leaned heavily on the Tondo and Gimpel
material, which is some of the best money I ever spent at a second-
hand store.


F:\gfortran\dan>gcc gg3.c -Wall -o indent.exe

F:\gfortran\dan>indent
brace: -1 bracket: 0 paren: 0
F:\gfortran\dan>type gg3.c
#include <stdio.h>
#include <stdlib.h>

int brace, brack, paren;

void incomment89(void);
void search(int);
void incomment99(int);
void inquote(int);

int main(void)
{
FILE *fin;
char * name = "test1.txt";
int c;
extern int brace, brack, paren;

fin = fopen(name, "r");

while((c = fgetc(fin)) != EOF)
{
if (c == '/')
{
if ((c = fgetc(fin)) == '*')
incomment89();
else if (c == '/')
incomment99(c);
else
search(c);
}
else if (c == '\'' || c == '"')
inquote(c);
else
search(c);

}

fclose(fin);
printf (" brace: %d bracket: %d "
"paren: %d ", brace, brack, paren);

return EXIT_SUCCESS;
}

void search(int c)
{
extern int brace, brack, paren;

switch(c)
{
case '{': brace++; break;
case '}': brace--; break;
case '(': paren++; break;
case ')': paren--; break;
case '[': brack++; break;
case ']': brace--; break;
}
}

void incomment89()
{
int c, d;

c = getchar();
d = getchar();
while ( c != '*' || d != '/')
{
c = d;
d = getchar();
}
}

void incomment99(int c)
{
while (c != '\n')
{
c = getchar();
}
}

void inquote(int c)
{
int d;

while ((d=getchar()) != c)
if (d == '\\')
getchar();
}

// gcc gg3.c -Wall -o indent.exe

F:\gfortran\dan>

Did I get the logic for c99 comments correct?
 
F

Frank

int getline(FILE * p1)
{
  int c, i;
  extern char line[];

That does not create a variable: it states that there is a variable
already in scope that we are going to use.  The "line" in main() is
not in scope since it is local to another function.  You need to
create that "line" outside of a function if you want to access the
variable from anywhere in your program.
 
I think I understand.
 
F

Frank

 The following purports to be a soln for 1-24
for contemporary C.  

Or this:

F:\gfortran\dan>gcc gg4.c -Wall -o indent.exe

F:\gfortran\dan>indent
brace: -1 bracket: 0 paren: 0
F:\gfortran\dan>type gg4.c
#include <stdio.h>
#include <stdlib.h>

int brace, brack, paren;

void incomment89(FILE *);
void search(int);
void incomment99(int, FILE *);
void inquote(int, FILE *);

int main(void)
{
FILE *fin;
char * name = "test1.txt";
int c;
extern int brace, brack, paren;

fin = fopen(name, "r");

while((c = fgetc(fin)) != EOF)
{
if (c == '/')
{
if ((c = fgetc(fin)) == '*')
incomment89(fin);
else if (c == '/')
incomment99(c, fin);
else
search(c);
}
else if (c == '\'' || c == '"')
inquote(c, fin);
else
search(c);

}

fclose(fin);
printf (" brace: %d bracket: %d "
"paren: %d ", brace, brack, paren);

return EXIT_SUCCESS;
}

void search(int c)
{
extern int brace, brack, paren;

switch(c)
{
case '{': brace++; break;
case '}': brace--; break;
case '(': paren++; break;
case ')': paren--; break;
case '[': brack++; break;
case ']': brace--; break;
}
}

void incomment89(FILE * fin)
{
int c, d;

c = fgetc(fin);
d = fgetc(fin);
while ( c != '*' || d != '/')
{
c = d;
d = fgetc(fin);
}
}

void incomment99(int c, FILE * fin)
{
while (c != '\n')
{
c = fgetc(fin);
}
}

void inquote(int c, FILE * fin)
{
int d;

while ((d=fgetc(fin)) != c)
if (d == '\\')
fgetc(fin);
}

// gcc gg4.c -Wall -o indent.exe

F:\gfortran\dan>
 
F

Frank

 The following purports to be a soln for 1-24
for contemporary C.  

Or this:

F:\gfortran\dan>gcc gg4.c -Wall -o indent.exe

F:\gfortran\dan>indent
brace: -1 bracket: 0 paren: 0
F:\gfortran\dan>type gg4.c
#include <stdio.h>
#include <stdlib.h>

int brace, brack, paren;

void incomment89(FILE *);
void search(int);
void incomment99(int, FILE *);
void inquote(int, FILE *);

int main(void)
{
FILE *fin;
char * name = "test1.txt";
int c;
extern int brace, brack, paren;

fin = fopen(name, "r");

while((c = fgetc(fin)) != EOF)
{
if (c == '/')
{
if ((c = fgetc(fin)) == '*')
incomment89(fin);
else if (c == '/')
incomment99(c, fin);
else
search(c);
}
else if (c == '\'' || c == '"')
inquote(c, fin);
else
search(c);

}

fclose(fin);
printf (" brace: %d bracket: %d "
"paren: %d ", brace, brack, paren);

return EXIT_SUCCESS;
}

void search(int c)
{
extern int brace, brack, paren;

switch(c)
{
case '{': brace++; break;
case '}': brace--; break;
case '(': paren++; break;
case ')': paren--; break;
case '[': brack++; break;
case ']': brace--; break;
}
}

void incomment89(FILE * fin)
{
int c, d;

c = fgetc(fin);
d = fgetc(fin);
while ( c != '*' || d != '/')
{
c = d;
d = fgetc(fin);
}
}

void incomment99(int c, FILE * fin)
{
while (c != '\n')
{
c = fgetc(fin);
}
}

void inquote(int c, FILE * fin)
{
int d;

while ((d=fgetc(fin)) != c)
if (d == '\\')
fgetc(fin);
}

// gcc gg4.c -Wall -o indent.exe

F:\gfortran\dan>
 
F

Frank

"Frank" <[email protected]> ha scritto nel messaggio
 The following purports to be a soln for 1-24
for contemporary C.

here in Italy
the exercise 1-24 of K&R C is not about how write the code
for indent a C program right; but on write code for check
C sintax (e.g. on check pair {} [] () " " '')

the problem of write a program that indent a C program like
other would like to see, is one of the two i try to write
for some time but without any success

But you see how the two are related in identifying curly braces. I
also want to have this program for the syntax check.
 
J

Jorgen Grahn

....
I'm having trouble adapting the wiki soln to K&R 1-24 to my fledgling
indent program.

??? Context, please. I have no idea what you are talking about.

....
F:\gfortran\dan>gcc bb10.c -Wall -o indent.exe

One thing though: if you think the "-Wall" gcc invocation above turns
on "all" warnings, you are wrong. I recommend

-std=c99 -Wall -Wextra -pedantic

but as always read the manual and decide for yourself.

/Jorgen
 
F

Frank

"io_x" <[email protected]> ha scritto nel messaggio

int incomment89(FILE* fin)
{int  ch, ch1;
ch1='*';        //  *
ch=fgetc(fin);  //  /   /*/ in not a end comment
if(ch=='\\') {ch1=ch; ch=fgetc(fin);}

i forget
this should be "if(ch=='/') {ch1=ch; ch=fgetc(fin);}"

you claim to be pedandt
but i'm sure 80% of your code has assunction on what can
overflow or can not overflow that are wrong
wrong too seems the use of some standard functions
for example  use "int  i=strlen(s);"
or use isspace(s); (where "char  s[12]; ")
withot speak for scanf and prinf

so where all you are pedandt?

That makes them sound french. I'll see how what you posted behaves
and let you know. Are we vedarchi?
 
F

Frank

...


??? Context, please. I have no idea what you are talking about.

...


One thing though: if you think the "-Wall" gcc invocation above turns
on "all" warnings, you are wrong. I recommend

  -std=c99 -Wall -Wextra -pedantic

Thx, Jorgen. I vascillate among using gcc, gfortran, g95, and perl.
It takes a while before I get the warnings right.
but as always read the manual and decide for yourself.

Greg Lindahl wrote that "real programmers don't document." This may
be our collective and unfortunate tendency. The only connection I've
made with the people who do the documentation is Andy Vaught, the
Force of One behind g95.

Anyways, I think this implementations are under-documented. This
might be a sensitive criticism in particular to those who have made
personal contributions to these efforts.

For proof, I contend that it is sufficient to say that they have no
screenshots. This is a basic block in any corresponding documentation
that Intel or MS would put out. Yes they pay money to people to use
all the means a computer has to inform the user, and it's money well
spent.
 
S

Seebs

#this is wrong; extern can be used inside a function
#there is anyone out there read what i write??

I mostly don't bother, because it's too hard for me to figure out what
you mean most of the time.

-s
 
N

Nick Keighley

I mostly don't bother, because it's too hard for me to figure out what
you mean most of the time.

ditto. And I'm not sure it's all to do with english-is-not-your-first-
language.
You just seem confused a lot of the time
 
J

James Kuyper

Nick said:
ditto. And I'm not sure it's all to do with english-is-not-your-first-
language.
You just seem confused a lot of the time

The biggest problem is not that he's confused, it's that his writing is
confusing. As result, I'm not really sure whether he's confused, or
simply failing to communicate well, though I suspect both are true.
Either way, the problem is so severe that I've stopped bothering to try
to figure out what he means.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top