On 12 Apr 2004 18:43:17 -0700,
mattd@myrealbox.com (Matt DeFoor)
wrote:
[color=blue]
>Sorry about. As soon I posted I realized that I had left my custom
>printf function in as well as omitting a few others. Apologies. I have
>another apology to make as well. This program is meant to be compiled
>with Metrowerks CodeWarrior where it doesn't work properly (yet it
>compiles). However, I've since tested and compiled on my rusty, yet
>trusty, Linux box and it works there with a small modification by
>typecasting line 62 as an int.[/color]
While I believe you tested something, it was not this code. It
doesn't compile clean. Did you cut and paste or retype the code?
[color=blue]
>
>With that said, if anyone knows of a better/more efficient way to
>accomplish what I'm trying to do, that'd be great. Essentially, I'm
>trying to read the log file backwards and compare the first column
>which is a timestamp.
>
>Anyway, here it is. In all its horrid glory:
>
>#include <stdlib.h>
>#include <stdio.h>
>
>int backtonewline (FILE *fp) {
> char ch;
> long pos;
> int rc;
>
> rc=fseek(fp, -1L, 1);[/color]
-1 would work just as well as -1L. But how do you know that SEEK_CUR
is 1 on all the systems you compile it on?
[color=blue]
> if (rc==-1)[/color]
fseek can return any non-zero value on error. Are you sure each of
your systems returns -1?
[color=blue]
> return -1;
>
> while (1) {
> ch=fgetc(fp);[/color]
fgetc returns an int, not a char. You need that to check for errors.
[color=blue]
> if (ch=='\n')
> break;
> rc=fseek(fp,-2L,1);
> if (rc==-1)
> return -1;
> }
> fseek(fp,-1L,1);[/color]
This positions you 1 character before the '\n'.
[color=blue]
> return 0;
>}
>
>int back1line (FILE *fp) {
> if (backtonewline (fp) != 0) return -1;[/color]
If successful, this positions you one character before the '\n' before
the current line,
[color=blue]
> if (backtonewline (fp) != 0) return -1;[/color]
If successful, this positions you one character before the '\n' before
the previous line.
After processing line 2, this will fail because there is no '\n'
before line 1 and obviously no character before that.
[color=blue]
> fseek(fp,1L,1);[/color]
This positions you at the '\n' before the previous line.
[color=blue]
> return 0;
>}
>
>
>int main () {
> FILE *in;
> int rc,len,i;
> char buffer[100];
> char *cptrs[3];
> long pos;
>
> len=strlen(buffer);[/color]
You forgot to include string.h for strlen, memset, strchr, etc.
buffer is uninitialized. This invokes undefined behavior. I assume
this is out of sequence?
[color=blue]
> if ((buffer[len-1] == '\n')||(buffer[len-1] == '\r'))
> buffer[len-1] = '\0';
> in=fopen("log","rb");
> if (in!=NULL) {
> fseek(in,0,SEEK_END);
> back1line(in);[/color]
If your file ends with a '\n' this will work. I believe that is
implementation defined. If there is no '\n', then you will skip the
last line and start with the one before it.
[color=blue]
>
> while (1) {
> pos=ftell(in);
> fgets(buffer,100,in);[/color]
Since back1line left you pointed at the '\n', you will only read in
that one character.
[color=blue]
> buffer[strlen(buffer)-1]=0;[/color]
This assumes the line was less than 99 characters. Are you sure?
[color=blue]
>
> len=strlen(buffer);[/color]
Did you really want to call strlen twice?
[color=blue]
> if ((buffer[len-1] == '\n')||(buffer[len-1] == '\r'))[/color]
The only possible '\n' was at the end of the string, just before the
'\0', and you removed it two statements earlier.
[color=blue]
> buffer[len-1] = '\0';
> printf("line=%s\n", buffer);
> memset(cptrs,0,sizeof(cptrs));[/color]
All bits 0 is not necessarily a valid value for a pointer. Why do you
bother since you initialize each cptrs as needed?
Undefined behavior in C89 because memset is assumed to return an int
which is not true.
[color=blue]
> i=0;
> cptrs[i]=buffer;
> while (cptrs[i] && i<3) {
> ++i;
> (int *)cptrs[i]=strchr(cptrs[i-1],' '); /* typecast change to
>work on Linux */[/color]
More undefined behavior or it would be if it wasn't for the syntax
error.
Tell us this was meant as a joke. The result of a cast is not a
modifiable l-value and therefore may not appear as the destination of
an assignment operator. Why did your note in the beginning say cast
to int when here you cast to int*?
[color=blue]
> if (cptrs[i]==NULL) {
> printf("we break in here\n");
> break;
> }
> *cptrs[i]=0;
> ++cptrs[i];
> }
> printf("got 0 = <%d>\n",atoi(cptrs[0]));
> printf("got 1 = <%d>\n",atoi(cptrs[1]));
> printf("got 2 = <%d>\n",atoi(cptrs[2]));[/color]
If you break out of the previous while loop because cptrs[i] is NULL,
then at least one of these calls to printf invokes undefined behavior.
[color=blue]
> fseek(in,pos,0);[/color]
Is 0 guaranteed to be SEEK_SET?
[color=blue]
> if (back1line(in)!=0)
> rc=1;
> }
> }
> else
> rc=1;
> fclose(in);
>
>}[/color]
Please provide the real code.
<<Remove the del for email>>