c - 段错误: 11 (C programming)

标签 c

我试图为登录程序编写代码,我必须使用 C 结构才能完成它。现在代码可以编译,但当用户输入用户名和密码时,我收到Segmentation error: 11

附加说明:代码在linux和windows上运行良好,但在unix环境下出现段错误。到目前为止我已经写了这个:

typedef struct {
    char username[20], password[20];
} DATA;

DATA user[10];
char iusername[20], ipassword[20];

DATA saveToStructforlogin(char* str) {
    DATA res;
    int flag = 0;
    int size;
    char *token = strtok(str, ";");

    while (token != NULL) {
        if (0 == flag) {
            strcpy(res.username, token);
        } else {
            strcpy(res.password, token);
        }
        flag++;
        token = strtok( NULL, ";" );
    }
    return res;
}

char *getUsername(DATA* arr, int size) {
    int i;
    for (i = 0; i < size; i++) {
        return arr[i].username;
    }
    return 0;
}

char *getPassword(DATA* arr, int size) {
    int i;
    for (i = 0; i < size; i++) {
        return arr[i].password;
    }
    return 0;
}

char *trimwhitespace(char *str) {
    char *end;

    // Trim leading space
    while (isspace((unsigned char)*str))
        str++;

    if (*str == 0)  // All spaces?
        return str;

    // Trim trailing space
    end = str + strlen(str) - 1;
    while (end > str && isspace((unsigned char)*end))
        end--;

    *(end+1) = 0;
    return str;
}

int main() {
    FILE *fp;
    char buffer[BUFFER_SIZE];
    int i = 0, flag = 0, a, status = 0;
    DATA arr[10];
    char *mUsername[10];
    char *mPassword[10];

    fp = fopen("admin.txt", "r");
    if (!fp) {
        return -1;
    }

    printf("Admin Login\n");
    printf("Username: ");
    scanf("%s", iusername);
    printf("Password: ");
    scanf("%s", ipassword);

    while (fgets(buffer, BUFFER_SIZE, fp)) {
        arr[flag] = saveToStructforlogin(buffer);
        mUsername[flag] = getUsername(arr, flag);
        mPassword[flag] = getPassword(arr, flag);
        if (strcmp(trimwhitespace(mUsername[flag]), iusername) == 0 &&
            strcmp(trimwhitespace(mPassword[flag]), ipassword) == 0) {
            status = 1;
            break;
        }
        flag++;
    }

    if (status == 1) {
        printf("Welcome to Admin Dashboard \n");
    } else {
        printf("Username or Password was wrong. please try again \n");
        main();
    }

    fclose(fp);
    return 0;
}

最佳答案

您的程序有多个问题:

  • 函数getUsernamegetPassword仅返回数组的第一个条目,如果为空则返回NULL。

  • 检查用户名和密码的循环太复杂。

    这是一个更简单的版本:

    while (fgets(buffer, BUFFER_SIZE, fp)) {
        DATA user = saveToStructforlogin(buffer);
        if (strcmp(user.username, iusername) == 0 &&
            strcmp(user.password, ipassword) == 0) {
                status = 1;
                break;
        }
    }
    
  • 函数saveToStructforlogin应该修剪文件中的字符串:

    DATA saveToStructforlogin(char* str) {
        DATA res = { 0 };
        char *token = strtok(str, ";");
    
        if (token != NULL) {
            strcpy(res.username, trimwhitespace(token));
            token = strtok(NULL, ";");
            if (token != NULL) {
                strcpy(res.password, trimwhitespace(token));
            }
        }
        return res;
    }
    
  • 递归调用 main 是不正确的。您应该使用 for(;;) 循环。

  • 返回结构是合法的,但不是一个很好的 API:它不允许正确的错误检测。

这是代码的简化和更正版本:

#include <ctype.h>
#include <stdio.h>
#include <string.h>

typedef struct {
    char username[20], password[20];
} DATA;

char iusername[20], ipassword[20];

char *trimwhitespace(char *str) {
    char *end = str + strlen(str);

    // Trim trailing space
    while (end > str && isspace((unsigned char)end[-1])) {
        *--end = '\0';
    }
    // Trim leading space
    while (isspace((unsigned char)*str)) {
        str++;
    }
    return str;
}

size_t bstrcpy(char *dest, size_t size, const char *src) {
    size_t len = strlen(src);
    if (len < size) {
        memcpy(dest, src, len + 1);
    } else
    if (size > 0) {
        memcpy(dest, src, size - 1);
        dest[size - 1] = '\0';
    }
    return len;
}

DATA *saveToStructforlogin(DATA *res, char* str) {
    char *token = strtok(str, ";");
    if (token != NULL) {
        bstrcpy(res->username, sizeof(res->username), trimwhitespace(token));
        token = strtok(NULL, ";");
        if (token != NULL) {
            bstrcpy(res->password, sizeof(res->password), trimwhitespace(token));
            return res;
        }
    }
    return NULL;
}

int main(void) {
    char buffer[1024];
    FILE *fp;
    int status;

    fp = fopen("admin.txt", "r");
    if (!fp) {
        return 1;
    }

    for (;;) {
        printf("Admin Login\n");
        printf("Username: ");
        if (scanf("%s", iusername) != 1)
            break;
        printf("Password: ");
        if (scanf("%s", ipassword) != 1)
            break;

        status = 0;
        rewind(fp);
        while (fgets(buffer, sizeof(buffer), fp)) {
            DATA user;
            if (saveToStructforlogin(&user, buffer)
            &&  !strcmp(user.username, iusername)
            &&  !strcmp(user.password, ipassword)) {
                status = 1;
                break;
            }
        }

        if (status == 0) {
            printf("Username or Password was wrong, please try again\n");
            continue;
        }
        printf("Welcome to Admin Dashboard \n");
        // handle the session here.
        break;
    }
    fclose(fp);
    return 0;
}

关于c - 段错误: 11 (C programming),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44871493/

相关文章:

c - 尝试读取文件时出现段错误 (C)

c - C 语言中的 'double pointer' 和 'returning pointer' 哪个更好?

c - 如果值包含 '&' 字符,则解析 POST 请求

c - haskell FFI传入和传出C结构数组

c - IPC FIFO 生产者-消费者死锁

c - Unix - C - 使用 exec 执行相同的程序

c - !! c 运算符,是两个 NOT 吗?

c - 需要帮助循环魔数(Magic Number)程序

c - 如何正确播种 mersenne twister RNG?

c - 从 CvPoint 获取 X Y 坐标