- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在从一行读取 3 个字符串、移动到下一行并将它们正确放入我的结构中时遇到问题。
我的文本文件如下所示:
- John Johnson Math
- Eric Smith Biology
- etc
我需要按学生选择的类(class)来安排他们。我应该如何将第一个字符串读取为名称,然后读取空白,第二个字符串读取为姓氏,第三个字符串读取为类别,并对每一行执行此操作,然后正确存储在我的结构中?这是我现在拥有的:
#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';
}
}
最佳答案
继续评论,你为什么用链接列表来解决这个问题?您可以使用链表,但开销和代码复杂性超出了要求。一个直接的解决方案是 students
类型的简单动态数组。 。数组的好处还是显着的。直接访问所有学生,只需调用 qsort
即可简单排序,简单的添加等等。
不要误会我的意思,如果您的分配是使用链接列表,那么一定要这样做,但您确实应该查看 student
类型的动态数组。 ,您可以在哪里realloc
根据需要添加任意数量的学生。
例如:
#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;
}
(注意:如果您的数据文件确实不是以 '- '
开头,那么只需将其从 sscanf
格式字符串中删除即可)
输入示例
$ cat dat/studentclass.txt
- John Johnson Math
- Eric Smith Biology
- etc.
示例使用/输出
$ ./bin/structstudents <dat/studentclass.txt
students:
Johnson, John Math
Smith, Eric Biology
内存错误/检查
在您编写的动态分配内存的任何代码中,对于分配的任何内存块,您都有两个责任:(1)始终保留指向内存块起始地址的指针,因此,(2)可以在以下情况下释放它:不再需要它了。
您必须使用内存错误检查程序来确保您没有在分配的内存块之外进行写入,尝试读取或基于未初始化的值进行跳转,最后确认您已释放所有内存您分配的内存。
对于 Linux valgrind
是正常的选择。例如
$ valgrind ./bin/structstudents <dat/studentclass.txt
==14062== Memcheck, a memory error detector
==14062== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==14062== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==14062== Command: ./bin/structstudents
==14062==
students:
Johnson, John Math
Smith, Eric Biology
==14062==
==14062== HEAP SUMMARY:
==14062== in use at exit: 0 bytes in 0 blocks
==14062== total heap usage: 1 allocs, 1 frees, 5,400 bytes allocated
==14062==
==14062== All heap blocks were freed -- no leaks are possible
==14062==
==14062== For counts of detected and suppressed errors, rerun with: -v
==14062== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)
始终确认所有堆 block 均已释放 - 不可能发生泄漏并且同样重要错误摘要:0 个上下文中出现 0 个错误。
仔细检查一下,让我知道数组方法是否适合您的需求以及您是否有任何疑问。
排序依据class
成员(member)
为了对struct students
的数组进行排序通过class
,最简单的方法是使用qsort
功能。它是 C 库提供的标准排序函数(包括 stdio.h
)。您可以按students
中的任何成员进行排序结构。您甚至可以按类别和名称排序。
新程序员遇到的唯一问题是 qsort
正在编写 compare 函数以传递给 qsort
以便让它按所需的顺序排序。 compare 函数将接收指向 struct Student 数组中两个元素的指针。参数传递为 void *
(实际上是const void *
)。就像任何void
一样指针,您必须先将其转换为正确的类型,然后才能取消引用它。 (在本例中 students *
)因此,您只需要一个转换 void
的函数。指向students *
的指针并将值传递给 strcmp
。示例:
int compare (const void *a, const void *b)
{
return strcmp (((students *)a)->class, ((students *)b)->class);
}
唯一剩下的就是调用 qsort
(在代码中的fclose
之后):
qsort (array, idx, sizeof *array, compare);
然后您的输出将按类别排序。
如果您想按 last
进一步排序按 class
排序后的名称,而不是返回 strcmp
对于 class
,测试结果是否不等于 0,并返回该结果。如果strcmp
的结果上class
为零,那么你只需 return strcmp (((students *)a)->last, ((students *)b)->last);
这只是按class
排序首先,但如果类相同,则按 last
进一步排序。例如:
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
花时间学习qsort
.
关于c - 从文本文件中读取 3 个字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36902460/
如何使用 SPListCollection.Add(String, String, String, String, Int32, String, SPListTemplate.QuickLaunchO
我刚刚开始使用 C++ 并且对 C# 有一些经验,所以我有一些一般的编程经验。然而,似乎我马上就被击落了。我试过在谷歌上寻找,以免浪费任何人的时间,但没有结果。 int main(int argc,
这个问题已经有答案了: In Java 8 how do I transform a Map to another Map using a lambda? (8 个回答) Convert a Map>
我正在使用 node + typescript 和集成的 swagger 进行 API 调用。我 Swagger 提出以下要求 http://localhost:3033/employees/sear
我是 C++ 容器模板的新手。我收集了一些记录。每条记录都有一个唯一的名称,以及一个字段/值对列表。将按名称访问记录。字段/值对的顺序很重要。因此我设计如下: typedef string
我需要这两种方法,但j2me没有,我找到了一个replaceall();但这是 replaceall(string,string,string); 第二个方法是SringBuffer但在j2me中它没
If string is an alias of String in the .net framework为什么会发生这种情况,我应该如何解释它: type JustAString = string
我有两个列表(或字符串):一个大,另一个小。 我想检查较大的(A)是否包含小的(B)。 我的期望如下: 案例 1. B 是 A 的子集 A = [1,2,3] B = [1,2] contains(A
我有一个似乎无法解决的小问题。 这里...我有一个像这样创建的输入... var input = $(''); 如果我这样做......一切都很好 $(this).append(input); 如果我
我有以下代码片段 string[] lines = objects.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.No
这可能真的很简单,但我已经坚持了一段时间了。 我正在尝试输出一个字符串,然后输出一个带有两位小数的 double ,后跟另一个字符串,这是我的代码。 System.out.printf("成本:%.2
以下是 Cloud Firestore 列表查询中的示例之一 citiesRef.where("state", ">=", "CA").where("state", "= 字符串,我们在Stack O
我正在尝试检查一个字符串是否包含在另一个字符串中。后面的代码非常简单。我怎样才能在 jquery 中做到这一点? function deleteRow(locName, locID) { if
这个问题在这里已经有了答案: How to implement big int in C++ (14 个答案) 关闭 9 年前。 我有 2 个字符串,都只包含数字。这些数字大于 uint64_t 的
我有一个带有自定义转换器的 Dozer 映射: com.xyz.Customer com.xyz.CustomerDAO customerName
这个问题在这里已经有了答案: How do I compare strings in Java? (23 个回答) 关闭 6 年前。 我想了解字符串池的工作原理以及一个字符串等于另一个字符串的规则是
我已阅读 this问题和其他一些问题。但它们与我的问题有些无关 对于 UILabel 如果你不指定 ? 或 ! 你会得到这样的错误: @IBOutlet property has non-option
这两种方法中哪一种在理论上更快,为什么? (指向字符串的指针必须是常量。) destination[count] 和 *destination++ 之间的确切区别是什么? destination[co
This question already has answers here: Closed 11 years ago. Possible Duplicates: Is String.Format a
我有一个Stream一个文件的,现在我想将相同的单词组合成 Map这很重要,这个词在 Stream 中出现的频率. 我知道我必须使用 collect(Collectors.groupingBy(..)
我是一名优秀的程序员,十分优秀!