#include <stdio.h>
#define TRUE 1
#define FALSE 0
typedef struct contact {
char firstname [40];
char lastname [40];
char address [100];
char phone[10];
}contact;
int main ()
{ FILE *pFile;
contact entry = {""};
int choice, firstname_flag = TRUE, lastname_flag = TRUE, address_flag = TRUE, phone_flag = TRUE;
pFile = fopen("C:\\contacts.txt", "a+");
if(!pFile){
printf("File could not be open.");
return 1;
}
do{
printf("Choose a selection:\n\n");
printf("1. First name:\n");
printf("2. Last name:\n");
printf("3. Address:\n");
printf("4. Phone number:\n\n");
scanf( "%d", &choice);
}while((choice < 1 || choice > 4));
switch (choice){
case 1:
firstname_flag = FALSE;
printf("Please enter first name: \n");
scanf("%s", &entry.firstname);
break;
case 2:
lastname_flag = FALSE;
printf("Please enter last name: \n");
scanf("%s", &entry.lastname);
break;
case 3:
address_flag = FALSE;
printf("Please enter address: \n");
scanf("%s", &entry.address);
break;
case 4:
phone_flag = FALSE;
printf("Please enter phone number: \n");
scanf("%s", &entry.phone);
break;
default:
break;
}
printf("\nYou will now be asked to enter the other items. \n\n");
if(firstname_flag){
printf("Please enter first name: \n");
scanf("%s", &entry.firstname);
}
if(lastname_flag){
printf("Please enter last name: \n");
scanf("%s", &entry.lastname);
}
if(address_flag){
printf("Please enter address: \n");
scanf("%s", &entry.address);
}
if(phone_flag){
printf("Please enter phone number: \n");
scanf("%s", &entry.phone);
}
fwrite (here)
fclose(pFile);
getchar();
return 0;
}
这是我到目前为止的代码。首先是有什么明显的说法是无效或错误的做法等吗?第二,我想写一个文件的名字,姓氏,地址和Phone#。我不确定我是否需要写入“入口”。另外,我注意到首先选择地址时,它几乎就像缓冲区不是空的,我放在空间后面即123 Park,Park将被错误地用作第一个名字而下一个我输入的条目将是Last名称。任何有关代码使用的建议和任何内容都将非常感激。再次感谢
答案 0 :(得分:1)
N°1。回应:“无效或错误的做法。”其中一些更有品味......
scanf
,请不要将其指向带有%s
的字符串缓冲区:使用%32s
到之类的内容指定缓冲区的长度(但可能不会消除)某人只是输入太多而导致程序崩溃(或更糟糕......) - 但是,请阅读下面的N°3以获取更多有关此问题的信息......
readline
是一个非常好的选择(但 GPL 不是 LGPL ,所以它不能用于“非自由”作品......){"", "", "", ""}
fwrite(entry)
吗?如果您在写入文件之前检查缺少的字段,您可能希望将标志库放在一边,而是循环“无效条件”。
while ('\0' == entry.firstname[0]) {
printf("Please enter first name: \n");
scanf("%40[^\r\n\0\04]", &entry.firstname[0]);
}
无需如此早地打开文件,并在等待用户交互时保持打开状态。以a+
模式打开文件是合理的“危险”(请参阅man lockf
了解),因为其他人可能会尝试写入文件;长时间以此模式打开会增加风险。
strerror(errno)
向用户提供失败的系统调用的详细信息,例如在检查fopen
,fwrite
和fclose
的返回代码时。由于缓存I / O的工作方式,fclose
甚至可以报告在某些情况下fwrite
发生的问题。stderr
... fprintf (stderr,
而不是输出流将您的错误消息打印到);
... prompt_for_field ("first name", &entry.firstname);
),检查缺失记录并提示它们的函数以及函数来分解这样的东西将记录写入文件,至少...... exit
的{{1}}的良好形式,而不是main
,例如使用return
/ exit(EXIT_SUCCESS)
。我相信这个想法是支持深奥和可能已经灭绝的系统,他们可能会将exit(EXIT_FAILURE)
以外的某些值视为成功的状态代码(也许是VMS?),但无论如何,它更容易阅读: - )< / LI>
N°2,是的,你可以0
,只要你永远不改变fwrite(entry)
的定义,你就应该能够完全阅读它。随着时间的推移,您可能希望切换到更“纯文本”类型的格式(struct contact
),但在这个小例子中,没有迫切需要引入这种复杂性。
最后,N°3,您应该使用#include <json-xml-init-religious-war>
来获取&entry.address[0]
的开头地址,但最重要的是: char[]
不会读取字符串。 看起来像<{1}} ,但它不是......
s匹配一系列非空白字符;下一个 指针必须是指向字符的指针 一个足够长的数组来保存输入序列和终止空字符('\ 0'), 这是自动添加的。输入字符串在空格或最大字段宽度处停止, 以先到者为准。
看到“非白空间?”那才是你的。输入的其余部分(在第一个空格之后)留在键盘缓冲区中,等待另一个scanf %s
读取它。从终端读取并接受空格的良好('ish)方式是printf %s
,将 40 替换为字符串缓冲区(scanf
)的大小。这意味着,接受(最多)40个字符,只要它们不是:回车符,新行,空字节或文件结束代码(%40[^\r\n\0\04]
)。
总而言之,你看起来是在正确的轨道上。祝你好运: - )