C 从文本文件中读取3个字符串

C 从文本文件中读取3个字符串,c,C,我很难从一行读取3个字符串,移动到下一行,并将它们正确地放入我的结构中 我的文本文件如下所示: - John Johnson Math - Eric Smith Biology - etc 我需要按学生选择的班级安排学生。我应该如何读取第一个字符串作为名称,然后是空白,第二个作为姓氏,第三个按类读取,并对每一行执行该操作,然后正确地存储在我的结构中?以下是我现在拥有的: #include <stdio.h> #include <stdlib.h> #define MAX

我很难从一行读取3个字符串,移动到下一行,并将它们正确地放入我的结构中

我的文本文件如下所示:

- John Johnson Math
- Eric Smith Biology
- etc
我需要按学生选择的班级安排学生。我应该如何读取第一个字符串作为名称,然后是空白,第二个作为姓氏,第三个按类读取,并对每一行执行该操作,然后正确地存储在我的结构中?以下是我现在拥有的:

#include <stdio.h>
#include <stdlib.h>
#define MAX 30

typedef struct students {
    char nameFirst[MAX];
    char NameLast[MAX];
    char choClass[MAX];
    struct students *next;
} Students;

int main() {
    FILE *in;
    Students *first = NULL, *New = NULL, *last = NULL, *old = NULL, *current = NULL;
    in = fopen("studenti.txt", "r");
    if (in == NULL)
    {
        printf("Cannot open file!\n");
        return 1;
    }
while (i = fgetc(in) != (int)(EOF))
{
    New = calloc(1, sizeof(Students));
    if (first == NULL)
        first = New;
    else
        last->next = New;

    j = 0;
    while (i != (int)(' '))
    {
        New->nameFirst[j++] = (char)i;
        i = fgetc(in);
    }
    New->nameFirst[j] = '\0';
}
}

继续评论,你为什么要用链表来解决这个问题?您可以使用链表,但开销和代码复杂性超出了要求。一个直接的解决方案是简单的动态类型学生数组。阵列或阵列的好处非常显著。直接访问所有学生,只需调用qsort即可进行简单排序,简单添加等

请不要误解我的意思,如果你的作业是使用链表,那你一定要这样做,但你应该真正考虑一个student类型的动态数组,在这里你可以根据需要重新定位,以添加尽可能多的学生

例如:

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

enum { MAXC = 30, MAXS = 60, MAXLN = 128 };

typedef struct students {
    char first[MAXC];
    char last[MAXC];
    char class[MAXC];
} students;

int main (int argc, char **argv) {

    students *array = NULL;
    size_t i, idx = 0, maxs = MAXS;
    char buf[MAXLN] = "";
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }

    /* allocate/validate maxs students in array */
    if (!(array = malloc (maxs * sizeof *array))) {
        fprintf (stderr, "error: virtual memory exhausted.\n");
        return 1;
    }

    while (fgets (buf, MAXLN, fp)) {    /* read each line into buf */
        /* separate in to struct members */
        if (sscanf (buf, "- %s %s %s", array[idx].first,
                    array[idx].last, array[idx].class) != 3)
            continue;

        if (++idx == maxs) {    /* check against current allocations */
            void *tmp = realloc (array, (maxs + MAXS) * sizeof *array);
            if (!tmp) {         /* valdate realloc array succeeded */
                fprintf (stderr, "error: realloc memory exhausted.\n");
                break;          /* or break and use existing data   */
            }
            array = tmp;        /* assign reallocated block to array */
            maxs += MAXS;       /* update current allocations size   */
        }
    }
    if (fp != stdin) fclose (fp);   /* close file if not stdin */

    printf ("\nstudents:\n\n");     /* output formatted data   */
    for (i = 0; i < idx; i++) {
        char tmp[2 * MAXC + 2] = "";
        strcpy (tmp, array[i].last);
        strcat (tmp, ", ");
        strcat (tmp, array[i].first);
        printf (" %-60s %s\n", tmp, array[i].class);
    }
    putchar ('\n');

    free (array);   /* free all allocated memory */

    return 0;
}
int compare (const void *a, const void *b)
{ 
    int r;
    if ((r = strcmp (((students *)a)->class, ((students *)b)->class)))
        return r;

    return strcmp (((students *)a)->last, ((students *)b)->last);
}
示例使用/输出

始终确认所有堆块都已释放-不可能发生泄漏,同样重要的错误摘要:0个上下文中的0个错误

请仔细查看,让我知道阵列方法是否适合您的需要,以及您是否有任何问题

按类成员排序

为了按类对struct student数组进行排序,最简单的方法是使用qsort函数。它是C库include stdio.h提供的标准排序函数。您可以按students结构的任何成员进行排序。您甚至可以按类和名称进行排序

新程序员使用qsort的唯一问题是编写传递给qsort的比较函数,以便按所需顺序进行排序。compare函数将接收指向struct student数组中两个元素的指针。传递的参数实际上是作为void*const void*传递的。就像任何空指针一样,必须将其强制转换为正确的类型,然后才能取消引用它。在本例中,students*因此,您只需要一个将void指针强制转换为students*并将值传递给strcmp的函数。例如:

