2

I have this function:

/*This func runs *.c1 file, and replace every include file with its content
It will save those changes to *.c2 file*/
void includes_extractor(FILE *c1_fp, char *c1_file_name ,int c1_file_str_len )
{
    int i=0;
    FILE *c2_fp , *header_fp;
    char ch, *c2_file_name,header_name[80]; /* we can assume line length 80 chars MAX*/
    char inc_name[]="include"; 
    char inc_chk[INCLUDE_LEN+1]; /*INCLUDE_LEN is defined | +1 for null*/

    /* making the c2 file name */

    c2_file_name=(char *) malloc ((c1_file_str_len)*sizeof(char));
    if (c2_file_name == NULL)
    {
     printf("Out of memory !\n");
     exit(0);
    } 

    strcpy(c2_file_name , c1_file_name); 
    c2_file_name[c1_file_str_len-1] = '\0'; 
    c2_file_name[c1_file_str_len-2] = '2';

/*Open source & destination files + ERR check */

    if( !(c1_fp = fopen (c1_file_name,"r") ) )
    {
     fprintf(stderr,"\ncannot open *.c1 file !\n");
     exit(0);
    }

    if( !(c2_fp = fopen (c2_file_name,"w+") ) )
    {
     fprintf(stderr,"\ncannot open *.c2 file !\n");
     exit(0);
    }

/*next code lines are copy char by char from c1 to c2,
  but if meet header file, copy its content */

    ch=fgetc(c1_fp);
    while (!feof(c1_fp))
    {
        i=0;    /*zero i */ 
        if (ch == '#') /*potential #include case*/
        {
             fgets(inc_chk, INCLUDE_LEN+1, c1_fp); /*8 places for "include" + null*/
         if(strcmp(inc_chk,inc_name)==0) /*case #include*/
         {
          ch=fgetc(c1_fp);
          while(ch==' ') /* stop when head with a '<' or '"' */
          {
           ch=fgetc(c1_fp);
          } /*while(2)*/

          ch=fgetc(c1_fp); /*start read header file name*/

          while((ch!='"') && (ch!='>')) /*until we get the end of header name*/
          {
           header_name[i] = ch;
           i++;
           ch=fgetc(c1_fp);
          }/*while(3)*/
          header_name[i]='\0';  /*close the header_name array*/


          if( !(header_fp = fopen (header_name,"r") ) ) /*open *.h for read + ERR chk*/
          {
               fprintf(stderr,"cannot open header file !\n");
           exit(0);
              }

          while (!feof(header_fp)) /*copy header file content to *.c2 file*/
          {
           ch=fgetc(header_fp);
           fputc(ch,c2_fp);
          }/*while(4)*/
          fclose(header_fp);
         }
                }/*frst if*/
        else
        {
         fputc(ch,c2_fp);
        }
     ch=fgetc(c1_fp);
    }/*while(1)*/ 

fclose(c1_fp);
fclose(c2_fp);
free (c2_file_name);    
}

This function reads a single *.c1 file and saves a copy of it to *.c2 file, but all the include files from *.c1 file are extracted and their contents expanded in *.c2.

After every include file that is extracted, I get 'ÿ' sign.

The include can contain 1 line or 1000 lines, but the 'ÿ' sign will appear only once after each include that is extracted.

Can't find why...

AShelly
  • 34,686
  • 15
  • 91
  • 152
Batman
  • 1,244
  • 2
  • 14
  • 26
  • 3
    Code Looks similar to this one.. http://stackoverflow.com/questions/4903812/cant-find-mistake-segmentation-fault-in-c – R K Feb 05 '11 at 10:36
  • 1
    Perhaps caused by a UTF-8 BOM interpreted as some other charset. Or you have some off-by-one in your pointer arithmetic. But your code is so ugly that I won't check that. – CodesInChaos Feb 05 '11 at 10:36
  • You should try to limit the code a bit. Also, after including so much code, you forgot to include bits that could be important, as the value of the defines. Code that you may want to prune: opening of the file, malloc (just mention that the pointer has so much memory malloc'ed as a comment), all code after reading the value for which you get unexpected results... – David Rodríguez - dribeas Feb 05 '11 at 10:44
  • As I recall, this is `0xFF` character. – ruslik Feb 05 '11 at 10:45
  • anyways plz dont post 10 questions with the same code and multiple problems because 1) the solutions may not be compatible with one another 2) its just trash :P – n00b Feb 05 '11 at 13:41
  • 1
    @n00b32, I would much rather see 10 focused questions with the same code sample than just one "please make my program work" question. – finnw Feb 05 '11 at 15:56

