0

I'm trying to print what is contained in a file, but it doesn't work when part of the code is enclosed in a function like this:

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

main() {    
    FILE *file;
    file = fopen(path, "rt"); //Instead of "path" there is the file's path

    read(file);
    fclose(file);
    return 0;
}

void read(f) {
    int c;

    if (f) 
        while ((c = getc(f)) != EOF)
            putchar(c);

}

However, it does work when I write everything in the main like this:

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

main() {    
    FILE *file;
    file = fopen(path, "rt");

    int c;

    if (file) 
        while ((c = getc(file)) != EOF)
            putchar(c);
    fclose(file);
    return 0;
}

Why doesn't it work? Any help will be really appreciated

LollolCat
  • 23
  • 7
  • 1
    Does your C compiler not give any warnings? Both clang and gcc produce several errors and warnings with default arguments. – Paul Hankin Apr 19 '21 at 13:38
  • there are only two valid signatures for function `main()` they are: `int main( void )` and `int main( int argc, char * argv[] )` – user3629249 Apr 20 '21 at 06:20
  • here is the prototype for function: `read()`: `ssize_t read(int fd, void *buf, size_t count);` `read()` is a well known C library function, It is a poor programming practice to try and replace C library functions with your own code, Suggest calling it `MyRead()` – user3629249 Apr 20 '21 at 06:26
  • regarding: `file = fopen(path, "rt");` 1) the variable: `path` is not defined, 2) always check (!=NULL) the returned value to assure the operation was successful, If not successful (==NULL) then call `perror( "fopen failed" )` so both your error message an the text reason the system thinks the failure occurred are output to `stderr` – user3629249 Apr 20 '21 at 06:30
  • 1
    regarding: `void read(f) {` the compiler will assume that the parameter has type `int`,, which will not work, To correct this, place a prototype before main() similar to: `void read( FILE f ); – user3629249 Apr 20 '21 at 06:37

3 Answers3

2

To answer your question , You have forgot to declare the type of f in in the function

void read(f) {

should be

void read(FILE *f) {

and

if (f) 

should be more

if (f!=NULL) 

Final code of function :

void read(FILE *f) {
int c;

if (f!=NULL) 
    while ((c = getc(f)) != EOF)
        putchar(c);

}

note : you should define the type of main (since you have used return 0; so it's int main() Finally : you should move the function before main (depends on your compiler )

Final code :

#include <stdio.h>
 #include <stdlib.h>
 void read(FILE *f) {
int c;

if (f!=NULL) 
    while ((c = getc(f)) != EOF)
        putchar(c);

 }
 int main() {    
FILE *file;
file = fopen(path, "rt"); //Instead of "path" there is the file's path

read(file);
fclose(file);
return 0;
 }
1

C compilers will assume that function arguments that are not declared or whose types are not specified as int for compatibility with old specification. In this case the argument should actually be FILE*. The size of int and FILE* may differ in some environment, so having the compiler make wrong assumption may cause trouble.

You should declare (or define) functions before using them and specify the type of the arguments, especially when you are working types other than int.

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

/* add declaration of the function */
void read(FILE* f);

/* add types */
int main(void) {
    FILE *file;
    file = fopen(path, "rt"); //Instead of "path" there is the file's path

    read(file);
    fclose(file);
    return 0;
}

/* add type of argument */
void read(FILE* f) {
    int c;

    if (f) 
        while ((c = getc(f)) != EOF)
            putchar(c);

}
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
0

Your file has had to be severely repaired to be able to run it, so I'm afraid you have not tested your code before sending it. Anyway, I have made a series of changes and I'll comment them in a diff file output, so you know what has been changed and how. Replacements are signalled with a - before the line changed, and with +

--- pru4358.c-orig      2021-04-20 10:05:49.236297000 +0300
+++ pru4358.c   2021-04-20 10:08:11.266937000 +0300
@@ -1,7 +1,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+char path[] = "file.txt";
+

There's no definition of the path variable in main. Every variable or data object must be declared to the compiler to be able to use it, before its use.

+void read(FILE *f);
+

you need to add prototypes of the functions you implement after their use in the file, or the compiler will not know what kinds of parameter your code uses and what types they are.

-main() {    
+int main() {    

Since a long ago, main() needs a return type int, and you need to write it. The compiler allows this to cope with very old legacy code, but it shouldn't be used in new projects. If you don't do, the compiler will assume your function returns int and when you later define it as void the compiler will shout at you telling that you don't agree yourself with the definition of it.

     FILE *file;
     file = fopen(path, "rt"); //Instead of "path" there is the file's path
 
@@ -10,7 +14,7 @@
     return 0;
 }
 
-void read(f) {
+void read(FILE *f) {

As above, you need to inform the compiler about the number or parameters, a name for each to be able to use them inside the function, and very important: the type of the parameters (in this case, FILE *)

     int c;
 
     if (f) 

Now, I will post the file as it is now, but commenting the places in which your don't do necessary things, that will lead you in trouble if you don't do them.

pru4358.c (corrected)

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

char path[] = "file.txt";

void read(FILE *f);

int main() {    
    FILE *file;
    file = fopen(path, "rt"); //Instead of "path" there is the file's path

You don't check the value returned from fopen(), and this can cause problems in the future, if you get NULL as return value from fopen() (It happened to me the first time I executed it, as I hadn't a file.txt. file)


    read(file);

You had better not to select a name like read for your file reading function. This example works (because you don't have to use the read(2) system call) but you'll run in trouble if you use any system call name (or even a library function name) for your own functions.

    fclose(file);
    return 0;
}

void read(FILE *f) {
    int c;

    if (f) 

You have better to do the NULL check before calling read(), just after fopen()ing it. Don't you think so? (As someone reading your code --like me--, would think you are not checking the return value of the function) You don't actually check it in main() and you later fclose() it being it NULL or not.

        while ((c = getc(f)) != EOF)
            putchar(c);

}

and last is how I believe your code should have been written (you were close to it :) )

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

/* static, to avoid name pollution */
static char path[] = "file.txt";

void copy_file_to_stdout(FILE *f);

int main() {
    FILE *file;
    file = fopen(path, "rt");

    if (!file) {
        fprintf(stderr, "ERROR: %s: %s\n",
                path, strerror(errno));
        /* don't continue if the file cannot be opened */
        exit(EXIT_FAILURE);
    }

    /* successfuly opened, so all that follows will have sense */
    copy_file_to_stdout(file);

    fclose(file);

    return EXIT_SUCCESS;
}

/* this is a better name for the file, as you don't just read the
 * file contents, you also write them to stdout. */
void copy_file_to_stdout(FILE *f) {
    int c;

    while ((c = getc(f)) != EOF)
        putchar(c);

}
Luis Colorado
  • 10,974
  • 1
  • 16
  • 31