Thread: Constructing the name of a file to open

  1. #1
    Registered User
    Join Date
    Sep 2015
    Posts
    13

    Constructing the name of a file to open

    I need to get the value of the environment variable TEMP and append the string “\test.dat” to it. Then I want to open a file with this name for writing. Then I want to write some stuff and close it.
    I can't get this working.

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    
    int main(int argc, char *argv[]) {
        const char* env_p = getenv("TEMP");
        strcat(env_p, "\\test.dat");
        FILE fp = fopen(env_p, "w");
        fprintf(fp, "%s\n","blah");
        fclose(fp);
    }
    What am I doing wrong?

  2. #2
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    Undefined behavior:
    Code:
    const char* env_p = getenv("TEMP");
    strcat(env_p, "\\test.dat");
    you need to copy the string in a new, writeable char array.

    Wrong type:
    Code:
    FILE fp = fopen(env_p, "w");
    "fp" needs to be a pointer to FILE.
    Devoted my life to programming...

  3. #3
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Fixing the compile warnings and errors would probably help.
    main.c||In function ‘main’:|
    main.c|7|error: implicit declaration of function ‘strcat’ [-Wimplicit-function-declaration]|
    main.c|7|warning: incompatible implicit declaration of built-in function ‘strcat’|
    main.c|7|error: passing argument 1 of ‘strcat’ discards ‘const’ qualifier from pointer target type|
    main.c|7|note: expected ‘char *’ but argument is of type ‘const char *’|
    main.c|8|error: invalid initializer|
    main.c|9|error: incompatible type for argument 1 of ‘fprintf’|
    /usr/include/stdio.h|356|note: expected ‘struct FILE * restrict’ but argument is of type ‘FILE’|
    main.c|10|error: incompatible type for argument 1 of ‘fclose’|
    /usr/include/stdio.h|237|note: expected ‘struct FILE *’ but argument is of type ‘FILE’|
    main.c|5|warning: unused parameter ‘argc’ [-Wunused-parameter]|
    main.c|5|warning: unused parameter ‘argv’ [-Wunused-parameter]|
    ||=== Build finished: 5 errors, 3 warnings (0 minutes, 0 seconds) ===|
    You should also read some documentation for the getenv() function before you try to actually use it.

    Pay particular attention to this part:
    RETURN VALUE
    The getenv() function returns a pointer to the value in the
    environment, or NULL if there is no match.
    And this part:

    As typically implemented, getenv() returns a pointer to a string
    within the environment list. The caller must take care not to modify
    this string, since that would change the environment of the process.

    Jim

  4. #4
    Registered User talahin's Avatar
    Join Date
    Feb 2015
    Posts
    51
    To late with my answer again, but still here's my response

    Code:
    #include <stdlib.h>
    #include <stdio.h>
     
    int main(int argc, char *argv[]) {
    Code:
        const char* env_p = getenv("TEMP");
        strcat(env_p, "\\test.dat");
    declaring at variable as const is considered a promise to the compiler that you won't try to change the content of the variable, yet in the next line you are doing just that.

    Code:
        strcat(env_p, "\\test.dat");
    strcat is defined in string.h, So you should include it.
    Also, because most string functions have no bound checks, the programmer, has to make sure that there is enough space in the strings that they are manipulating. In this case make sure your env_p has enough space for the extra characters you try to concatenate. Otherwise you may end up with a segmentation fault.
    Code:
        FILE fp = fopen(env_p, "w");
    you named your variable fp, which you probably ment to be a pointer to a file object, Then why do you declare it as a file object and not a pointer to a file object.
    Also, if you call a function that might fail, you should check if it failed or not.

    Code:
    }
    You declared main as a function that would return a int.
    So return a value.

    I leave it for now. After you solved you current problems and if you still have problems compiling, show your new code and the compilations error messages.

    Cheers

  5. #5
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    I would use
    Code:
    #define _POSIX_C_SOURCE 200809L
    #include <stdlib.h>
    #include <stdio.h>
    #include <wordexp.h>
    
    int main(void)
    {
        FILE *out;
        wordexp_t w;
    
        if (wordexp("$HOME/example.txt", &w, WRDE_NOCMD) != 0) {
            fprintf(stderr, "Cannot locate example.txt.\n");
            return EXIT_FAILURE;
        }
    
        if (w.we_wordc != 1) {
            fprintf(stderr, "Multiple possibilities for locating example.txt.\n");
            return EXIT_FAILURE;
        }
    
        out = fopen(w.we_wordv[0], "wb");
        if (out == NULL) {
            fprintf(stderr, "%s: %m.\n", w.we_wordv[0]);
            return EXIT_FAILURE;
        }
    
        fprintf(out, "Hello, world!\n");
    
        if (fflush(out)) {
            fprintf(stderr, "%s: Write error.\n", w.we_wordv[0]);
            fclose(out);
            return EXIT_FAILURE;
        }
        if (fclose(out)) {
            fprintf(stderr, "%s: Write error closing file.\n", w.we_wordv[0]);
            fclose(out);
            return EXIT_FAILURE;
        }
    
        printf("%s created successfully.\n", w.we_wordv[0]);
    
        wordfree(&w);
    
        return EXIT_SUCCESS;
    }
    but it only works on systems that provide a C library with POSIX.1 capabilities (Linux, Mac OS X, BSDs, many Unixes -- I don't think it works in Windows).

    I could have made it shorter, but this version has very careful error checking in place.

  6. #6
    Registered User
    Join Date
    Sep 2015
    Posts
    13
    Thanks all. I got it working:

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    
    int main(int argc, char *argv[]) {
        FILE* fp;
        char buff[1024];
        const char* env_p = getenv("TEMP");
        strcpy(buff, env_p);
        strcat(buff, "\\test.dat" );
        fp = fopen(buff, "w");
        if(fp != NULL) {
          fprintf(fp, "%s\n","blah");
          fclose(fp);
          return 1;
        }
        else {
          return 0;
        }
    }

    Doesn't seem that it needs <string.h>. Also I thought you could declare variables when you needed them in C, but apparently not, they have to be declared at the top of the routine like Fortran (I am one of these...)

  7. #7
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Quote Originally Posted by ferrad View Post
    Doesn't seem that it needs <string.h>.
    It does if you're using string functions (strcpy, strcat). Try maximizing your compiler warnings to see if you get any "implicit declaration" warnings.

    Quote Originally Posted by ferrad View Post
    Also I thought you could declare variables when you needed them in C, but apparently not, they have to be declared at the top of the routine like Fortran (I am one of these...)
    This limitation is from an older C standard. What compiler and OS are you using?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 03-10-2013, 09:47 PM
  2. Replies: 3
    Last Post: 03-08-2010, 02:43 PM
  3. Replies: 12
    Last Post: 03-10-2005, 07:48 PM
  4. constructing frames...
    By Devil Panther in forum Networking/Device Communication
    Replies: 20
    Last Post: 08-09-2004, 12:34 PM
  5. Constructor not constructing!
    By Dragoon_42 in forum C++ Programming
    Replies: 6
    Last Post: 02-05-2003, 03:48 PM