Thread: Accessing files.

  1. #1
    Novice.
    Join Date
    Oct 2005
    Posts
    88

    Accessing files.

    I've got the following code:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    FILE * fptr;
    int main()
    {
     char letter;
     int i;
     fptr = fopen("C:\\abc.txt", "r+");
     printf("Enter: ");
     scanf("% d", &i);
     fseek(fptr, (i-1), SEEK_SET);
     fputc('*', fptr);
     fseek(fptr, 0, SEEK_SET);
     printf("The file looks like this: \n");
     for (i = 0; i < 26; i++)
         {
          letter = fgetc(fptr);
          printf("The next letter is %c\n",letter);
         }
     fclose(fptr);
     getchar();
     getchar();
     getchar();
    
      return 0;
    }
    The thing is that I I'd like to replace a letter, only the asterisk is placed somewhere completely different. Could anyone explain on how to make it work?

    Thanks.

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Are you counting correctly, as in counting newline as two characters?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    FILE * fptr;
    should be local inside main

    char letter;
    should be int letter because fgetc returns int

    "&#37; d"

    should ne "%d"
    Code:
    for (i = 0; i < 26; i++)
         {
          letter = fgetc(fptr);
          printf("The next letter is %c\n",letter);
         }
    loop should look like
    Code:
    while((letter = fgetc(fptr)) != EOF)
    {
          printf("The next letter is %c\n",(unsigned char)letter);
    }
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  4. #4
    Novice.
    Join Date
    Oct 2005
    Posts
    88
    Well the file I use to modify looks like this:
    ABCDEFGHIJKLMNOPQRSTUVWXYZ


    Code:
    fseek(fptr, (i-1), SEEK_SET);
    Will move the 'cursor' i bytes

    So to check how much space 1 character takes up I tried:
    Code:
    #include <stdio.h>
    
    int main()
    {
      char b = 'A';
      printf(" &#37;d", sizeof(b));
      getchar();
      return 0;
    }
    The output was 1 . So to move the 'cursor' 1 character I would have to enter 1 I thought. It doesn't work though.

  5. #5
    Novice.
    Join Date
    Oct 2005
    Posts
    88
    Vart would you mind explaining please?

  6. #6
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by omnificient View Post
    Well the file I use to modify looks like this:
    ABCDEFGHIJKLMNOPQRSTUVWXYZ


    So to check how much space 1 character takes up I tried:

    The output was 1 . So to move the 'cursor' 1 character I would have to enter 1 I thought. It doesn't work though.
    problem is not the size - the scanf

    sizeof (char ) is always 1

    and it is how much space the char takes in memory, not in file
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  7. #7
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by omnificient View Post
    Vart would you mind explaining please?
    Which of 4 items?
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  8. #8
    Novice.
    Join Date
    Oct 2005
    Posts
    88
    All except the one about "&#37; d", that was a typo.

  9. #9
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Well, you measured incorrectly. Here's what a part of the man page says about fseek:
    Code:
    SYNOPSIS
           #include<stdio.h>
    
           int fseek(FILE*stream,long offset,int whence);
    [ ... ]
    DESCRIPTION
           The  fseek  function  sets  the  file position indicator for the stream
           pointed to by stream.  The new position, measured in bytes, is obtained
           by  adding offset bytes to the position specified by whence.  If whence
           is set to SEEK_SET, SEEK_CUR, or SEEK_END, the offset  is  relative  to
           the  start of the file, the current position indicator, or end-of-file,
           respectively.
    An int is only used to represent a character in most I/O functions because of the possibility that it must return EOF as a status. EOF is defined by the standard to be a negative number. Nothing in the same standard says that it fits in a character, which can be implemented as signed or unsigned by default according to the compiler. Most compilers I worked with utilized signed char anyway, so maybe EOF could be represented in a character. But it is not good practice at all to rely on the compiler's implementation details.

    So fix your offset, and you should be ok.

    But I think a whole lot easier method would be to just read the file, and replace the asterisk, then write it back to the file. You're already working at "I/O speed" so I don't think hacking at the interface to peek at the file is going to give you much of a performance boost. Any marginal benefit comes at the cost of you not really understanding how you solved the problem.

  10. #10
    Novice.
    Join Date
    Oct 2005
    Posts
    88
    I'm sorry but I think your answer is a bit too complicated for me. What is wrong with my offset exactly?

  11. #11
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by omnificient View Post
    All except the one about "% d", that was a typo.
    Then show the real code - by using copy/paste

    1. FILE* pointer is used only in main - so it should be declared local to this function. You should avoid globals - they complicate maintanence of the code in big projects, so good habbit is to make all variables as local as possible declaring them in the smallest possible scope.

    2. getc returns int 0-255 values are for byte read from file and -1 (EOF0 is used to indicate end-of-file event
    so in general usage of this function should be
    Code:
    int letter;
    letter = fgetc(fp);
    if(letter != EOF)
    {
       unsigned char readLetter = (unsigned char)letter;
       /* use readLetter */
    }
    3. as a result the loop that reads all the file contents using this function should look like in the sample I have shown. You could read more in FAQ
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Can you post your current code?

    Also, perhaps you could post the result of your program, and the inputs you used to get there?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  13. #13
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    BTW:
    Code:
    fseek(fptr, 0, SEEK_SET);
    That's the same as
    Code:
    rewind(fptr);
    Code:
     getchar();
     getchar();
     getchar();
    The more, the merrier!

    Why not just use something like this?
    Code:
    while(getchar() != '\n');
    2. getc returns int 0-255 values are for byte read from file and -1 (EOF0 is used to indicate end-of-file event
    so in general usage of this function should be
    Code:
    int letter;
    letter = fgetc(fp);
    if(letter != EOF)
    {
       unsigned char readLetter = (unsigned char)letter;
       /* use readLetter */
    }
    Not necessarily. Most of the time, you can probably just read the letter as an int and keep it as an int. (chars are automatically promoted to ints when they're passed to varargs functions like printf() anyway, and with prototyped functions the compiler should be able to handle things.)

    Anyway -- it's strange that your code isn't working, because this overwrites the '5' correctly for me.
    Code:
    #include <stdio.h>
    
    #define FILENAME "overwrite.txt"
    
    int main() {
        int c;
        FILE *fp = fopen(FILENAME, "w");
        fputs("1234567890", fp);
        fclose(fp);
        
        fp = fopen(FILENAME, "r+");
        fseek(fp, 5-1, SEEK_SET);  /* overwrite the '5' */
        putc('*', fp);
        rewind(fp);
        
        while((c = getc(fp)) != EOF) putchar(c);
        
        getchar();
        return 0;
    }
    The only thing that I can think of is that rewind() flushes the file and fseek() does not -- because you need to flush the file (such as with fflush()) as you switch between reading and writing.

    Again, though, I agree with citizen -- why not just read in a line, change that, and re-create the file? It's probably more efficient, actually -- less file manipulation.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  14. #14
    Novice.
    Join Date
    Oct 2005
    Posts
    88
    Well I'm not really trying to program something useful, I'm just going through a book, an trying to figure out how things work. So I just want to learn how to use what's in the book rather than fix things another way.
    I'm still using the original code:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    FILE * fptr;
    int main()
    {
     char letter;
     int i;
     fptr = fopen("C:\\abc.txt", "r+");
     printf("Enter: ");
     scanf("% d", &i);
     fseek(fptr, (i-1), SEEK_SET);
     fputc('*', fptr);
     fseek(fptr, 0, SEEK_SET);
     printf("The file looks like this: \n");
     for (i = 0; i < 26; i++)
         {
          letter = fgetc(fptr);
          printf("The next letter is %c\n",letter);
         }
     fclose(fptr);
     getchar();
     getchar();
     getchar();
    
      return 0;
    }
    I compiled the program, ran it and I entered 4. the d should have been changed into *, but it prints out * much later it turns out. Have a look at abc.txt.
    Attachment 7895

  15. #15
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    you still have &#37; d as a format
    and still missing fflush between write/read operations
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Program Deployment and DLL/OCX Files?
    By dfghjk in forum C++ Programming
    Replies: 5
    Last Post: 06-16-2008, 02:47 AM
  2. Storing and accessing data from and to .txt files.
    By Glauber in forum C++ Programming
    Replies: 9
    Last Post: 05-27-2008, 02:59 PM
  3. Multiple Cpp Files
    By w4ck0z in forum C++ Programming
    Replies: 5
    Last Post: 11-14-2005, 02:41 PM
  4. Folding@Home Cboard team?
    By jverkoey in forum A Brief History of Cprogramming.com
    Replies: 398
    Last Post: 10-11-2005, 08:44 AM
  5. Batch file programming
    By year2038bug in forum Tech Board
    Replies: 10
    Last Post: 09-05-2005, 03:30 PM