Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

File operations using <stdio.h>

Status
Not open for further replies.

Malachi

Programmer
Aug 13, 2001
38
US
I want to create a function that opens a text file containing a list of filenames and verifies that each filename in the text file exists in the current working directory. The text file will contain one filename per line. I have been using some of the standard functions found in the <stdio.h> header to create a pointer to the text file and then used fgets(char *, int, FILE * ) to get the string. However, when I try a simple test to verify the existence of the file it fails. Here is the code I have so far.


#include <stdio.h>
#include <stdlib.h>

#define MAXLINE 10

void main(){

FILE *file;
char line[MAXLINE];


file = fopen( &quot;test.txt&quot;, &quot;rb&quot; );

while( fgets( line, MAXLINE, file ) != NULL )
{

if( fopen( line, &quot;rb&quot; ))
{
printf( &quot;Yahoo, %s exists! \n&quot;, line);
}
else
{
printf( &quot;Problem reading file %s \n&quot;, line );
}

}

fclose( file );
}
Any suggestions or help would be appreciated.

Thanks, in advance.

Malachi
 
I noticed that you don't check if your file pointer is NULL before using it. Also, why not put in some debugging print statements to help you know exactly where the program is failing. Hope this helps.

file = fopen( &quot;test.txt&quot;, &quot;rb&quot; );

if (file != NULL)
{
while( fgets( line, MAXLINE, file ) != NULL )
{
}
}
 
I've made some changes to the program. I call fopen() twice. The first time is to open a text file that contains a list of filenames. The second call to fopen passes the fetched string to the function. I'm doing this to test fopen()'s return value. I beleive that if the return is NULL, then the file doesn't exist.

The logical failure occurs when I try to test the existence (???) of the file path returned by calling fopen() the second time, passing the fetched string to it. The return from fopen() is always NULL, even when I know the file exists. I then test whether the response is NULL, and then print a message indicating the response. Finally I use 'fgets()' to get each newline terminated string from the file.

The input file contains a list of file names that SHOULD exist in the current working directory. For example:

DATA
LOGS
SomeDir\MANUALS
SomeDir\MODS

I haven't had any problems opening the input file and reading the contents. I've used strlen() to test the length of each string found in the input. The funny thing is the string length is one character greater than I expect to see. This may be caused by counting the newline character. Here is the source code.

/* fileopen - opens and reads a file to then determine if the filenames in the data file exist in the
current directory. */

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


void main(){

char filename[] = &quot;vdelist.ver&quot;;
FILE *pdatafile;
FILE *pnewfile;
char *line;
const char *filepath;

pdatafile = fopen( filename, &quot;r&quot; );

if( pdatafile == NULL )
{
printf( &quot;ERROR: Error Opening File %s \n&quot;, filename );
exit(1);
}
else
{
if( fgets( line, FILENAME_MAX, pdatafile ) != NULL )
{
printf( &quot;%s%d \n&quot;, line, strlen(line) );
}
else
{
printf( &quot;ERROR: Error Reading File %s \n&quot;, pdatafile );
}

pnewfile = fopen( line, &quot;r&quot; );

if( pnewfile == NULL )
{
printf( &quot;Cannot test the File %s \n&quot;, pnewfile );

}
else
{
printf( &quot;File Exists! \n&quot; );
fclose( pnewfile );
}

fclose( pdatafile );
}
}

*******************************************
Might the newline character passed in one of the arguments to fopen() cause a problem? I can't find any documentation indicating it would. What function or syntax should I use to truncate the character pointer before passing it to fopen() if that is indeed the problem?

Thanks in advance,

Malachi
 
If you want to strip the newline character, do this just before you do the fopen():

line[strlen(line) - 1] = '\0';

This will strip the last character of the string.
 
Thanks, stripping the newline character from the filename worked. Now, I'm getting an application error whenever the program exits. I'm using Windows 2000 Professional and the error is a

Windows - Application Error: The instruction at &quot;0x77f8ddc3&quot; referenced memory at &quot;0x00000004&quot;. the memory could not be &quot;read&quot;. Click on OK to terminate the program.

Here is the code:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


