我刚开始学习我的第一个C ++课程,而且我正在学习。该程序应该有3个不同的文件,一个头文件(prog1.h),一个prog1.cpp文件(不确定这个的正确术语)和一个包含main的测试文件:测试我们的程序(prog1_test.cpp) )。
不要求任何帮助(但是,我确定在我进入之后我会发布另一个问题),但是你想知道这个程序是什么应该这样做是为了理解我的问题。我们的程序应该从文件中读取一些数字并将这些数字放入2D数组中。然后它应该为每个数字值分配字符并打印当前数组和"图片"用角色创建。然后它将通过数组,确保每个数字的值与它的邻居的值不超过1,如果是,则程序将用其相邻的平均数替换该数字。值。然后程序将打印出这个校正过的数组和"图片"使用分配给更正数组的字符创建。
我知道头文件应该包含将在多个文件中使用的代码,但我很难弄清楚我的程序的哪些部分需要在这个文件中。例如,我的代码打开,读取和关闭数据文件是否包括在这里,或者没有,因为文件只被打开,读取和关闭一次?
答案 0 :(得分:6)
头文件包含函数和类声明。这些只是声明函数的名称,返回类型和参数列表。 .cpp文件包含这些函数的定义 - 即实际实现。如果您在其他文件中#include
,则头文件对程序的其余部分可见,但实现细节隐藏在.cpp文件中。
.cpp文件中声明/定义的任何不在.h文件中的内容对程序的其余部分是不可见的,因此您可以在.cpp文件中定义内部变量,辅助函数等,以及那些实现细节将不可见。我的示例中的foo()
就是一个例子。
你的程序的粗略草图将如下所示:
在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]);
在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
}
在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;
}
答案 1 :(得分:3)
使用各种头文件,以及与应用程序文件分开的代码/实现文件,以促进代码的可维护性和重用。通过在单个文件中收集所有相关的函数,变量和数据结构,我们可以防止在我们编写的每个后续应用程序中复制该代码。
以您的情况为例,您将开发与矩阵或数组相关的例程。此方案允许您将处理数组的常用例程收集到单个文件中,例如arrays.c
。现在,无论您编写多少程序,都有一个包含数组例程的公共文件。现在,如果你再编写5个需要你的数组例程的应用程序,你可以准备好进入arrays.c
。
为了可维护性,假设您现在有一种更有效的方法来处理从文件到阵列的输入。您无需返回并更新5个不同应用程序文件中的read_array
函数,只需更新read_array
中的一个arrays.c
函数,即可完成所有应用程序的更新例程。用它。
header
文件如何适应?为了在其他应用程序中使用您的数组函数,应用程序需要一种通用的方法来包含代码以使其可供使用。这是通过在每个需要它的应用程序中包含arrays.h
头文件来完成的。好的,那么arrays.h
中的内容以及arrays.c
中的内容是什么?您的标头文件将包含实现header files, function declarations, data structures and variables
中包含的function definitions
所需的数组例程的arrays.c
。这样,任何希望成为数组例程用户的应用程序只需在其文件开头包含行#include "arrays.h"
即可访问arrays.c
中包含的数组函数
一个例子(在C中)将有助于解决问题。假设您有几个数组函数将文本文件中的行读入字符串read_array
,打印行prn_array
,然后释放数组使用的内存和字符串free_array
。您已在array.c
中收集了数组函数。 (我们知道我们会在顶部包含array.h
。)所以,例如:
#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 */
}
现在让我们创建标题。我们收集了function declarations
以及所使用的任何variables
或data structures
,并且还包含system headers
以及included header files
中我们的功能所需的任何其他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 */
注意我们已将标头的内容包装在测试#ifndef MY_ARRAY_H
中,这只是询问编译器是否已定义MY_ARRAY_H
,ifndef
(如果没有定义),我们让编译器知道我们#define
之后的所有内容,直到我们到达#endif
的if语句MY_ARRAY_H
的末尾,这样如果另一个文件试图包含相同的标题 - 编译器知道它已经拥有它并且不需要再次包含它。 (不是必需的,但我们也会定义MY_ARRAY_H
值1
)
那么我们如何将自定义标头array.h
和我们的自定义函数用于处理arrays.c
中的数组以便为我们工作?我们编写了一个使用arrays.c
中的函数的应用程序,并在我们的应用程序中声明arrays.c
中的所有函数,我们只在应用程序中包含array.h
。 (下面称为application.c
):
#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;
}
编译application.c和array.c文件:
gcc -Wall -Wextra -o application application.c array.c
在任何短文本文件(少于100行)上运行
$ ./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!
现在,您可以看到创建一个单独文件的好处,该文件包含我们将使用的相关函数,变量和数据结构,并创建头文件。只需在我们的应用程序中包含头文件arrays.h
,我们就可以在任何我们喜欢的应用程序中重用该代码。我们可以在一个地方更新和维护所有数组函数,更新我们的arrays.c
将更新使用该代码的所有其他应用程序。
我知道我已经离开了很多,但要确保你对这些概念有所了解。它们是处理多个源文件的基础,包含在C / C ++中。
答案 2 :(得分:1)
以下基本内容应出现在您的标题文件中。
标题文件不应包含任何代码。