int compare (const void *a, const void *b)
{ 
    return strcmp (((students *)a)->class, ((students *)b)->class);
}
剩下的就是在代码中fclose之后调用qsort:

qsort (array, idx, sizeof *array, compare);
然后按类对输出进行排序

如果您想在按类排序后按姓氏进一步排序,而不是在类的strcmp上返回,请测试结果是否不等于零,然后返回该结果。如果类上strcmp的结果为零,则只需返回strcmp students*a->last,students*b->last;这只是先按类排序,但如果类相同,则按最后一个进行进一步排序。例如:

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

enum { MAXC = 30, MAXS = 60, MAXLN = 128 };

typedef struct students {
    char first[MAXC];
    char last[MAXC];
    char class[MAXC];
} students;

int main (int argc, char **argv) {

    students *array = NULL;
    size_t i, idx = 0, maxs = MAXS;
    char buf[MAXLN] = "";
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }

    /* allocate/validate maxs students in array */
    if (!(array = malloc (maxs * sizeof *array))) {
        fprintf (stderr, "error: virtual memory exhausted.\n");
        return 1;
    }

    while (fgets (buf, MAXLN, fp)) {    /* read each line into buf */
        /* separate in to struct members */
        if (sscanf (buf, "- %s %s %s", array[idx].first,
                    array[idx].last, array[idx].class) != 3)
            continue;

        if (++idx == maxs) {    /* check against current allocations */
            void *tmp = realloc (array, (maxs + MAXS) * sizeof *array);
            if (!tmp) {         /* valdate realloc array succeeded */
                fprintf (stderr, "error: realloc memory exhausted.\n");
                break;          /* or break and use existing data   */
            }
            array = tmp;        /* assign reallocated block to array */
            maxs += MAXS;       /* update current allocations size   */
        }
    }
    if (fp != stdin) fclose (fp);   /* close file if not stdin */

    printf ("\nstudents:\n\n");     /* output formatted data   */
    for (i = 0; i < idx; i++) {
        char tmp[2 * MAXC + 2] = "";
        strcpy (tmp, array[i].last);
        strcat (tmp, ", ");
        strcat (tmp, array[i].first);
        printf (" %-60s %s\n", tmp, array[i].class);
    }
    putchar ('\n');

    free (array);   /* free all allocated memory */

    return 0;
}
int compare (const void *a, const void *b)
{ 
    int r;
    if ((r = strcmp (((students *)a)->class, ((students *)b)->class)))
        return r;

    return strcmp (((students *)a)->last, ((students *)b)->last);
}
示例输入

示例使用/输出


花点时间学习qsort。

您展示的代码看起来不像是真正的努力。你有没有试过读这个文件?无论如何?这里有很多例子,当然你可以比仅仅打开文件更进一步。或者至少尝试一下。我在试着让我,马克斯,进来!=intEOF对指针做了一些事情,但我从编译器那里得到了写访问冲突,我想我读错了…你最好创建一个学生数组并删除下一个指针。链接列表会不必要地使项目复杂化。fgets似乎是一个合理的开始。所以,一定要展示代码,并解释您在代码中遇到的问题。好的,这是我尝试一个字符一个字符地读取它的名字,显然我没有正确格式化它,oops:非常感谢,先生,不,我不必使用struct,我会按照您所说的做,并尝试完成它。这是一个很好的答案,对我来说,尤其是记忆部分。再次感谢大家!很乐意帮忙。每个人都需要一两个例子来开始。学习C的关键是放慢速度。有很多东西需要学习,而C提供的低级控制意味着由您来解释所使用的每一块内存。大多数其他语言在幕后处理内存管理会遇到很多麻烦,在C语言中,这取决于您。所以慢下来,花点时间去理解一个字符所使用的内存,然后是一个字符数组、一个结构、一个结构数组等等。你会做得很好的。我按照你说的做了这个列表,它工作得很好,我的问题是,我应该如何只按类的字母顺序排序,而不是按它们的名字排序?我应该使用什么函数?要按类排序,您将使用qsort。您需要编写一个比较函数来比较这些类。这可以通过int compare const void*a,const void*b{return strcmp students*a->class,students*b->class;}完成。然后只需调用qsort数组、idx、sizeof*数组、compare;在打印之前。非常感谢,我使用了i qsort,但没有比较函数,他只是对我的字符串排序,而不是列表。我知道我错过了什么。谢谢你,先生!
int compare (const void *a, const void *b)
{ 
    int r;
    if ((r = strcmp (((students *)a)->class, ((students *)b)->class)))
        return r;

    return strcmp (((students *)a)->last, ((students *)b)->last);
}
$ cat dat/studentclass.txt
- Wade Williams Biology
- John Johnson Math
- Eric Smith Biology
- etc.
$ ./bin/structstudents <dat/studentclass.txt

students:

 Smith, Eric                                                  Biology
 Williams, Wade                                               Biology
 Johnson, John                                                Math