`进程返回-1073741819(0xC 0000005)`开始运行代码时出错

kknvjkwl  于 2023-04-29  发布在  其他
关注(0)|答案(1)|浏览(158)

我写了下面的共享代码-作为练习-它编译时没有警告和错误,但是当我尝试运行它时,它似乎不工作,并且在崩溃前输出Process returned -1073741819 (0xC0000005)错误。我试图寻找任何解释这种行为,虽然我没有成功地这样做;我还在学习,所以欢迎任何建议。此外,users.csv文件中的值可以是虚构的,但它们应该是以下形式:<identification number>;<movies watched>;<age>;<occupation>

/*
Write a program that takes in input a file with data relative to users from
a streaming site, loads them in memory in a structured type variable and, 
after having sorted them by age in ascending order, writes in a new file
the data relative to only the users that are students.
*/

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

const int MAX = 100;                // I wasn't able to use a preprocessor command (such as '#define MAX 100') | error: expected identifier or '(' before numeric constant | so I declared a constant global variable

typedef struct {
    int id, age, watched_movies;
    char occupation[30];
} USER[100];                        // can't initialize with MAX ( ==> cannot initialize arrays with variable sized elements)

//Written 'MAX' as 'max' to avoid variable shadowing and confusion in function building
void sort_users(USER* U, int max);
void print_students(USER* U, int max);

int main(void)
{
    FILE* usersPtr;

    if ((usersPtr = fopen("users.csv", "r")) == NULL) {
        puts("File 'users.csv' could not be opened.");
        exit(1);
    } else {
        USER U[100] = {{{0, 0, 0, ""}}};    // added braces to remove compiler warning
        for (int i = 0; i < MAX; ++i) {
            U[i]->id = 99999;
            U[i]->age = 0;
            U[i]->watched_movies = 0;
            strcpy(U[i]->occupation, "");
        }

        int i = 0;
        char string[60] = {""};
        char* strPtr;
        while (!feof(usersPtr)) {
            fscanf(usersPtr, "%s", string);

            strPtr = strtok(string, ";");
            U[i]->id = atoi(strPtr);

            strPtr = strtok(NULL, ";");
            U[i]->age = atoi(strPtr);

            strPtr = strtok(NULL, ";");
            U[i]->watched_movies = atoi(strPtr);

            strPtr = strtok(NULL, ";");
            strcpy(U[i]->occupation, strPtr);

            i++;
        }
        strPtr = NULL;

        sort_users(U, MAX);
        print_students(U, MAX);

        printf("%s", "The 'students.csv' file has been created and filled with the relevant pieces of information.\n");

        fclose(usersPtr);
        usersPtr = NULL;
    }
    return 0;
}

void sort_users(USER* U, int max)       // ("bubble sorting")
{
    for (int i = 0; i < max; ++i) {
        for (int j = max - 1; j != i; --j) {

            if (U[j]->age <= U[i]->age) {
                USER T[1] = {{{0, 0, 0, ""}}};                  // create a temporary array of structs (of 1 element)

                T[0]->id = U[i]->id;
                T[0]->age = U[i]->age;
                T[0]->watched_movies = U[i]->watched_movies;
                strcpy(T[0]->occupation, U[i]->occupation);

                T[i]->id = U[j]->id;
                T[i]->age = U[j]->age;
                T[i]->watched_movies = U[j]->watched_movies;
                strcpy(T[i]->occupation, U[j]->occupation);

                T[j]->id = U[0]->id;
                T[j]->age = U[0]->age;
                T[j]->watched_movies = U[0]->watched_movies;
                strcpy(T[j]->occupation, U[0]->occupation);
            }
        }
    }
}

void print_students(USER* U, int max)
{
    FILE* studentsPtr;

    if ((studentsPtr = fopen("students.csv", "w")) == NULL) {
        puts("File 'students.csv' could not be created.");
        exit(1);
    } else {
        for (int i = 0; i < max; ++i) {
            if (strcmp(U[i]->occupation, "student") == 0) {
                fprintf(studentsPtr, "%d,%d,%d,%s\n", U[i]->id, U[i]->age, U[i]->watched_movies, U[i]->occupation);
            }
        }
        fclose(studentsPtr);
        studentsPtr = NULL;
    }
}