void main(){
	
	char filename[] = &quot;test.txt&quot;;		/* filename list file */
	FILE *fh_Datafile;				  	/* pointer to filename (filehandle) list file */
	FILE *fh_Newfile;					/* filehandle for files used during testing */
	char *p_Line;						/* pointer to individual lines in filename list */

	printf( &quot;Opening filename list file \n&quot; );
	fh_Datafile = fopen( filename, &quot;r&quot; );

	if( fh_Datafile == NULL )
	{
		printf( &quot;ERROR: Error Opening File %s \n&quot;, filename );
		exit(1); /* Error Occurs here */
	}
	else
	{
		if( fgets( p_Line, FILENAME_MAX, fh_Datafile ) != NULL )
		{
			printf( &quot;%s%d \n&quot;, p_Line, strlen(p_Line) );
		}
		else
		{
			printf( &quot;ERROR: Error Reading File %s \n&quot;, fh_Datafile );
		}
	}

	p_Line[strlen(p_Line)-1]='\0';			/* kill the newline character */

	fh_Newfile = fopen( p_Line, &quot;r&quot; );		/* attempt to open the filename for reading */
	
	if( fh_Newfile == NULL )				/* if un-successful, then produce an error */
	{
		printf( &quot;%s \n&quot;, &quot;Error Opening File&quot; );
	}
	else
	{
		printf( &quot;File %s Exists! \n&quot;, p_Line );	 /* Otherwise, print a message */
		fclose( fh_Newfile );
	}
	fflush( fh_Datafile );
	fclose( fh_Datafile );
	exit(0);    /* Error always occurs here if the rest of the program execution was successful */

}

Any suggestions? The error occurs whether or not I fflush() the file pointer, or use exit(0) or exit(1) to exit the application.
 
The main() does not require a return value. I've tried return(0), but receive a compiler complaint that void main() does not need a return value. I've also changed the void main() to int main( void ). Then, added the return(0) to the last statement, but it caused the same error. Thanks for the suggestion programsecrets :)

I believe the error is caused by how I'm manipulating the filehandle pointer references. I might not be releasing memory properly before exiting, but I don't know what else to do. As I read my program it seems pretty straight forward. Any help is appreciated.
 
How you are handling the file pointers looks correct. You are also not allocating any memory, so you shouldn't have to release any memory.

This may not be the problem, but be aware that there is a difference between exit() and return(). The exit() function &quot;terminates the calling process&quot;, while return() &quot;terminates the execution of a function and returns control to the calling function&quot;.

Therefore, the return value from exit() is passed to the parent process of the calling routine (like the grandparent), whereas the return value from return() is returned to the calling routine.

I wish I could help you with that Win2K message though.
 
Good news. I didn't see it at first, but you've got to allocate a buffer to accept the line you're reading in. All you've got is a pointer there:
Code:
    /* pointer to individual lines in filename list */
    char *p_Line;

    /* more code... */

    if( fgets( p_Line, FILENAME_MAX, fh_Datafile ) != NULL )
    {
    }
Do something like this instead:
Code:
    /* buffer for individual lines in filename list */
    char sLine[512];

    /* more code... */

    if( fgets( sLine, FILENAME_MAX, fh_Datafile ) != NULL )
    {
    }

That's probably what's really causing your program to blow up, not the exit().
 
By jove, I think I've found it. The fgets() function was producing the error. Well, I think that is how it should be said. Here is the function definition for fgets(): char *fgets(char *line, int n, FILE *fp) from C by Dissection: The essentials of C programming by Al Kelley and Ira Pohl. Apparently I need a buffer instead of a pointer. I read the function definition wrong. Thanks all for the help.
 
I guess I was a little slower than you to come up with the solution. As an addendum, here is what I ended up using as the array definition.
#include <stdio.h>

char p_Line[FILENAME_MAX] = {0};

/* some Code */

if( fgets( p_Line, FILENAME_MAX, fh_Datafile ) != NULL )


FILENAME_MAX is the maximum filename characters defined in <stdio.h>
 
It's cool you found it too! One suggestion, now that p_Line is actually a string array, you may want to drop the &quot;p&quot; prefix and change that to an &quot;s&quot; or &quot;sz&quot; to indicate that it isn't just a pointer, but a string (or null terminated string), according to hungarian notation.

Do you know what I mean? It's just a minor point which will make your variables more accurate and self-documenting.
 
Good point. I always try to make any program self-documenting because I sometimes forget to provide appropriate comments.

I am interested in fetching file information like file size, date, ownership and attributes, for each file pointed to by p_Line ( soon to be sz_Line ). I am interested in creating a function to fetch this file information that is compatible with UNIX and Win32 platforms. There are simple functions available on both platforms which provide this detail, however I'm looking for possibly a POSIX (???) standard function to use.

I've found a header called stat.h which is available on most UNICES and Windows compilers. I think this header provides the &quot;stat&quot; function, which will allow me to fetch the file information I need.

I've also discovered dos.h and dir.h; Borland specific headers. These include definitions of a file structure, but aren't cross platform compliant.

If someone could point me to the right way to fetch, and use, information about a file on both MSWindows and UNIX, please let me know.
Thanks in advance.
 
See this thread205-179608 regarding a link to <yawn> POSIX standards.

You may be better off posting your most recent request separately so it isn't buried in this thread. ;-)

Best wishes... nice meeting you.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top