Thread: File IO

  1. #1
    Registered User
    Join Date
    Sep 2010
    Posts
    63

    File IO

    i am trying to figure out how to check if a file exists in my void existing_file(void) function, and if not i would like to create it. The big thing that i am trying to do is prompt the user for a file path and also prompt the user for a name and append the name to the end of the path. Then use this path to make a new file! Also, how do i write a function that actually opens the file and shows it on the screen?

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void new_file();
    void existing_file();
    
    struct date {
            int day;
            int month;
            int year;
          } birth;
    
    int main(void)
    {
            int option;
    
        printf("1. Create a new file\n");
        printf("2. Open an existing file\n");
        printf("3. Exit program\n");
        printf("Enter option number: ");
        scanf("%d", &option);
    
        switch(option) {
            case 1:
                new_file();
                break;
            case 2:
                existing_file();
                break;
            case 3:
                exit(1);
                break;
        }
    
    }
    
    void new_file(void)
    {
    
        FILE *fp_a;
        FILE *fp_o;
        fp_o = fopen("/home/anthony/Documents/new.txt", "w");
    
            printf("Please enter your day of birth: ");
            scanf("%d", &birth.day);
    
            printf("Please enter your month of birth: ");
            scanf("%d", &birth.month);
    
            printf("Please enter your year of birth: ");
            scanf("%d", &birth.year);
    
        fp_a = fopen("/home/anthony/Documents/new.txt", "a+");
            fprintf(fp_a, "%d %d %d", birth.day, birth.month, birth.year);
    
            fclose(fp_a);
            fclose(fp_o);
    }
    
    void existing_file(void)
    {
        FILE *fp_e;
    
        char path[50];
        printf("Enter the file path: ");
        scanf("%c", &path);
    
        if(fp_e = (fopen("path", "a")==NULL)) printf("Cannot open file for appending!");
            else printf("File has been opened for appending.");
    
        if(fp_e)
    
    
        fclose(fp_e);
    
    }
    Thanks in advanced!!

  2. #2
    Registered User Swarvy's Avatar
    Join Date
    Apr 2008
    Location
    United Kingdom
    Posts
    195
    First of all, your main function should return an int. It is completely missing a return statement at the moment.

    Your new_file function opens a file under 'w+' mode, then takes a load of input from the user and finally opens the same file again using a different pointer and appends the data to the file. Why did you open the file the first time when you don't actually do anything in the file using that file pointer?

    As for your exist_file function this bit needs to change:
    Code:
    scanf("%c", &path);        /* Use '%s' instead of '%c' because you are extracting a string, not a single character */
    fopen("path", "a")           /* Get rid of the double quotation marks around the variable 'path' */
    Also note that a 50 character buffer (49 if you think about the NULL terminating character at the end) may not be enough in some circumstances. Even if it is enough, the way you blindly take the input means you are leaving yourself open to a buffer overflow attack (if you don't know what those are, google it).

    There are no checks imposed on the variable 'path' which means that if the user made a mistake or intentionally entered incorrect directory information the program will experience a runtime error and your program will crash.

    In terms of printing out the contents of the file you could try something like this:
    Code:
    do
    {
          fgets(temp_buff, sizeof(temp_buff), fp_e);
          printf("%s", temp_buff);
    } while( !feof( fp_e ) );
    Just curious, but why don't you pass parameters to, or return info from, the functions you have written? If you don't know how, don't be shy to ask. If you don't ask questions you won't get answers.
    Last edited by Swarvy; 10-31-2010 at 11:05 PM.

  3. #3
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by codecaine_21 View Post
    i am trying to figure out how to check if a file exists in my void existing_file(void) function, and if not i would like to create it.
    You can try opening it for append access, as you are already doing.
    If the first open fails, open if for write.

  4. #4
    Registered User
    Join Date
    Sep 2010
    Posts
    63
    Swarvy.... I see what you are saying about the w+ mode and the append mode. I will drop the write and keep the append! I just thought I had to open a file for writing before I could append to it. So what parameters do you suggest I pass and why? Because I didn't think I needed them. I am familiar with function parameters but not great with them. And I understand your way of printing the file to the screen. Great suggestion, thank you! And how do you suggest I take in the input instead of the way I am doing it? To fix the buffer overflow problem?

    CommonTater... Not much to say. Very clear, thanks you!!

  5. #5
    Registered User Swarvy's Avatar
    Join Date
    Apr 2008
    Location
    United Kingdom
    Posts
    195
    Perhaps if you take the inputted user directory & filename into the function then you could make your program command line based as well as having a 'user interface'. That way your program could do both. Alternatively if you make it take a string as a parameter then you have a handy little function for any later projects you do. I've been doing that with most of the code I have written for a while (most of the decent code anyway), and I've ended up being up quite a nice little library of common, homemade functions and classes (C++) that I've used in many different projects.

    By all means, you don't have to make your functions take parameters, it was just a suggestion. It really depends whether you feel it is worth the time/effort to do it.

    As for the buffer overflow problem, when using C to take strings you could declare a fixed size buffer and then use the fgets() function (there are other ways of doing it) (I would normally just throw in some C++ strings, but since this is the C section, I'm not gonna talk about that), as so:
    Code:
    char temp_buff[256];
    fgets(temp_buff, sizeof(temp_buff), stdin);
    The only problem with the fgets method should above is that it considers the new-line character to be a valid part of the string (which is what you want in most situations, but not the directory/filename situation below). So you would have to clip the last character of any inputted string from it. It is fairly easy to do, just a little more hassle.

    This works because it automatically clips the input if the user types too much. I don't think you really need to worry about buffer overflow exploits in this program you are writing but I am just trying to teach good programming practice from the outset. It is much harder to change bad habits when you have been programming for a while.

    If you want to take the directory and filename as separate inputs then you could use the sprintf() function to append the filename to the directory:
    Code:
    char file_dir[256];
    char file_name[256];
    char temp_buff[512];
    
    fgets(file_dir, sizeof(file_dir), stdin);
    fgets(file_name, sizeof(file_name), stdin);
    
    sprintf(temp_buff, "%s/%s", file_dir, file_name);
    Last edited by Swarvy; 11-01-2010 at 12:11 AM.

  6. #6
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >You can try opening it for append access, as you are already doing.
    >If the first open fails, open if for write.
    There's no need to make two requests. A base open mode of "a" will create the file if it doesn't exist. In fact, the only time a file won't be created, assuming the operation succeeds at the system level, is if the base open mode is for reading ("r", "rb", "r+" "r+b", "rb+").
    My best code is written with the delete key.

  7. #7
    Registered User
    Join Date
    Sep 2010
    Posts
    63
    Prelude, I took out the write mode and used read. Because read returns a null character if the file doesn't exists. From there I can open a file with append mode. Or whatever. Thanks!!

    Swarvy, I used your sprintf thingy and I keep getting errors! It prompts the user for the persons name but you cannot input anything. It won't allow you to put in the users name. It automatically prints file does not exist. I have a feeling that the char buffers can't be used with file io?? Like maybe they aren't compatible? Or maybe type casting is needed? Here's the code

    [code]
    Void new_file(void)
    {
    char file_dir[256] = "/home/anthony/Documents";
    char file_name[256];
    char temp_buff[512];

    printf("Please enter the persons name: ");
    fgets(file_name, sizeof(file_name), stdin);

    sprintf(temp_buff, "%s/%s", file_dir, file_name);

    FILE *fp_a;
    If((fp_a = fopen(temp_buff, "r"))==NULL)
    fp_a = fopen(temp_buff, "a");
    Fclose(fp_a);
    }
    [\code]

    Some stuff might be a little off cuz I wrote this from my tiny little screen on my iPhone.

    .
    Last edited by codecaine_21; 11-01-2010 at 10:23 PM.

  8. #8
    Registered User Swarvy's Avatar
    Join Date
    Apr 2008
    Location
    United Kingdom
    Posts
    195
    Quote Originally Posted by Swarvy
    The only problem with the fgets method should above is that it considers the new-line character to be a valid part of the string (which is what you want in most situations, but not the directory/filename situation below). So you would have to clip the last character of any inputted string from it. It is fairly easy to do, just a little more hassle.
    In my previous post I did mention a possible problem with how fgets works which might cause problems and it looks like it has. When you use fgets to collect input from the standard input (stdin), it treats the new-line character on the end when you press enter as part of the string - it doesn't remove it from the string. That is the problem you are having. You are leaving the new-line character on the end of the string and this is causing fopen to fail.

    The way you solve this problem is to add in the following line of code after you have combined the two strings, but before you call fopen.
    Code:
    temp_buff[ strlen(temp_buff) - 1 ] = '\0';
    This will replace the '\n' at the end of your string with a NULL character, terminating the string and allowing fopen to work properly.

    Edit: Almost forgot, the strlen function is included in the string header file so you will need to include that if you haven't already.
    Last edited by Swarvy; 11-01-2010 at 11:40 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A development process
    By Noir in forum C Programming
    Replies: 37
    Last Post: 07-10-2011, 10:39 PM
  2. Can you help me about tolower() in file
    By nctar in forum C Programming
    Replies: 7
    Last Post: 05-12-2010, 10:04 AM
  3. Formatting the contents of a text file
    By dagorsul in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2008, 12:36 PM
  4. Can we have vector of vector?
    By ketu1 in forum C++ Programming
    Replies: 24
    Last Post: 01-03-2008, 05:02 AM
  5. File IO with .Net SDK and platform SDK
    By AtomRiot in forum Windows Programming
    Replies: 5
    Last Post: 12-14-2004, 10:18 AM