C中的用户csv搜索(auth)

ghg1uchk  于 2023-07-31  发布在  其他
关注(0)|答案(1)|浏览(105)

我需要在.csv文件中进行身份验证,mi users.csv文件看起来像这样:

1,root,root,1
2,user,user,0

字符串
列表示[id,user,pass,isAdmin]
我需要的是在.csv行中搜索[user,pass]列,检查它是否等于用户输入的user和pass,顺便说一句,我是这样使用结构体的

我的代码

struct User {
    int id;
    char user[20];
    char password[20];
    bool isAdmin;
};


和这样的函数:

void getUser (struct User *currentUser, FILE *users) {
    char allUsers[100][20];
    char user[20];
    char password[20];
    printf("Gimme your username: ");
    scanf("%s", user);
    printf("Gimme your password: ");
    scanf("%s", password);

    char line[MAX_USER_ROW_LENGTH];
    while (fgets(line, sizeof(line), users)) {
        char *token = strtok(line, DELIMITER);
        char *token2 = strtok(line, DELIMITER);
        token2 = strtok(NULL, DELIMITER);
        while (token != NULL) {
            if ((strcmp(user, token) == 0) && strcmp(password, token2) == 0) {
                printf("user an pass correct");
                
                /**
                 * here goes the code that initialize the user, i plan to do something like, if the user and pass 
                 * are correct i would do something like this:
                 *      currentUser->id = id;
                 *      currentUser->user = user;
                 *      currentUser->password = password;
                 *      currentUser->isAdmin = 1 or 0
                 *      
                 * I just relize that i have no idea how to initialize the user, sorry :c
                 * */
            } else {
                printf("user and pass not found");
                return;
            }
            token = strtok(NULL, DELIMITER);
            token2 = strtok(NULL, DELIMITER);
        }
    }
}


我试过了
我已经使用函数strtok()来分隔逗号之间的每一行,但是,我只能比较用户名或密码,而不是每次迭代两次,(对不起,如果wile是空的,我试过的每一个丁,我做了ctrl+z,因为我在恐慌中输入)
一旦我检查了用户是否存在并可以进入,我应该将值传递给*currentUser,但我认为我可以做到这一点。
谢谢你的帮助??😀

p8ekf7hl

p8ekf7hl1#

1.当您将struct Userchar user[20]属性(即重复)这是一个提示,表明您的模型是不正确的。在本例中,我将该属性重命名为name
1.在结构定义中使用符号常量而不是魔术值。您可以随后在定义相关变量时使用这些常量。

  1. getUser()接口没有一个好的方法来告诉调用者查找是否成功。另一方面,我认为传入FILE *users而不是路径名是一个不错的选择。
    1.使用scanf()阅读字符串时,始终使用最大字段宽度,以避免缓冲区溢出。依赖于str2()宏的str()宏对此很方便。
    1.通常,将用户交互和应用程序逻辑分离是一个好主意。已将用户提示移动到main()
    1.(不固定)“给我”不是正确的英语。“用户?”和“密码?”“会是合适的提示我想你不是一个母语的人。
    1.您需要MAX_USER_ROW_LENGTH,因为您使用fget()。如果你使用getline(),它会为你分配一个合适的字符串。
  2. strtok()修改了它的输入,所以你不能在同一个输入上调用它两次。strpbrk()strchr()优于strtok()scanf()函数家族是解析文件的一种简洁方式。
#define _POSIX_C_SOURCE 200809L
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DELIMITER ','
#define FIELDS 4
#define NAME_LEN 19
#define PASSWORD_LEN 19
#define str(s) str2(s)
#define str2(s) #s

struct User {
    int id;
    char name[NAME_LEN+1];
    char password[PASSWORD_LEN+1];
    bool isAdmin;
};

struct User *getUser(FILE *users, const char *name, const char *password) {
    struct User *user = malloc(sizeof *user);
    if(!user) {
        perror("malloc");
        return NULL;
    }
    char *lineptr = NULL;
    size_t n;
    while(getline(&lineptr, &n, users) != -1) {
        int isAdmin;
        int rv = sscanf(lineptr,
            "%d,"
            "%" str(NAME_LEN) "[^,],"
            "%" str(PASSWORD_LEN) "[^,],"
            "%d",
            &user->id,
            user->name,
            user->password,
            &isAdmin
        );
        user->isAdmin = isAdmin;
        if(rv != FIELDS) {
            fprintf(stderr, "%d of %d fields read\n", rv, FIELDS);
            goto err;
        }
        if(
            !strcmp(name, user->name) &&
            !strcmp(password, user->password)
        ) {
            free(lineptr);
            return user;
        }
    }
err:
    free(lineptr);
    free(user);
    return NULL;
}

void printUser(struct User *user) {
    if(!user)
        return;
    printf(
        "id: %d, user: %s, password: %s, isAdmin: %d\n",
        user->id, user->name, user->password, user->isAdmin
    );
}

int main(void) {
    FILE *users = fopen("users.csv", "r");
    if(!users) {
        perror("fopen");
        return 1;
    }
    char name[NAME_LEN+1];
    printf("Gimme your username: ");
    scanf("%" str(NAME_LEN) "s", name);
    char password[PASSWORD_LEN+1];
    printf("Gimme your password: ");
    scanf("%" str(PASSWORD_LEN) "s", password);
    struct User *user = getUser(users, name, password);
    printUser(user);
    free(user);
    fclose(users);
}

字符串
和示例会话:

$ ./a.out
Gimme your username: root
Gimme your password: root
id: 1, user: root, password: root, isAdmin: 1
$ ./a.out
Gimme your username: root
Gimme your password: !root

相关问题