c - 使用C中的文本文件登录系统
问题描述
所以我的任务是创建一个登录系统。用户名和密码将与“account.txt”文件中的内容一起检查。内容是该文件的结构如下所示:
帐户 ID:1
姓名:John Lee
通行证:7uf
角色:学生
帐户 ID:2
名称:Park Lee
通行证:42h
角色:讲师
到目前为止,我得到了什么:
struct Account {
char name[20];
char pass[20];
};
void Login (char name[], char pass[]){
FILE *sc;
struct Account acc;
sc = fopen("Account.txt","r");
fscanf(sc,"\nName: %s",acc.name);
fscanf(sc,"\nPass: %s",acc.pass);
if(strcmp(name,acc.name) == 0 && strcmp(pass,acc.pass)) {
printf("Login successful");
}
else {
printf("Name or Pass incorrect");
}
fclose(sc);
}
int main () {
struct Account log[20];
fflush(stdin);
printf("\n\t\tEnter your name: ");
gets(log[20].name);
printf("\t\tEnter your password: ");
gets(log[20].pass);
Login(log[20].name,log[20].pass);
}
return 0; }
你们觉得我应该怎么做?
解决方案
在函数中:login()
代码需要在声明失败之前检查文件中的每个条目。毕竟,第一个条目可能不适合尝试登录的人
关于:
sc = fopen("Account.txt","r");
fscanf(sc,"\nName: %s",acc.name);
1) 始终检查 (!=NULL) 返回值 fromfopen()
以确保操作成功。
2)在尝试读取名称之前需要移过输入文件中每个条目的第一行
3) 当使用输入格式说明符 '%s' 和/或 '%[...]' 时,总是包含一个比输入缓冲区长度小 1 的 MAX CHARACTERS 修饰符,因为这些说明符总是将 NUL 字节附加到输入。这避免了缓冲区溢出和由此产生的未定义行为。
IE
if( !sc )
{
perror( "fopen failed" );
exit( EXIT_FAILURE );
}
{input first line of acct and discard}
if( fscanf(sc,"\nName: %19s",acc.name) != 1 )
{
// handle error
}
但是,如果输入文件中的那些行包含这些标签,例如Name:
那么代码还需要输入和丢弃这些标签,如上例所示。
这似乎是家庭作业,所以我非常不愿意只是“给”你适当的代码。我希望你的导师或助教能够帮助你了解代码应该做什么的细节。
关于以下陈述:
gets(log[20].name);
1)gets()
不再是 C 语言的一部分,你的编译器应该告诉你这一点。
2) 数组的有效索引范围为:0...(数组中的条目数 -1)。所以索引 20 超出了范围的末尾。建议只使用指向数组的指针。
3) 建议使用`fgets() 从文件中输入每一行。
4)您声明的结构不能很好地处理输入文件中的实际数据。
建议使用:
#define MAX_LOG_ENTRIES 20
int main( void )
{
struct Account acc[ MAX_LOG_ENTRIES ] = { "","" };
char dummy[128];
size_t i;
for( i = 0; i<MAX_LOG_ENTRIES; i++ )
{
if( i< MAX_LOG_ENTRIES && fgets( dummy, sizeof( dummy ), sc ) )
{ // then successfully read 'account' line
if( fgets( dummy, sizeof( dummy ), sc ) )
{ // then successfully read 'Name:` line
// remove trailing newline
dummy[ strcspn( dummy, "\n" )] = '\0';
// skip past Name: ' label
char * namePtr = strchr( dummy, ':' );
if( namePtr )
{ // then found the ':'
// step by ': '
namePtr += 2;
}
// extract name
strcpy( log[i].name, namePtr );
if( fgets( dummy, sizeof( dummy ), sc ) )
{ // then successfully read 'Pswd:` line
// remove trailing newline
dummy[ strcspn( dummy, "\n" )] = '\0';
// skip past Pswd: ' label
char * pswdPtr = strchr( dummy, ':' );
if( pswdPtr )
{ // then found the ':'
// step by ': '
pswdPtr += 2;
}
// extract password
strcpy( log[i].pswd, pswdPtr );
// read/discard unused data line
fgets( dummy, sizeof( dummy ), sc );
// read/discard unused blank line
fgets( dummy, sizeof( dummy ), sc );
}
当上述for()
循环退出时,所有记录都被读入命名数组log[]
,变量“i”包含数组“log[]”中实际使用的条目数
现在代码需要输入用户的两个字段(姓名和密码)
然后循环遍历数组log[]
,看看是否有“name+pswd”匹配。
如果 fgets( dummy, sizeof( dummy ), sc ); 找到匹配项,则成功,否则用户输入有效数据失败。
注意:上述代码无法检查错误和类似问题,包括输入文件是否包含少于 20 个条目。您应该能够添加错误(和 EOF)检查
推荐阅读
- haskell - 是否可以在 Rust 中表示高阶抽象语法?
- cakephp - CakePHP 3.x - 安装 Phinx 错误
- php - 如何在 Zend Framework 3 中声明全局常量?
- python - 如何在使用 angularjs ng-repeat 从 Bottle Framework 查询后显示数据?
- python-3.x - 添加到 BoxSizer 后如何调整面板(wxPython)的大小
- mybatis - 如何将两个结果列映射为要映射的键值
- spring-kafka - 恰好一次交付是否可以通过 spring-cloud-stream-binder-kafka 或 spring-kafka 使用哪一个
- python-3.x - 如何构建复杂的面向对象的 tkinter 程序
- r - 查找唯一元素的向量索引
- c# - devexpress 文本框搜索不起作用