我对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;
}
答案 0 :(得分:2)
分段错误可能是由于fopen
无法打开文件引起的。
您应始终测试此类故障并通过提示信息退出。
还请注意,如果文件确实是二进制文件,则应以二进制模式打开它,以避免换行符转换:
FILE *fp = fopen("students.db", "rb");
也将main
的原型更改为int main(int argc, char *argv[])
或简单地更改为int main()
。 char **argv[]
中的星星过多。
答案 1 :(得分:1)
您不必将我的答案标记为已接受,只想激发人们编写代码,使其可读性和安全性。在质量是一个重要因素的情况下,不要懒于编写这样的代码。
#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 %s\n", action);
exit(code);
}
printf("Succeeded to %s\n", action);
return ptr;
}
int handle_nonzero_error (int val, char *action, int code)
{
if(val != 0)
{
fprintf(stderr, "Failed to %s\n", action);
exit(code);
}
printf("Succeeded to %s\n", action);
return val;
}
int handle_negval_error (int val, char *action, int code)
{
if(val < 0)
{
fprintf(stderr, "Failed to %s\n", action);
exit(code);
}
printf("Succeeded to %s\n", 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: %ld\n", size);
printf("There are %ld students in the file", num_students);
}
int main (void)
{
make_arrays();
return EXIT_SUCCESS;
}