3 Answers3

12

"ÿ" corresponds to the code point 0xFF. fgetc returns EOF when the end of file is reached, which is (usually) defined as -1. Store -1 in a char and you'll wind up with 0xFF. You must check for EOF between calling fgetc and fpuc.

int ch;
...
/*copy header file content to *.c2 file*/
for (ch=fgetc(header_fp); ch > -1; ch=fgetc(header_fp)) {
   fputc(ch,c2_fp);
}

Instead of getting characters one at a time, you could use fgets to get a block of characters.

#ifndef BUFSIZE
#  define BUFSIZE 1024
#endif
char buf[BUFSIZE], *read;
...
/*copy header file content to *.c2 file*/
while ((read = fgets(buf, BUFSIZE, header_fp))) {
    fputs(buf, c2_fp);
}
outis
  • 75,655
  • 22
  • 151
  • 221
  • A better check would be to make `ch` an `int` and use `ch != EOF`. This will catch any other failed read as well. – CB Bailey Feb 05 '11 at 11:00
  • @Charles: I like that better. Was waffling on whether to use `ferror` or make `ch` an int. – outis Feb 05 '11 at 11:03
  • It is good BUT ! it gives me a space line between each content of header, while I need the headers to be written in sequence in *.c2 file... – Batman Feb 05 '11 at 11:46
  • @Mosh: That sounds like a problem with processing `c1_fp`, rather than with concatenating the included file, unless the included files have blank lines at their ends, in which case you need to buffer what you read from the file, discarding trailing newlines when you reach EOF. There are other issues with your code. For example, what happens if there's a "#" that's not followed by "include"? – outis Feb 05 '11 at 12:02
  • You also will find functions from [](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/ctype.h.html) (such as [`isspace`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/isspace.html)) and [](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/string.h.html) (such as [`strtok`](http://pubs.opengroup.org/onlinepubs/009695399/functions/strtok.html), [`strcspn`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/strcspn.html) and [`strchr`](http://pubs.opengroup.org/onlinepubs/009695399/functions/strchr.html)) useful. – outis Feb 05 '11 at 12:04
  • Your `fgets`/`fputs` solution is not binary-clean (it will corrupt files containing null bytes). It's possible to handle null bytes correctly with `fgets`, but rather difficult, so it would be much better to use `fread` and `fwrite`. – R.. GitHub STOP HELPING ICE Feb 05 '11 at 15:31
2

You major problem is this loop.

  while (!feof(header_fp)) /*copy header file content to *.c2 file*/
  {
   ch=fgetc(header_fp);
   fputc(ch,c2_fp);
  }/*while(4)*/

When fgetc encounters the end of file, it will return EOF, which is a negative integer. You store this in a char and then without checking write it out to the other file.

feof is very rarely useful as a loop condition. Most of the time it is better to check the return value of a read function.

You should always store to return value of fgetc in an int so that you can check the return value for errors (either an end-of-file condition or some other error). fputc takes in int, in any case.

A better way to construct the loop would be as follows.

int ch_hdr;
while((ch_hdr = fgetc(header_fp)) != EOF)
{
    fputc(ch_hdr, c2_fp);
}
CB Bailey
  • 755,051
  • 104
  • 632
  • 656
0

If you look at your code you have to places where you write to the target file.

If I were you I would set a break point at

        }/*frst if*/
        else
        {
        fputc(ch,c2_fp); // brk point here
        }

to check what you are actually writing there.

AndersK
  • 35,813
  • 6
  • 60
  • 86