0

Use a file pointer name in another file it was not declared in.

I want to use a file pointer name in another file it is not declared in using a makefile. I tried searching for it but I only found how to use normal variables and not file pointer names.

I tried just running it through the makefile I wrote for the commands and used the file pointer name as I would normally do but it said it was not declared because I didn't declare it in that specific file but I did declare it in the second C file.

This is the main file:

#include"cube.h"
#include <stdio.h>

int main() {
    char encdec;
    char fname[30];
    char foutname[30];
    printf("Write e for encode or d for decode\n");
    scanf("%c", &encdec);
    printf("Enter file name\n");
    scanf("%s", fname);
    printf("Enter output file name\n");
    scanf("%s", foutname);

    FILE* read = fopen(fname, "r");
    FILE* code = fopen(foutname, "w");

    char c;
    if (read == NULL) {
        printf("Error! opening file");
        return 0;
    }
    if (encdec == 'e' || encdec == 'E') {
        while ((c = fgetchar()) != EOF) {
            encode();
        }
    }
}

and this is the second file I want to use the file pointers from the main file:

int encode() {
    const int d = 10;
    if (c >= 'a' && c + d < 'z' || c >= 'A' && c + d < 'Z') {
        fprintf(code, "%c\n", c + d);
    }

    else if (c < 'A' || 'a'>c > 'Z' || c > 'z') {// making sure the input 
        is
            within the alphabets
            fprintf(stdout, "invalid character\n");
    }
    else if (c + d > 'z') {
        c = ((c + d) % 122) + 96;/*using the ascii equivalent of the
        letters for it to stay in the range of the alphabet we want it
        to
        be*/
        fprintf(code, "%c\n", c);
    }
    else if (c + d > 'Z' < 'a') {
        c = ((c + d) % 90) + 64;
        fprintf(code, "%c\n", c);
    }
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Itamar-C
  • 1
  • 2
  • 1
    Can you show us the code you're using? If you want to use a variable in more than one C file you'll have to use `extern` or just pass it as a parameter. Doesn't really have anything to do with a makefile, that's just how C works. – Retired Ninja Nov 01 '22 at 22:39
  • [How do I use extern to share variables between source files?](https://stackoverflow.com/questions/1433204/how-do-i-use-extern-to-share-variables-between-source-files) may be helpful. – Retired Ninja Nov 01 '22 at 22:42
  • What is a "file pointer name"? – Shawn Nov 01 '22 at 22:45
  • I would change `int encode()` to `int encode(FILE* code, int c)` and call it like `encode(code, c);` from `main`. Inside `main` you should also change `char c;` to `int c;` to properly handle `EOF`. – Retired Ninja Nov 01 '22 at 23:14
  • Use the arg because `c` in `main` isn't visible to `encode` so this won't compile. Also, `fgetchar()` --> `fgetc(read)` – Craig Estey Nov 01 '22 at 23:21
  • 1
    `'a'>c > 'Z'` is purely wishful thinking. – tadman Nov 01 '22 at 23:53

1 Answers1

0

You can use the file streams stdin, stdout and stderr in any file that includes <stdio.h> because the variables are declared in the header.

To use a variable by name in multiple files, it must be defined in one file and declared in all the other files that need to use. If the name is not declared, you cannot use it. If the name is declared inconsistently, the result is "undefined behaviour", something to be avoided at all costs. Using a single header to declare the variable and including that header both in the source file where the variable is defined and in all the source files that reference it gives you the maximum safety. The headers become the glue that holds the system together.

If you want to be able to use FILE *read; (see later for a discussion of the choice of read as the name) and FILE *code; in other files, you need a header (call it header.h) that is used by all the files. It will contain a header guard, #include <stdio.h> and the variable declarations:

#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED

#include <stdio.h>

extern FILE *read;
extern FILE *code;

#endif /* HEADER_H_INCLUDED */

Then the variables need to be defined at file scope (outside any function) in the main file:

FILE *read = NULL;
FILE *code = NULL;

Now you can use those names in the other files.

This is the standard, sane way of proceeding.

The header guards are necessary to prevent problems if the header is included more than once, whether it is included directly, which would be silly but happens, or indirectly, which is much more common and perfectly excusable. This makes the header "idempotent".

It's necessary to #include <stdio.h> so that the header compiles even if it is used on its own without any other headers before it. This makes the header "self-contained".

The header doesn't need any other information, so it doesn't include any other headers. This makes the header "minimal".

Your headers should be idempotent, self-contained and minimal.

The name read is not a good choice for a global variable — on POSIX systems, there is a system function read() too. It would be better to avoid the name clash. Your code will probably work these days, but it is better to be safe than sorry. And similar comments apply to other symbols defined by the Standard C library, the POSIX library, and the Windows library. When the variable was at function scope in main(), the name clash was largely harmless; you simply couldn't have used the function read() in the main() function (which you weren't trying to do), but the name had no linkage so it could not confuse the linker. It becomes more problematic at file scope, even if defined as a static variable; it means that you have to jump through hoops to call the function read() instead of using the file stream read. As a global variable, it is even more problematic.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278