我仍然是C语言的新手,我是第一次玩阅读文件。我的代码与以前的代码相似,该代码过去可以很好地运行,但是现在我遇到了问题。每次尝试运行此程序时,我都会不断收到错误Segmentation fault (core dumped)
。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct student {
char first[30];
char last[30];
char ssn[9];
};
void make_arrays() {
FILE *fp = fopen("students.db", "r");
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
long num_students = size / sizeof(struct student);
printf("There are %ld students in the file", num_students);
fclose(fp);
}
int main(int argc, char **argv[]) {
make_arrays();
return 0;
}
分割故障可能是由fopen
未能打开文件引起的。
您应始终测试此类故障并通过信息丰富的消息退出。
还要注意,如果文件确实是二进制文件,则应在二进制模式下打开,以避免线翻译结束:
FILE *fp = fopen("students.db", "rb");
还将main
的原型更改为int main(int argc, char *argv[])
或int main()
。char **argv[]
中的星星太多。
您不必将我的答案标记为接受,只是想激发人们编写代码,以便它可以阅读和安全。不要懒于在质量上写这样的代码。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
struct student /* Magic numbers everywhere */
{
char first[30];
char last[30];
char ssn[9];
};
void* handle_nullptr_error (void* ptr, char *action, int code)
{
if(ptr == NULL)
{
fprintf(stderr, "Failed to %sn", action);
exit(code);
}
printf("Succeeded to %sn", action);
return ptr;
}
int handle_nonzero_error (int val, char *action, int code)
{
if(val != 0)
{
fprintf(stderr, "Failed to %sn", action);
exit(code);
}
printf("Succeeded to %sn", action);
return val;
}
int handle_negval_error (int val, char *action, int code)
{
if(val < 0)
{
fprintf(stderr, "Failed to %sn", action);
exit(code);
}
printf("Succeeded to %sn", action);
return val;
}
/** This function is not guaranteed to be portable and work (but it will at least fail properly),
* because not all systems and/or library implementations support `SEEK_END` in files
* opened in text mode, as specified by @mode
* Moreover, in binary mode it will behave in an undefined manner, because different systems
* may store files data completely differently. In most cases it will succeed, just don't
* write code that crashes if not.
*/
long int get_file_charcount (const char *filename, char* mode)
{
FILE* fp = NULL;
long int fpSize = 0L;
/* Alignment for complicated function calls (for e.g where functions are passed as arguments) */
fp = handle_nullptr_error (fopen(filename, mode), "open file.", 1);
(void)handle_nonzero_error (fseek(fp, 0, SEEK_END), "seek end position.", 2);
fpSize = handle_negval_error (ftell(fp), "tell position.", 3);
fclose(fp); /* - May fail, as well */
return fpSize;
}
/** This function depends on POSIX headers and it is unix-conformant, although there are still
* some exceptions.
*
* Note that the value returned is the length of the contents of the symbolic link,
* and does not count any trailing null pads. The value is ought to be system-specific.
*/
_off64_t get_file_size (const char *filename)
{
struct stat st = {0};
(void)handle_negval_error(stat(filename, &st), "get file size.", (-1));
return st.st_size;
}
/** A validation function should first determine whether file's size is
* actually dividable by `sizeof(struct STUDENT_DESCRIPTION);`.
*
* Further more you can use `get_file_size()` as an alternative to
* `get_file_charcount()`. In the latter case, make sure you to specify the
* appropriate mode, "r" for text files and "rb" for binary files.
*/
void make_arrays ()
{
long int size = get_file_charcount("myfile.txt", "r");
long int num_students = size / sizeof(struct STUDENT_DESCRIPTION);
printf("size of file: %ldn", size);
printf("There are %ld students in the file", num_students);
}
int main (void)
{
make_arrays();
return EXIT_SUCCESS;
}