![]() |
| | #1 |
| Registered User Join Date: Jun 2009 Location: Melbourne, Australia
Posts: 49
| NULL or '\o' usage I am a little puzzled by the NULL or \0 that terminates strings and how is it generated and tested for. I am reading in a list of file names as the contents of a file (file A) . I then wish to open File A and use it's contents to open the text files in question and analyse them. The problem I have is that I can open file A ok and print out its contents but I can't seem to open the individual files and print their contents. I am want to read out their contents line by line and print them for a start. I am using a NULL check to get the whole line but it seems to be ignored Code: while (fgets(fileline, 22, tmpFile)!=NULL) {
printf("*** Inside the RPT file contents ***\n");
Code: intptr_t searchHandle = _findfirst("*.rpt", &fileData);
// if the search started
if (searchHandle != -1) {
// print a banner
//puts("Found the following files:");
rptFile = fopen (rpt_file, "w+"); /* open data file "rptFile.dat" for writing */
do {
// print the file name
//puts(fileData.name);
fprintf(rptFile, "%s\n", fileData.name); /* write RPT file name to rptFile.dat file */
}
// look for any more files
while (_findnext(searchHandle, &fileData) == 0);
// stop the search after all have been enumerated
_findclose(searchHandle);
fclose(rptFile);
The opening of file A is Code: if ( (access(rpt_file, F_OK)) != -1 ) {
//printf("An RPT.dat file exists\n");
rptFile = fopen (rpt_file, "r");
while (fgets(rptline, 25, rptFile)!=NULL) { //loop for reading a line up to end of file
//printf("RPT file exists, getting name of it out of file\n");
printf("%s", rptline); //print the name of each RPT file found
printf(" Opening %s", rptline);
//open each RPT individually and print out it's contents.
tmpFile = fopen(rptline, "r"); /* open data file "rptFile.dat" for reading */
while (fgets(fileline, 22, tmpFile)!=NULL) {
printf("*** Inside the RPT file contents ***\n");
}
printf(" Closing %s", rptline);
fclose(tmpFile);
}
} else {
printf("An RPT.dat file does not exist");
return 0;
}
|
| Tigers! is offline | |
| | #2 |
| and the Hat of Guessing Join Date: Nov 2007
Posts: 8,740
| 1. A pointer can be NULL. A character can be '\0'. 2. To be a string, a bunch of characters in memory must have a '\0' character at the end. This character is neither read from or written to a file. (But when a string is read in, the '\0' character is (almost always) added to the end for you.) |
| tabstop is offline | |
| | #3 |
| Registered User Join Date: Sep 2006
Posts: 2,415
| Using != NULL: I would use != EOF, instead. Your while loop is getting all the lines in the file, not just the first line. Don't worry, fgets() knows to stop whenever it encounters a newline. ![]() For your buffer, I would make it one to two chars longer - there will be a newline (which may be actually two char's for a Windows text file (CarriageReturn&LineFeed). All of these input details can be readily solved by checking the contents of your buffer, and the contents of your line of text. Another check - when you print your buffer, does it move the cursor down to the next line and return it to the far left hand side of the screen? If so, then you know it has the newline char in it. Same goes with your filenames. Print them out. Remember that a \ char is an escape char in printf(). You need two \\'s to show one \ with printf(). It's not '\o', it's '\0' for the end of string char. |
| Adak is offline | |
| | #4 |
| Registered User Join Date: Jun 2009 Location: Melbourne, Australia
Posts: 49
| Thank you for your replies. I am still having trouble so I added in a test message to see if I am opening each file mentioned in File A correctly. Code: if(tmpFile==NULL) {
printf("Error: can't open file.\n");
return 1;
}
I am opening the file, denoted by rptline, as read only e.g. Code: tmpFile = fopen(rptline, "r"); /* open data file "rptFile.dat" for reading */ Code: char rptline[25]; //name of RPT file
..
while (fgets(rptline, 25, rptFile)!=NULL)
{
..
}
Code: tmpFile = fopen(rptline, "r"); /* open data file "rptFile.dat" for reading */ It may not be a subtle error as I am still relearning C and have had blatant errors in the past. |
| Tigers! is offline | |
| | #5 |
| and the hat of vanishing Join Date: Aug 2001 Location: The edge of the known universe
Posts: 21,214
| > I have allowed 22 characters for the fgets to have the \0 included. So where did 25 come from? fgets(rptline, 25, rptFile) If you've got char rptline[22]; then fgets(rptline, sizeof(rptline), rptFile) is the best way of making sure the size passed to fgets() is correct. > Using != NULL: I would use != EOF, instead. Except fgets() doesn't return EOF, it returns NULL Edit: answer to your update Having read a line using fgets(), you need to remove the \n from the end before using it as a filename. How to do this is in the FAQ somewhere.
__________________ If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut. Up to 8Mb PlusNet broadband from only £5.99 a month! |
| Salem is offline | |
| | #6 |
| Registered User Join Date: Oct 2008 Location: TX
Posts: 1,238
| Strip out the newline left behind as your buffer (rptline[]) is bigger than the string you are reading from fileA, as in Code: while (fgets(rptline, 25, rptFile)!=NULL)
rptline[strlen(rptline)-1] = NULL;
...
|
| itCbitC is offline | |
| | #7 |
| and the hat of vanishing Join Date: Aug 2001 Location: The edge of the known universe
Posts: 21,214
| > rptline[strlen(rptline)-1] = NULL; Whilst NULL may be 0 on your system, it sends the wrong semantic message to the reader. Use '\0' when referring to the character called 'nul'. Also, simply removing the last character does NOT take into account the case where there is no \n at the end (for example, reading a long line into a short buffer).
__________________ If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut. Up to 8Mb PlusNet broadband from only £5.99 a month! |
| Salem is offline | |
| | #8 |
| Registered User Join Date: Sep 2006
Posts: 2,415
| This is one way to do it: To see it work, you'll need at least 2 tiny files: (I tested it with 4) 1) filenames.txt - which just lists each of the below listed filenames, one per line. 2) files with the proper names and extensions (if any), that you have listed in #1, above. Each of these files should have 1 single integer on the first line, and nothing else. The trick mentioned by itCbitzC above, is worth remembering when you're working with strings: Code: fnames[strlen(fnames)-1] = '\0'; Code: /*Snippet shows how to read a list of files, and then open each file, one
after the other.
Status: OK
*/
#include <stdio.h>
#include <string.h>
int main(void) {
int i, number;
FILE *in1, *in2;
char fnames[25];
/*Earlier I said use EOF for this test -
that was wrong ( EOF is used with fscanf() ),
use NULL for fopen() and fgets() testing.
*/
//Open the file with the filenames listed in them
if((in1=fopen("filename.txt", "rt")) == NULL) {
printf("\nError opening filename.txt, program terminated\n");
return 1;
}
/*read a filename, and open that file. Read it's contents, and close it
when all it's data has been read. Then repeat on each subsequent file
that's listed.
*/
printf("\n\n");
while(fgets(fnames, 23, in1) != NULL) {
fnames[strlen(fnames)-1] = '\0';
if((in2 = fopen(fnames, "rt")) == NULL) {
printf("\nFile Not Found: %s\n", fnames);
continue;
}
if(fscanf(in2, "%d", &number))
printf("\n The number I read was: %d", number);
close(in2);
for(i = 0; i < 25; i++)
fnames[i] = '\0';
}
close(in1);
printf("\n\n\t\t\t Press Enter When Ready");
i = getchar();
return 0;
}
Last edited by Adak; 07-06-2009 at 10:48 AM. |
| Adak is offline | |
| | #9 | |
| Registered User Join Date: Oct 2008 Location: TX
Posts: 1,238
| Quote:
You're right, my solution was specific given that the string read from fileA was shorter (=21) than the destination buffer (=22). | |
| itCbitC is offline | |
| | #10 |
| Registered User Join Date: Jun 2009 Location: Melbourne, Australia
Posts: 49
| Et al Thank you for all your replies. Having a fiddle last night I could get File A to be read provided it was created in the form Code: 20090220085501237.RPT20090310111500094.RPT20090316112501203.RPT20090507091000206.RPT20090604103500072.RPT ![]() Is it possible to be able to get File A to be created in the form Code: 20090220085501237.RPT 20090310111500094.RPT 20090316112501203.RPT 20090507091000206.RPT 20090604103500072.RPT I am still unsure whether '\0' needs to be added by my programme when creating file A and whether I need to add '\n' (new line or carriage return). Are the '\0' and '\n' considered as part of the characters that fgets must extract or can they be ignored? Or maybe I just start again? |
| Tigers! is offline | |
| | #11 | |
| subminimalist Join Date: Jul 2008 Location: NYC
Posts: 3,788
| Quote:
fgets() reads to the newline, chucks it, and adds a null terminator, so you do not have to deal explicitly with either character in an fgets statement. Your suggested format for file A should be fine, but you will need to add a \n to get the filenames on separate lines. WRT to that, this is a valid string: Code: "20090220085501237.RPT\n20090310111500094.RPT\n20090316112501203.RPT\n"
__________________ Accuracy and integrity mean nothing if you don't make it past the censors...PYTHAGORAS Last edited by MK27; 07-06-2009 at 05:00 PM. | |
| MK27 is offline | |
| | #12 |
| Registered User Join Date: Apr 2006 Location: United States
Posts: 3,183
| There's information regarding replacing '\n' with '\0' here. If you use a flexible approach like the one from the link, the format of the file names file won't matter so much, as long as the input from fgets is going to be complete (hence I think why you want to read 25 characters, as every file name is this size in the file -- give that constant a name, btw!).
__________________ Os iusti meditabitur sapientiam Et lingua eius loquetur indicium "There is nothing either good or bad, but thinking makes it so." (Shakespeare, Hamlet, Act II scene ii) http://www.myspace.com/whiteflags99 |
| whiteflags is offline | |
| | #13 | |
| Senior software engineer Join Date: Mar 2007 Location: Portland, OR
Posts: 5,357
| Quote:
If the output of your program is considered "text" then it probably should not contain null characters, but "text" is not the only kind of output a program could produce.
__________________ "Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot | |
| brewbuck is offline | |
| | #14 | |
| subminimalist Join Date: Jul 2008 Location: NYC
Posts: 3,788
| Quote:
But there is no law, human or otherwise, that says you cannot do that.
__________________ Accuracy and integrity mean nothing if you don't make it past the censors...PYTHAGORAS | |
| MK27 is offline | |
| | #15 |
| Senior software engineer Join Date: Mar 2007 Location: Portland, OR
Posts: 5,357
| No it won't. fgets() pays no attention to '\0'. It reads bytes until it either fills the buffer or sees a '\n'
__________________ "Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot |
| brewbuck is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Linked List Not Saving Value as Int | bar338 | C Programming | 4 | 05-04-2009 07:53 PM |
| Help Debugging my AVL tree program. | Nextstopearth | C Programming | 2 | 04-04-2009 01:48 AM |
| Compiling 3rd party code problem me too | siavoshkc | C Programming | 1 | 09-12-2007 05:55 AM |
| Linked List of Linked list of linked list : problem with a condtion | gemini_shooter | C Programming | 6 | 03-02-2005 02:45 AM |
| Contest Results - May 27, 2002 | ygfperson | A Brief History of Cprogramming.com | 18 | 06-18-2002 01:27 PM |