okay, experts, i need help.

i can't seem to replace characters in a file, like i thought i would be able to:

here's an example code. i put print and error stuff in there to try and debug. everything seems to be working ... except that my filename is not modified.

any help greatly appreciated.

if ((fptr = fopen (filename, "ab+")) == NULL)
    {
        printf("File Open Error %s", filename);
        exit(0);
    }
    rewind (fptr);
    for (inx=1; inx<MTDF_HEAD_DURATION; inx++)   // looking for 10th line...
    {
        fgets (buf, 90, fptr);
        printf("%s (%p)\n",buf,fptr);
    }
    errno = 0;

    for (inx=0; inx<strlen(MTDF_Header.Duration); inx++)  // replace w/str "0001359"
    {
        result = putc (MTDF_Header.Duration[inx], fptr);
        printf("result: %d, errno: %d\n",result,errno);
    }
    fclose(fptr);

Recommended Answers

All 5 Replies

okay, experts, i need help.

:icon_eek:

I think the problem is the way you are opening the file.

a+
Open a file for reading and appending. All writing operations are performed at the end of the file, protecting the previous content to be overwritten. You can reposition (fseek, rewind) the internal pointer to anywhere in the file for reading, but writing operations will move it back to the end of file. The file is created if it does not exist.

okay... so i'm feeling stupid here :P

its not writing anything to the file, at all. either at the position i thought (hoped?) it would, or at the end of the file.

the return values from either putc( ) or fprintf( ) indicate success, theres no errno code ... but its not writing anything. the file stays unmodified.

i have write permissions to the file in question.

i must be missing something obvious.

i must be missing something obvious.

fo'shizzle my nizzle: for (inx=1 ... in my defense, i was originally opening it as "rb+", later on in frustration i tried "ab+" ... '

did i mention that i just worked 65 hours this week, through the weekend. is that a valid excuse?

:icon_redface:

A few tips:

>printf("File Open Error %s", filename);
>exit(0);
Most likely you don't want to use stdout for your error messages. At the very least use stderr, and for more robust messaging, use your own stream. Either way you'll be using fprintf. Also, 0 means success, so exit(0) is functionally identical to return 0 . For portability purposes you should be using EXIT_FAILURE. Ideally you would have something like this:

errno = 0;
fptr = fopen ( filename, mode );

if ( fptr == NULL ) {
  fprintf ( stderr, "Unable to open [%s]: '%s'\n",
    filename, strerror ( errno ) );
  exit ( EXIT_FAILURE );
}

Though I still tend to frown on hard termination for all but the most extreme of errors. You could easily get the user to enter an alternative filename.

>fgets (buf, 90, fptr);
Always check your input calls for success.

>printf("%s (%p)\n",buf,fptr);
The %p specifier expects a pointer to void. Just because fptr is a pointer doesn't mean it's the correct type. Avoid undefined behavior with a cast:

printf ( "%s (%p)\n", buf, (void*)fptr );

>for (inx=0; inx<strlen(MTDF_Header.Duration); inx++)
This effectively turns an O(N) loop into an O(N*M) loop. Unless MTDF_Header.Duration changes length in the body of the loop, don't use strlen in your condition. This also serves to make your lines shorter (a big help if you use wide indentation):

size_t len = strlen ( MTDF_Header.Duration );

for ( inx = 0; inx < len; inx++ )
errno = 0;

for (inx=0; inx<strlen(MTDF_Header.Duration); inx++)
{
  result = putc (MTDF_Header.Duration[inx], fptr);
  printf("result: %d, errno: %d\n",result,errno);

Okay, this one is subtle. Presumably you set errno to 0 because you want to error check putc, but a library function is allowed to set errno to a non-zero value even if there isn't an error. There's no guarantee that strlen won't set errno to something and give you a false positive in your result message.

The best practice for errno is to clear it immediately before calling the function you want to error check, and use it immediately after:

for (inx=0; inx<strlen(MTDF_Header.Duration); inx++)
{
  errno = 0;
  result = putc (MTDF_Header.Duration[inx], fptr);
  printf("result: %d, errno: %d\n",result,errno);
commented: i appreciate the time you took here. good advice :) +1

thanks narue. what i posted was throwaway code just to debug why it wasnt writing to my file.

i don't /ever/ use exit(0); in the production... I instead write a message to the GUI and set the GUI to a certain state -- all of which would not help readability here... I also take more care with type casting (not that I would normally use a reference to %p outside throwaway code, anyhow.)

as for your notes about being careful with setting the errno outside a library loop, and using size_t len -- I have to admit I can be a bit sloppy... those are good suggestions for me to remember, thanks!

:)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.