我写了下面的共享代码-作为练习-它编译时没有警告和错误,但是当我尝试运行它时,它似乎不工作,并且在崩溃前输出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
1条答案
按热度按时间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
去掉换行符。fscanf
将失败,如果(e。(g)该占领区内有空间,例如:Chief Executive Officer
1.将
MAX
作为计数传递给sort_users
和print_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.我添加了一些帮助宏来遍历数组(例如例如
FORUSERS
和FORALLUSERS
)。在上面的代码中,我使用了
cpp
条件来表示old与新代码:注意:这可以通过
unifdef -k
运行文件来清理。下面是我创建的
users.csv
:下面是程序创建的
students.csv
:下面是清理后的代码(通过
unifdef -k
运行):更新:
谢谢!你能告诉我更多关于这些宏的信息吗?这不是一个我熟悉的概念。- 吉斯瓦尔多
虽然有 * 很多 * 引用宏的参数,这里有一个: www.example.com
与[某些]汇编器中的宏不同,我们无法从C中获得一个 clean
.lst
文件来显示后处理的输出。但是,我们可以给予cc
和/或cpp
提供-E
和-P
选项来查看输出。但是,为了进行有意义的比较,我们需要对输入和输出文件进行大量的清理,以便
diff
具有一定的意义。下面是
diff
,它显示了FORUSERS
和FORALLUSERS
宏的扩展。作为奖金(?),我们也看到了MAX
宏的效果:要么进一步教育[或困惑];- )],下面是一个增强的示例:
1.在上面的例子中,列表的名称被 * 硬连接到宏中作为
ulist
。在下面的代码中,它现在是宏中的一个参数。1.我们使用并传递了 * 两个 * 变量:
ulist
和max
1.用户列表数组的最大计数 * 固定 * 为
MAX
(e.g. 100)1.如果我们创建一个“列表”
struct
(e.例如下面的ULIST
),我们可以将列表实现为可以增长到任何大小的动态数组。而且,我们可以完全消除MAX
。1.现在,我们只需要向函数传递一个 * 单一 * 参数[列表指针]。
1.作为使用这种动态列表的副产品,它消除了许多最初的问题。