C二进制文件工作不正常
我有一个问题。这是一个家庭作业,无法理解。这个简单的程序要求用户将其姓名和电话号码写入一个文件,如果它找到RDS电话号码ex(C二进制文件工作不正常,c,struct,C,Struct,我有一个问题。这是一个家庭作业,无法理解。这个简单的程序要求用户将其姓名和电话号码写入一个文件,如果它找到RDS电话号码ex(0*3*12415324),则将其所有者和电话号码写入一个二进制文件。 问题是程序没有将任何内容写入二进制文件(output.dat) 到目前为止,我做到了: #include <stdio.h> #include <stdlib.h> typedef struct { char name[50]; char tel[50];
0*3*12415324
),则将其所有者和电话号码写入一个二进制文件。
问题是程序没有将任何内容写入二进制文件(output.dat)
到目前为止,我做到了:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char name[50];
char tel[50];
} PERSON;
int main()
{
FILE *fin,*fout;
int n, i;
PERSON p[50];
fin = fopen("input.txt","rt");
fout = fopen("output.dat","wb");
fscanf(fin,"%i", &n);
for (i=0; i<n; ++i)
{
fscanf (fin,"%s%s", p[i].name, p[i].tel);
}
for (i=0; i<n; ++i){
if (p[i].tel[1]=='3'){
fwrite(p[i].name,sizeof(PERSON),n,fout);
fwrite(p[i].tel,sizeof(PERSON),n,fout);
}
}
fclose(fin);
fclose(fout);
return 0;
}
#包括
#包括
类型定义结构
{
字符名[50];
电话[50];
}人;
int main()
{
文件*fin,*fout;
int n,i;
人p[50];
fin=fopen(“input.txt”、“rt”);
fout=fopen(“output.dat”、“wb”);
fscanf(fin、%i、&n);
对于(i=0;i当我运行你的代码时,我得到一个segfault。运行揭示了问题
==75112== Invalid read of size 8
==75112== at 0x1001D0C5F: flockfile (in /usr/lib/system/libsystem_c.dylib)
==75112== by 0x1001D303C: fscanf (in /usr/lib/system/libsystem_c.dylib)
==75112== by 0x100000D42: main (test.c:21)
==75112== Address 0x68 is not stack'd, malloc'd or (recently) free'd
==75112==
==75112==
==75112== Process terminating with default action of signal 11 (SIGSEGV)
==75112== Access not within mapped region at address 0x68
==75112== at 0x1001D0C5F: flockfile (in /usr/lib/system/libsystem_c.dylib)
==75112== by 0x1001D303C: fscanf (in /usr/lib/system/libsystem_c.dylib)
==75112== by 0x100000D42: main (test.c:21)
fscanf
被传递了一个伪造的文件句柄,因为fopen
失败。在这种情况下,我没有input.txt
。请始终检查fopen
的结果。我使用包装器函数确保这种情况始终发生
#include <errno.h>
#include <string.h>
FILE *open_file(const char *filename, const char *mode) {
FILE *fp = fopen(filename, mode);
if( fp == NULL ) {
fprintf(stderr, "Could not open %s: %s.\n", filename, strerror(errno));
exit(errno);
}
return fp;
}
好的,触摸input.txt
并再次运行。再次执行另一个segfault.Valgrind
==75478== Conditional jump or move depends on uninitialised value(s)
==75478== at 0x100000D0F: main (test.c:32)
==75478==
==75478== Conditional jump or move depends on uninitialised value(s)
==75478== at 0x100000D91: main (test.c:36)
==75478==
==75478== Conditional jump or move depends on uninitialised value(s)
==75478== at 0x100000DB9: main (test.c:37)
前两个是关于n
,因为input.txt是空的,所以它没有初始化。本来应该填充它的fscanf
失败了,所以n
包含它开始时使用的任何垃圾。循环根据n
中的垃圾运行随机次数。它尝试从input.txt读取,但失败了p
未初始化,也包含垃圾
第三个错误是关于尝试读取p
n
中包含垃圾的垃圾,因此for循环尝试从未初始化的p
数组中读取
这一切都可以通过初始化n
和之前一样,检查fscanf
是否工作来解决。同样,包装函数确保检查错误
int scan_check(FILE *restrict stream, const char *restrict format, ...) {
va_list args;
va_start(args, format);
int ret = vfscanf(stream, format, args);
if( ret <= 0 ) {
fprintf(stderr, "Could not match input to '%s'.\n", format);
exit(errno);
}
return ret;
}
这说明fwrite
调用有问题
fwrite(p[i].name,sizeof(PERSON),n,fout);
fwrite(p[i].tel,sizeof(PERSON),n,fout);
这意味着要编写n
项,每个项的大小与PERSON
结构相同。如果您编写所有p
,这将很好。但您只编写一个姓名和一个电话号码。相反,您希望编写与字符串长度相等的字符,加上一个表示空字节的字符
fwrite(p[i].name, sizeof(char), strlen(p[i].name)+1, fout);
fwrite(p[i].tel, sizeof(char), strlen(p[i].tel)+1 , fout);
最后,综上所述,valgrind没有抱怨
int main()
{
int n = 0;
PERSON p[50];
FILE *fin = open_file("input.txt","rt");
FILE *fout = open_file("output.dat","wb");
scan_check(fin,"%i", &n);
for (int i=0; i<n; ++i)
{
scan_check(fin,"%s%s", p[i].name, p[i].tel);
}
for (int i=0; i<n; ++i){
if (p[i].tel[1]=='3'){
fwrite(p[i].name, sizeof(char), strlen(p[i].name)+1, fout);
fwrite(p[i].tel, sizeof(char), strlen(p[i].tel)+1 , fout);
}
}
fclose(fin);
fclose(fout);
return 0;
}
n
同样是不必要的。没有必要用input.txt
来告诉您有多少条记录,而是读取文件直到eof(fin)
。这避免了n
不准确。您必须检查所有系统调用的返回值。(如fopen、fwrite等)使用调试器或在代码的关键位置放置一些printf
s,以便查看发生了什么。顺便说一句:您的程序不会向用户询问任何问题。作为旁注,您的fwrite
的第二个和第三个参数毫无意义;p[i]。name
和p[i].tel
是50个字符的数组,而不是n
次PERSON
@altermann C没有将“rt”
定义为无效,而是未定义。在OP的平台上“rt”
可以很好地定义。C:\Users\zsombi\Desktop\Egyetem\Programozas II\Labor 3\RDSbinarisan\main.C | 42 |错误:应为“;”、“,”或“)'在'stream'| |===生成失败之前:1个错误,4个警告(0分钟,0秒))====我知道这个错误,但它不需要更改。@Zsombi抱歉,我不知道第42行是什么,但我想我知道发生了什么。我故意遗漏了一些包含,所以你不能直接剪切和粘贴。。。)
fwrite(p[i].name, sizeof(char), strlen(p[i].name)+1, fout);
fwrite(p[i].tel, sizeof(char), strlen(p[i].tel)+1 , fout);
int main()
{
int n = 0;
PERSON p[50];
FILE *fin = open_file("input.txt","rt");
FILE *fout = open_file("output.dat","wb");
scan_check(fin,"%i", &n);
for (int i=0; i<n; ++i)
{
scan_check(fin,"%s%s", p[i].name, p[i].tel);
}
for (int i=0; i<n; ++i){
if (p[i].tel[1]=='3'){
fwrite(p[i].name, sizeof(char), strlen(p[i].name)+1, fout);
fwrite(p[i].tel, sizeof(char), strlen(p[i].tel)+1 , fout);
}
}
fclose(fin);
fclose(fout);
return 0;
}
PERSON p;
....
for (int i=0; i<n; ++i)
{
scan_check(fin,"%s%s", p.name, p.tel);
if (p.tel[1]=='3'){
fwrite(p.name, sizeof(char), strlen(p.name)+1, fout);
fwrite(p.tel, sizeof(char), strlen(p.tel)+1 , fout);
}
}