6

I'm just getting started on my first ever C++ program and am pretty much just learning as I go. The program is supposed to have 3 different files, a header file (prog1.h), a prog1.cpp file (not sure the right terminology for this one) and a test file that includes main: to test our program (prog1_test.cpp).

Not asking for help on any of this (yet, I'm sure I'll be posting another question once I get into it), but figured you'd need to know what the program is supposed to do in order to understand my question. Our program is supposed to read in some numbers from a file and put these numbers into a 2D array. It's then supposed to assign characters to each number value and print the current array and the "picture" created with the characters. Then it will go through the array, making sure that each number doesn't differ in value from it's neighbors by more than 1, if it does, the program is to replace that number with the average of its neighboring values. The program will then print out this corrected array and "picture" created with the characters assigned to the corrected array.

I know that header files are supposed to include code that will be used across multiple files, but am having trouble figuring out what parts of my program need to go in this file. For example, would my code to open, read, and close the data file be included here, or no since the file is only being opened, read, and closed once?

  • The header should not include code that will be called by other code in multiple files, it should include *what that other code needs to know about that code*. That basically means function and class *declarations*. If you give us some simple examples of code, we can explain in more detail. – Beta Sep 10 '14 at 04:40
  • So, this might include things like the function to assign the characters to the numbers, and the function to check for errors (numbers differing by more than 1 from their neighbors)? I was going to try and divide this up into the multiple files as I went, but I'm thinking it'd be easier to do it all in one file and then divide it up after I have it working. I don't actually have any code written, like I said, I'm literally learning this stuff as I go, so still trying to get started. I'll post code when I have some written though. –  Sep 10 '14 at 04:44
  • It helps to realize, that in C++ (and C), `#include` is equivalent to copy-pasting contents of included file. This has a bunch of implications, but most importantly it will help you understand when linker complains about duplicate symbols, which you will no doubt encounter. – hyde Sep 10 '14 at 06:33
  • Does this answer your question? [What should go into an .h file?](https://stackoverflow.com/questions/1945846/what-should-go-into-an-h-file) – Antti Haapala -- Слава Україні Sep 09 '20 at 17:51

3 Answers3

5

Header files contain function and class declarations. These simply declare the name of the function, its return type, and its argument list. The .cpp file contains the definitions of these functions -- i.e. the actual implementation. The header file is visible to the rest of the program if you #include it in other files, but the implementation details are hidden in the .cpp file.

Anything declared/defined in the .cpp file that is not in the .h file is not visible to the rest of the program, so you can define internal variables, helper functions, etc. in the .cpp file and those implementation details will not be visible. An example of this is foo() in my example below.

A very rough sketch of your program would look like this:

In prog1.h:

#include <iostream> // and whatever other libraries you need to include

#define ARRAY_SIZE 100 // and other defines

// Function declarations

// Read number from file, return int
void read_number(int array[ARRAY_SIZE][ARRAY_SIZE]);

char assign_char(int n);

void print_array(int array[ARRAY_SIZE][ARRAY_SIZE]);

void neighbor_check(int array[ARRAY_SIZE][ARRAY_SIZE]);

In prog1.cpp:

// included headers, defines, and functions declared in prog1.h are visible
#include "prog1.h"

void read_number(int array[ARRAY_SIZE][ARRAY_SIZE]) {
    // implementation here
}

char assign_char(int n) {
    char c;
    // implementation here
    return c;

}

void print_array(int array[ARRAY_SIZE][ARRAY_SIZE]) {
    // implementation here
}

void neighbor_check(int array[ARRAY_SIZE][ARRAY_SIZE]) {
    // implementation here
}

// not visible to anything that #includes prog1.h
// since it is not declared in prog1.h
void foo() {
    // implementation here
}

In prog1_test.cpp:

// included headers, defines, and functions declared in prog1.h are visible
#include "prog1.h"
// any other includes needed by main()

int main() {
   int array[ARRAY_SIZE][ARRAY_SIZE];

   read_number(array);

   for (int i = 0; i < ARRAY_SIZE; i++) {
       for (int j = 0; j < ARRAY_SIZE; j++) {
           assign_char(array[i][j]);
       }
   }

   neighbor_check(array);

   print_array(array);

   return 0;
}
Null
  • 1,950
  • 9
  • 30
  • 33
3

The use of various header files, and code/implementation files separate and apart from the application file is done to promote maintainability and reuse of code. By collecting all related functions, variables and data structures in a single file, we prevent having to duplicate that code in every subsequent application we write.

Take for example your situation where you will be developing routines related to matrices or arrays. This scheme allows you to collect the common routines dealing with your arrays into a single file, say arrays.c. Now regardless of how many more programs you write, you have a common file that contain your array routines. Now if you write 5 more applications that need your array routines, you have them ready to go in arrays.c.

For maintainability, let's say you now have a more efficient way of handling input from a file to your array. Instead of having to go back and update the read_array function in 5 different application program files, you simply update the one read_array function in arrays.c and you have accomplished updating that routine for all applications that use it.

How does the header file fit in? In order to use your array functions in other applications, the applications need a common way of including the code to make it available for use. That is done by including your arrays.h header file in each application that needs it. OK, so what goes in arrays.h and what goes in arrays.c? Your header files will include the header files, function declarations, data structures and variables for your array routines that are necessary to implement the function definitions contained in arrays.c. That way any application that wishes to make user of your array routines need only include the line #include "arrays.h" at the beginning of its file to have access to your array functions contained in arrays.c

An example (in C) will help sort things out. Say you have several array functions that read lines in a text file into strings read_array, print the lines prn_array and then frees the memory used by the array and strings free_array. You have collected your array functions in array.c. (we know we will include array.h at the top.) So, for example:

#include "array.h"

char **read_array (char *filename)
{
    char *buffer = NULL;
    size_t len = 0;
    ssize_t read;
    char **array = NULL;
    int cnt = 0;

    FILE *fp;
    fp = fopen (filename, "r");      //open file , read only
    if (!fp) {
        fprintf (stderr, "failed to open file for reading\n");
        return NULL;
    }

    array = calloc (AMAX, sizeof (*array) * AMAX); /* allocate pointers, set NULL */

    while ((read = getline (&buffer, &len, fp)) != -1) { /* read each line */

        if (cnt == AMAX) {
            fprintf (stderr, "Error: AMAX reached\n");
            break;
            /* you will realloc *array here in real life */
        }

        if (buffer[read-1] == '\n') {   /* strip newline              */
            buffer[read-1] = 0;
            read -= 1;
        }

        array[cnt] = strdup (buffer);   /* copy buffer to array[cnt]   */
        cnt++;                          /* increment counter           */
    }

    fclose (fp);                        /* close file stream (fp)      */
    return array;
}

void prn_array (char **array)
{
    register int j = 0;
    while (array[j]) {
        printf ("  array[%d]: %s\n", j, array[j]);
        j++;
    }
}

void free_array (char **array)
{
    register int j = 0;
    while (array[j]) {      /* for each allocated string */
        free (array[j]);    /* free pointer to string    */    
        j++;
    }
    free (array);           /* free array                */
}

Now let's create our header. We collect our function declarations along with any variables or data structures used and also include the system headers and any other included header files required by our functions in array.h:

#ifndef MY_ARRAY_H
#define MY_ARRAY_H  1

/* headers required for array.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define AMAX 100

/* function declaration */
char **read_array (char *filename);
void prn_array (char **array);
void free_array (char **array);

#endif  /* MY_ARRAY_H */

Notice we have wrapped the contents of our header inside a test #ifndef MY_ARRAY_H which just asks the compiler if MY_ARRAY_H is defined yet, ifndef (if not defined), we let the compiler know that everything that follows our #define until we reach the end of the if statement #endif we are defining as MY_ARRAY_H so that if another file tries to include the same header -- the compiler knows it already has it and doesn't need to include it again. (not required, but we also give our define of MY_ARRAY_H the value 1)

So how do we put our custom header array.h and our custom functions for handling arrays in arrays.c to work for us? We write an application that makes use of the functions in arrays.c and to declare all the functions in arrays.c in our application, we simply include array.h in our application. (called application.c below):

#include <stdio.h>
#include "array.h"                      /* include array.h  */

int main (int argc, char *argv[]) {

    if (argc < 2) {
        printf ("filename.csv please...\n");
        return 1;
    }

    char **my_array = NULL;             /* declare pointers */

    my_array = read_array (argv[1]);    /* call read_array  */
    prn_array (my_array);               /* call prn_array   */
    free_array (my_array);              /* call free_array  */

    return 0;
}

compile the application.c and array.c files:

gcc -Wall -Wextra -o application application.c array.c

run it on any short text file (less than 100 lines)

$ ./application input.txt
  array[0]: 1.  This is a simple input file with line numbers
  array[1]: 2.  for use with application showing the use of
  array[2]: 3.  header file: array.h
  array[3]: 4.  array functions defined in: array.c
  array[4]: 5.  (blank)
  array[5]: 6.  compiled with the following:
  array[6]: 7.  gcc -Wall -Wextra -o application application.c array.c
  array[7]: 8.  --------
  array[8]: 9.  Now you know!

Now you can see the benefit of creating a separate file holding the related functions, variables, and data structures we will use and creating a header file. We can reuse that code in any application we like simply by including the header file arrays.h in our application. We can update and maintain all our array functions in one place and updating our arrays.c will update all other applications that make use of that code.

I know I have left much out, but make sure you are solid on these concepts. They are fundamental to working with multiple source files and includes in C/C++.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
0

Following basic things should appear in your header file.

  1. class body with function declaration , data variable, constructor and destructor declaration.
  2. declaration of all functions in class. Note: not a function body or definition.
  3. inline functions.
  4. define
  5. all library include header files. so you need to add only one header file in you respective .c file of this header file.
  6. structures
  7. ifndef block
  8. forward declaration of class if you need it some times.
  9. doxygen comments for the functions and classes and variables.
  10. description of this file as comment in top of you header file for doxygen. etc...

Header file should not have any code.

user2641018
  • 108
  • 5
  • So is it kind of the equivalent of an interface in Java? I'm just thinking since an interface only contains the declarations of abstract classes and not any body code for these declarations, that maybe headers are kind of similar? I'm really new to this and am pretty much teaching it to myself with a lot of help from google and my textbook (my prof's not very good at explaining things in a way that we actually know what he's talking about ha) but am kind of familiar with Java, so trying to use what I know from that to help me learn this, if that makes any sense. –  Sep 10 '14 at 05:06
  • I disagree on point 5: This unnecessarily prolongs builds because the library headers will be included in *all* .cpp files using it. Better include only those library headers that you need for the header itself, and include the rest in the .cpp file. Compilation times are already much worse in C++ than with C, no need to artificially worsen it. – cmaster - reinstate monica Sep 10 '14 at 05:20
  • 1
    You should also put your templated code in a header. That and point 3 thus contradicts your last rule. – Willem Hengeveld Sep 10 '14 at 05:25
  • to cmaster yup you are right.... but i answered in context of only one header file and one cpp file. – user2641018 Sep 10 '14 at 05:28
  • 1
    it is best practice in c++ to have inline function in header file. you can not have declaration of inline function in header file and its body in cpp file. – user2641018 Sep 10 '14 at 05:32
  • 1
    As soon as you are using templates, your bold remark is impossible to do. – celtschk Sep 10 '14 at 08:07
  • @BethTanner No, equivalent of Java interface in C++ is pure abstract class (no member variables, all methods are pure virtual). Ideally .h file is the public API to a corresponding .cpp file, together they are similar to a single .java file (though C++ does not enforce this in any way, so programmer needs to have some discipline and know the language to avoid making a mess). – hyde Sep 10 '14 at 14:35