users.csv示例:

1234;18;10;student
3253;22;3;sommelier
1;16;100;teacher
1743;50;5;retired
9654;28;18;student
8yoxcaq7

8yoxcaq71#

有几个问题..
1.你有一个typedef struct { ... } USER[100];
1.你想要:typedef struct { ... } USER;,因为之后你会:USER U[100]; You can't [well,_shouldn't] have both.
1.我想你对struct * 标量 *(单变量)和struct数组,并试图使 everything 成为某种数组。
1.你的循环使用feof来读取数据。这有问题。最后一行后还没停。这将导致segfault(您得到的错误),因为缓冲区只有 * 一个 * 令牌[来自上一次循环迭代的 unchanged 缓冲区],并且 * 第二个 * strtok调用将返回NULL
1.您正在使用fscanf读取缓冲区。最好使用fgets获取行,使用strcspn去掉换行符。

  1. fscanf将失败,如果(e。(g)该占领区内有空间,例如:Chief Executive Officer
    1.将MAX作为计数传递给sort_usersprint_students。这应该是i--读入的 * 实际 * 用户数。
    1.在你的sort函数中,你正在做:T[j]->id = U[0]->id .T只有一个元素,所以T[j]是未定义的行为(并导致第二个segfault)。(即)交换代码已损坏。
    1.在排序中,你正在向后迭代j。这可能是一个有效的排序方法,但我认为这是有问题的。
    1.您可以使用#define MAX 100
    这是更正后的版本。
    1.它标注了bug和修复。
    1.在改变了typedef [如上所述]后,我改变了所有(e.例如,将U[i]->id转换为U->id,因为我将U作为指向 current 元素的指针。
    1.我添加了一些帮助宏来遍历数组(例如例如FORUSERSFORALLUSERS)。
/*
Write a program that takes in input a file with data relative to users from
a streaming site, loads them in memory in a structured type variable and,
after having sorted them by age in ascending order, writes in a new file
the data relative to only the users that are students.
*/

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

#if 0
// NOTE/BUG: whatever error you got, it was _not_ from the #define
const int MAX = 100;                    // I wasn't able to use a preprocessor command (such as '#define MAX 100') | error: expected identifier or '(' before numeric constant | so I declared a constant global variable
#else
#define MAX     100
#endif

typedef struct {
    int id,
     age,
     watched_movies;
    char occupation[30];
#if 0
// NOTE/BUG: we do _not_ the typedef to define an _array_ of structs -- only a
// single instance
} USER[100];                            // can't initialize with MAX ( ==> cannot initialize arrays with variable sized elements)
#else
} USER;
#endif

// helper macros to loop through arrays of USER structs
#define FORUSERS(u_,lo_,hi_) \
    USER *u_ = &ulist[lo_];  u_ < &ulist[hi_];  ++u_
#define FORALLUSERS(u_) \
    FORUSERS(u_,0,max)

//Written 'MAX' as 'max' to avoid variable shadowing and confusion in function building
void sort_users(USER * U, int max);
void print_students(USER * U, int max);

int
main(void)
{
    FILE *usersPtr;
    int max = MAX;

    if ((usersPtr = fopen("users.csv", "r")) == NULL) {
        puts("File 'users.csv' could not be opened.");
        exit(1);
    }
    else {
#if 0
// NOTE/BUG: because of the original typedef, this defines 10,000 elements!
        USER userlist[100] = { {{0, 0, 0, ""}
            }
// NOTE/BUG: the compiler warnings are your _friend_
        }; // added braces to remove compiler warning
#else
        USER ulist[MAX];
#endif
        for (FORALLUSERS(U)) {
            U->id = 99999;
            U->age = 0;
            U->watched_movies = 0;
            strcpy(U->occupation, "");
        }

#if 0
        int max = 0;
        char string[60] = { "" };
#else
        char string[1000];
#endif
        char *strPtr;

#if 0
// NOTE/BUG: this does _not_ stop after the last line and causes a segfault
// on the strtok for id
        while (!feof(usersPtr)) {
            fscanf(usersPtr, "%s", string);
#else
        max = 0;
        while (fgets(string,sizeof(string),usersPtr) != NULL) {
            string[strcspn(string,"\n")] = 0;
#endif

            USER *U = &ulist[max];

            strPtr = strtok(string, ";");
            U->id = atoi(strPtr);

            strPtr = strtok(NULL, ";");
            U->age = atoi(strPtr);

            strPtr = strtok(NULL, ";");
            U->watched_movies = atoi(strPtr);

            strPtr = strtok(NULL, ";");
            strcpy(U->occupation, strPtr);

            max++;
        }
        strPtr = NULL;

#if 0
// NOTE/BUG: we must only pass the actual number of users read in
        sort_users(U, MAX);
        print_students(U, MAX);
#else
        sort_users(ulist, max);
        print_students(ulist, max);
#endif

        printf("%s", "The 'students.csv' file has been created and filled with the relevant pieces of information.\n");

        fclose(usersPtr);
        usersPtr = NULL;
    }

    return 0;
}

void
sort_users(USER *ulist, int max)            // ("bubble sorting")
{
    for (FORALLUSERS(Ui)) {
#if 0
// NOTE/BUG: while this may be valid, it is confusing [to me ;-)]
        for (int j = max - 1; j != i; --j) {
#else
        for (FORUSERS(Uj,(Ui - ulist) + 1,max)) {
#endif

#if 0
// NOTE/BUG: since I've changed the for loops, this test is reversed
            if (Uj->age <= Ui->age) {
                USER T[1] = { {{0, 0, 0, ""}
                    }
                };                      // create a temporary array of structs (of 1 element)
#else
            if (Uj->age > Ui->age) {
                USER T;
#endif

#if 0
// NOTE/BUG: this is a bit convoluted
                T[0]->id = Ui->id;
                T[0]->age = Ui->age;
                T[0]->watched_movies = Ui->watched_movies;
                strcpy(T[0]->occupation, Ui->occupation);

                T[i]->id = Uj->id;
                T[i]->age = Uj->age;
                T[i]->watched_movies = Uj->watched_movies;
                strcpy(T[i]->occupation, Uj->occupation);

// NOTE/BUG: T[j] goes beyond the end of T
                T[j]->id = U[0]->id;
                T[j]->age = U[0]->age;
                T[j]->watched_movies = U[0]->watched_movies;
                strcpy(T[j]->occupation, U[0]->occupation);
#else
                T = *Ui;
                *Ui = *Uj;
                *Uj = T;
#endif
            }
        }
    }
}

void
print_students(USER *ulist, int max)
{
    FILE *studentsPtr;

    if ((studentsPtr = fopen("students.csv", "w")) == NULL) {
        puts("File 'students.csv' could not be created.");
        exit(1);
    }
    else {
        for (FORALLUSERS(U)) {
            if (strcasecmp(U->occupation, "student") == 0) {
                fprintf(studentsPtr, "%d,%d,%d,%s\n",
                    U->id, U->age, U->watched_movies, U->occupation);
            }
        }
        fclose(studentsPtr);
        studentsPtr = NULL;
    }
}

在上面的代码中,我使用了cpp条件来表示old与新代码:

#if 0
// old code
#else
// new code
#endif

#if 1
// new code
#endif

注意:这可以通过unifdef -k运行文件来清理。
下面是我创建的users.csv

11111;23;5;Programmer
22222;37;6;Doctor
33333;43;7;Lawyer
44444;17;82;Student
55555;12;197;Student

下面是程序创建的students.csv

55555,12,197,Student
44444,17,82,Student

下面是清理后的代码(通过unifdef -k运行):

/*
Write a program that takes in input a file with data relative to users from
a streaming site, loads them in memory in a structured type variable and,
after having sorted them by age in ascending order, writes in a new file
the data relative to only the users that are students.
*/

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

#define MAX     100

typedef struct {
    int id,
     age,
     watched_movies;
    char occupation[30];
} USER;

// helper macros to loop through arrays of USER structs
#define FORUSERS(u_,lo_,hi_) \
    USER *u_ = &ulist[lo_];  u_ < &ulist[hi_];  ++u_
#define FORALLUSERS(u_) \
    FORUSERS(u_,0,max)

//Written 'MAX' as 'max' to avoid variable shadowing and confusion in function building
void sort_users(USER * U, int max);
void print_students(USER * U, int max);

int
main(void)
{
    FILE *usersPtr;
    int max = MAX;

    if ((usersPtr = fopen("users.csv", "r")) == NULL) {
        puts("File 'users.csv' could not be opened.");
        exit(1);
    }
    else {
        USER ulist[MAX];
        for (FORALLUSERS(U)) {
            U->id = 99999;
            U->age = 0;
            U->watched_movies = 0;
            strcpy(U->occupation, "");
        }

        char string[1000];
        char *strPtr;

        max = 0;
        while (fgets(string,sizeof(string),usersPtr) != NULL) {
            string[strcspn(string,"\n")] = 0;

            USER *U = &ulist[max];

            strPtr = strtok(string, ";");
            U->id = atoi(strPtr);

            strPtr = strtok(NULL, ";");
            U->age = atoi(strPtr);

            strPtr = strtok(NULL, ";");
            U->watched_movies = atoi(strPtr);

            strPtr = strtok(NULL, ";");
            strcpy(U->occupation, strPtr);

            max++;
        }
        strPtr = NULL;

        sort_users(ulist, max);
        print_students(ulist, max);

        printf("%s", "The 'students.csv' file has been created and filled with the relevant pieces of information.\n");

        fclose(usersPtr);
        usersPtr = NULL;
    }

    return 0;
}

void
sort_users(USER *ulist, int max)            // ("bubble sorting")
{
    for (FORALLUSERS(Ui)) {
        for (FORUSERS(Uj,(Ui - ulist) + 1,max)) {

            if (Uj->age > Ui->age) {
                USER T;

                T = *Ui;
                *Ui = *Uj;
                *Uj = T;
            }
        }
    }
}

void
print_students(USER *ulist, int max)
{
    FILE *studentsPtr;

    if ((studentsPtr = fopen("students.csv", "w")) == NULL) {
        puts("File 'students.csv' could not be created.");
        exit(1);
    }
    else {
        for (FORALLUSERS(U)) {
            if (strcasecmp(U->occupation, "student") == 0) {
                fprintf(studentsPtr, "%d,%d,%d,%s\n",
                    U->id, U->age, U->watched_movies, U->occupation);
            }
        }
        fclose(studentsPtr);
        studentsPtr = NULL;
    }
}

更新:

谢谢!你能告诉我更多关于这些宏的信息吗?这不是一个我熟悉的概念。- 吉斯瓦尔多
虽然有 * 很多 * 引用宏的参数,这里有一个: www.example.com
与[某些]汇编器中的宏不同,我们无法从C中获得一个 clean.lst文件来显示后处理的输出。但是,我们可以给予cc和/或cpp提供-E-P选项来查看输出。
但是,为了进行有意义的比较,我们需要对输入和输出文件进行大量的清理,以便diff具有一定的意义。
下面是diff,它显示了FORUSERSFORALLUSERS宏的扩展。作为奖金(?),我们也看到了MAX宏的效果:

1d0
< #define MAX       100
8,11d6
< #define FORUSERS(u_,lo_,hi_) \
<   USER *u_ = &ulist[lo_];  u_ < &ulist[hi_];  ++u_
< #define FORALLUSERS(u_) \
<   FORUSERS(u_,0,max)
18c13
<   int max = MAX;
---
>   int max = 100;
24,25c19,20
<       USER ulist[MAX];
<       for (FORALLUSERS(U)) {
---
>       USER ulist[100];
>       for (USER *U = &ulist[0]; U < &ulist[max]; ++U) {
59,60c54,55
<   for (FORALLUSERS(Ui)) {
<       for (FORUSERS(Uj, (Ui - ulist) + 1, max)) {
---
>   for (USER *Ui = &ulist[0]; Ui < &ulist[max]; ++Ui) {
>       for (USER *Uj = &ulist[(Ui - ulist) + 1]; Uj < &ulist[max]; ++Uj) {
79c74
<       for (FORALLUSERS(U)) {
---
>       for (USER *U = &ulist[0]; U < &ulist[max]; ++U) {

要么进一步教育[或困惑];- )],下面是一个增强的示例:
1.在上面的例子中,列表的名称被 * 硬连接到宏中作为ulist。在下面的代码中,它现在是宏中的一个参数。
1.我们使用并传递了 * 两个 * 变量:ulistmax
1.用户列表数组的最大计数 * 固定 * 为MAX(e.g. 100)
1.如果我们创建一个“列表”struct(e.例如下面的ULIST),我们可以将列表实现为可以增长到任何大小的动态数组。而且,我们可以完全消除MAX
1.现在,我们只需要向函数传递一个 * 单一 * 参数[列表指针]。
1.作为使用这种动态列表的副产品,它消除了许多最初的问题。

// Write a program that takes in input a file with data relative to users from
// a streaming site, loads them in memory in a structured type variable and,
// after having sorted them by age in ascending order, writes in a new file
// the data relative to only the users that are students.

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

// definition of user
typedef struct {
    int id,
     age,
     watched_movies;
    char occupation[30];
} USER;

// dynamic list of users
typedef struct {
    USER *data;                         // pointer to users in list
    int max;                            // number of users in list
} ULIST;

// helper macros to loop through arrays of USER structs
#define FORUSERS(u_,ul_,lo_,hi_) \
    USER *u_ = &ul_->data[lo_];  u_ < &ul_->data[hi_];  ++u_
#define FORALLUSERS(u_,ul_) \
    FORUSERS(u_,ul_,0,ul_->max)

void sort_users(ULIST *ulist);
void print_students(ULIST *ulist);
USER *ulistnew(ULIST *ulist);

int
main(void)
{
    FILE *usersPtr;

    if ((usersPtr = fopen("users.csv", "r")) == NULL) {
        puts("File 'users.csv' could not be opened.");
        exit(1);
    }

    // get an empty list
    ULIST *ulist = calloc(1,sizeof(*ulist));

    char string[1000];
    char *strPtr;

    while (fgets(string,sizeof(string),usersPtr) != NULL) {
        string[strcspn(string,"\n")] = 0;

        USER *U = ulistnew(ulist);

        strPtr = strtok(string, ";");
        U->id = atoi(strPtr);

        strPtr = strtok(NULL, ";");
        U->age = atoi(strPtr);

        strPtr = strtok(NULL, ";");
        U->watched_movies = atoi(strPtr);

        strPtr = strtok(NULL, ";");
        strcpy(U->occupation, strPtr);
    }
    strPtr = NULL;

    sort_users(ulist);
    print_students(ulist);

    printf("The 'students.csv' file has been created and filled"
    " with the relevant pieces of information.\n");

    fclose(usersPtr);
    usersPtr = NULL;

    return 0;
}

void
sort_users(ULIST *ulist)
{
    for (FORALLUSERS(Ui,ulist)) {
        size_t uidx = Ui - ulist->data;
        for (FORUSERS(Uj,ulist,uidx + 1,ulist->max)) {
            if (Uj->age > Ui->age) {
                USER T = *Ui;
                *Ui = *Uj;
                *Uj = T;
            }
        }
    }
}

void
print_students(ULIST *ulist)
{
    FILE *studentsPtr;

    if ((studentsPtr = fopen("students.csv", "w")) == NULL) {
        puts("File 'students.csv' could not be created.");
        exit(1);
    }

    for (FORALLUSERS(U,ulist)) {
        if (strcasecmp(U->occupation, "student") == 0) {
            fprintf(studentsPtr, "%d,%d,%d,%s\n",
                U->id, U->age, U->watched_movies, U->occupation);
        }
    }

    fclose(studentsPtr);
    studentsPtr = NULL;
}

USER *
ulistnew(ULIST *ulist)
{
    // get index of new element and increment the count of users
    int uidx = ulist->max++;

    // increase the size of the array of users
    ulist->data = realloc(ulist->data,sizeof(*ulist->data) * ulist->max);

    // fault out on no memory
    if (ulist->data == NULL) {
        perror("realloc");
        exit(1);
    }

    // point to the new entry
    USER *U = &ulist->data[uidx];

    return U;
}

相关问题