- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
所以我目前正在从事一个使用 txt 文件中的数据的项目。提示用户输入文件名,txt 文件的前两行是整数,主要包含 txt 文件的行值和列值。按照我的老师要求的方式编写这个程序时,有两件事让我感到困惑。对于标准,她说:
最左边的列是一个标识符,而该行的其余部分应被视为该行数据(浮点值)。该文件可能包含的示例是:
3
4
abc123 8.55 5 0 10
cdef123 83.50 10.5 10 55
hig123 7.30 6 0 1.9
我的代码:
//Creates array for 100 characters for filename
char fileName[100];
printf("Enter the file name to be read from: ");
scanf("%s", fileName);
FILE *myFile;
myFile = fopen(fileName, "r");
//Checks if file opened correctly
if (myFile == NULL)
{
printf("Error opening file\n"); //full file name must be entered
}
else {
printf("File opened successfully\n");
}
//gets value of records and value per records from file
//This will be the first 2 lines from line
fscanf(myFile, "%d %d", &records, &valuesPerRecords);
//printf("%d %d\n", records, valuesPerRecords); //Check int values from file
int counter = 0;
char *ptr_data;
ptr_data = (char*)malloc(records*(valuesPerRecords));
int totalElements = records*(valuesPerRecords);
/*If malloc can't allocate enough space, print error*/
if (ptr_data == NULL) {
printf("Error\n");
exit(-1);
}
int counter;
for (counter = 0; counter < totalElements; counter++){
fscanf(myFile, "%s", &ptr_data);
}
所以我想知道到目前为止,我是否在正确的轨道上。我似乎想不出一种方法将第一列作为字符串读入,而其余列作为整数读入。稍后我还必须使用存储的值并对它们进行排序,但这是以后的另一个问题。
最佳答案
首先,您的教授显然希望您熟悉在字符串(标签)和数字(浮点值)的集合中遍历指针) 使用指针算法 而不使用数组索引。扎实的指针熟悉度分配。
要处理标签,您可以使用指向 char 类型指针的指针(双指针),因为每个指针都将指向一个 char 数组。您可以按如下方式为标签声明和分配指针。 (假设您已经从输入文件中读取了 rows
和 cols
值)
char buf[MAXC] = "", /* temporary line buffer */
**labels = NULL, /* collection of labels */
**lp = NULL; /* pointers to walk labels */
...
/* allocate & validate cols char* pointers */
if (!(labels = calloc (rows, sizeof *labels))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1;
}
您可以为您的指针值做同样的事情,除了您只需要一个指向 double 类型的指针,因为您只需要分配一个 double 的集合。
double *mtrx = NULL, /* collection of numbers */
*p; /* pointers to walk numbers */
...
nptrs = rows * cols; /* set number of poiners required */
/* allocate & validate nptrs doubles */
if (!(mtrx = calloc (nptrs, sizeof *mtrx))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1;
}
指针 lp
和 p
的使用至关重要,因为您不能递增 labels
或 mtrx
(不保存原始地址)因为这样做会丢失指向分配给每个内存的开始的指针,立即导致内存泄漏(您无法释放该 block )并阻止您再次访问开始.每次您需要遍历 labels
或 mtrx
时,只需将起始地址分配给指针,例如
p = mtrx; /* set pointer p to mtrx */
lp = labels; /* set poiners lp to labels */
现在您可以自由地以您选择的任何方式读取和解析行,但我强烈建议使用line-oriented-input 函数将每一行读入临时行缓冲区,然后使用 sscanf
解析您需要的值。这比单独使用 fscanf
读取有很多优势。阅读每一行后,您可以在为字符串分配空间并分配值之前解析/验证每个值。
(注意:我在下面使用一个 sscanf
调用作弊,您实际上应该将一个 char*
指针分配给 buf
,请阅读label
,然后循环 cols
次(可能使用 strtok/strtod
)检查每个值并分配给 mtrx
, -- 留给你)
/* read each remaining line, allocate/fill pointers */
while (ndx < rows && fgets (buf, MAXC, fp)) {
if (*buf == '\n') continue; /* skip empty lines */
char label[MAXC] = ""; /* temp storage for labels */
double val[cols]; /* temp storage for numbers */
if (sscanf (buf, "%s %lf %lf %lf %lf", /* parse line */
label, &val[0], &val[1], &val[2], &val[3]) ==
(int)(cols + 1)) {
*lp++ = strdup (label); /* alloc/copy label */
for (i = 0; i < cols; i++) /* alloc/copy numbers */
*p++ = val[i];
ndx++; /* increment index */
}
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
然后只需再次循环这些值,根据需要使用或输出,然后释放
您分配的内存。你可以用类似的东西来做到这一点:
p = mtrx; /* reset pointer p to mtrx */
lp = labels; /* reset poiners lp to labels */
for (i = 0; i < rows; i++) {
printf (" %-10s", *lp);
free (*lp++);
for (j = 0; j < cols; j++)
printf (" %7.2lf", *p++);
putchar ('\n');
}
free (mtrx); /* free pointers */
free (labels);
这基本上是众多方法中的一种。将它们放在一起,您可以:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { MAXC = 512 }; /* constants for max chars per-line */
int main (int argc, char **argv) {
char buf[MAXC] = "", /* temporary line buffer */
**labels = NULL, /* collection of labels */
**lp = NULL; /* pointers to walk labels */
double *mtrx = NULL, /* collection of numbers */
*p; /* pointers to walk numbers */
size_t i, j, ndx = 0, rows = 0, cols = 0, nptrs = 0;
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;
}
while (fgets (buf, MAXC, fp)) /* get rows, ignore blank lines */
if (sscanf (buf, "%zu", &rows) == 1)
break;
while (fgets (buf, MAXC, fp)) /* get cols, ignore blank lines */
if (sscanf (buf, "%zu", &cols) == 1)
break;
if (!rows || !cols) { /* validate rows & cols > 0 */
fprintf (stderr, "error: rows and cols values not found.\n");
return 1;
}
nptrs = rows * cols; /* set number of poiners required */
/* allocate & validate nptrs doubles */
if (!(mtrx = calloc (nptrs, sizeof *mtrx))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1;
}
/* allocate & validate rows char* pointers */
if (!(labels = calloc (rows, sizeof *labels))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1;
}
p = mtrx; /* set pointer p to mtrx */
lp = labels; /* set poiners lp to labels */
/* read each remaining line, allocate/fill pointers */
while (ndx < rows && fgets (buf, MAXC, fp)) {
if (*buf == '\n') continue; /* skip empty lines */
char label[MAXC] = ""; /* temp storage for labels */
double val[cols]; /* temp storage for numbers */
if (sscanf (buf, "%s %lf %lf %lf %lf", /* parse line */
label, &val[0], &val[1], &val[2], &val[3]) ==
(int)(cols + 1)) {
*lp++ = strdup (label); /* alloc/copy label */
for (i = 0; i < cols; i++) /* alloc/copy numbers */
*p++ = val[i];
ndx++; /* increment index */
}
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
p = mtrx; /* reset pointer p to mtrx */
lp = labels; /* reset poiners lp to labels */
for (i = 0; i < rows; i++) {
printf (" %-10s", *lp);
free (*lp++);
for (j = 0; j < cols; j++)
printf (" %7.2lf", *p++);
putchar ('\n');
}
free (mtrx); /* free pointers */
free (labels);
return 0;
}
使用的示例输入文件
$ cat dat/arrinpt.txt
3
4
abc123 8.55 5 0 10
cdef123 83.50 10.5 10 55
hig123 7.30 6 0 1.9
示例使用/输出
$ ./bin/arrayptrs <dat/arrinpt.txt
abc123 8.55 5.00 0.00 10.00
cdef123 83.50 10.50 10.00 55.00
hig123 7.30 6.00 0.00 1.90
内存使用/错误检查
在您编写的任何动态分配内存的代码中,您对分配的任何内存块负有 2 个责任:(1) 始终保留指向起始地址的指针内存块,因此,(2) 它可以在不再需要时被释放。
您必须使用内存错误检查程序来确保您没有在分配的内存块之外/之外写入,尝试读取或基于未初始化的值进行跳转,最后确认您已释放所有你分配的内存。对于 Linux valgrind
是正常的选择。
$ valgrind ./bin/arrayptrs <dat/arrinpt.txt
==22210== Memcheck, a memory error detector
==22210== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==22210== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==22210== Command: ./bin/arrayptrs
==22210==
abc123 8.55 5.00 0.00 10.00
cdef123 83.50 10.50 10.00 55.00
hig123 7.30 6.00 0.00 1.90
==22210==
==22210== HEAP SUMMARY:
==22210== in use at exit: 0 bytes in 0 blocks
==22210== total heap usage: 5 allocs, 5 frees, 142 bytes allocated
==22210==
==22210== All heap blocks were freed -- no leaks are possible
==22210==
==22210== For counts of detected and suppressed errors, rerun with: -v
==22210== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)
始终确认所有堆 block 都已释放——不可能发生泄漏,同样重要的是错误摘要:0 个上下文中的 0 个错误。注意:一些操作系统没有提供足够的泄漏和错误抑制文件(将系统和操作系统内存排除在报告中的文件),这将导致 valgrind
报告一些内存还没有被释放(尽管你已经完成了你的工作并释放了你分配和控制的所有 block )。
检查一下,如果您有任何问题,请告诉我。
关于c - 使用 txt 文件中的指针在内存中存储和访问数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39431880/
我想做的是让 JTextPane 在 JPanel 中占用尽可能多的空间。对于我使用的 UpdateInfoPanel: public class UpdateInfoPanel extends JP
我在 JPanel 中有一个 JTextArea,我想将其与 JScrollPane 一起使用。我正在使用 GridBagLayout。当我运行它时,框架似乎为 JScrollPane 腾出了空间,但
我想在 xcode 中实现以下功能。 我有一个 View Controller 。在这个 UIViewController 中,我有一个 UITabBar。它们下面是一个 UIView。将 UITab
有谁知道Firebird 2.5有没有类似于SQL中“STUFF”函数的功能? 我有一个包含父用户记录的表,另一个表包含与父相关的子用户记录。我希望能够提取用户拥有的“ROLES”的逗号分隔字符串,而
我想使用 JSON 作为 mirth channel 的输入和输出,例如详细信息保存在数据库中或创建 HL7 消息。 简而言之,输入为 JSON 解析它并输出为任何格式。 最佳答案 var objec
通常我会使用 R 并执行 merge.by,但这个文件似乎太大了,部门中的任何一台计算机都无法处理它! (任何从事遗传学工作的人的附加信息)本质上,插补似乎删除了 snp ID 的 rs 数字,我只剩
我有一个以前可能被问过的问题,但我很难找到正确的描述。我希望有人能帮助我。 在下面的代码中,我设置了varprice,我想添加javascript变量accu_id以通过rails在我的数据库中查找记
我有一个简单的 SVG 文件,在 Firefox 中可以正常查看 - 它的一些包装文本使用 foreignObject 包含一些 HTML - 文本包装在 div 中:
所以我正在为学校编写一个 Ruby 程序,如果某个值是 1 或 3,则将 bool 值更改为 true,如果是 0 或 2,则更改为 false。由于我有 Java 背景,所以我认为这段代码应该有效:
我做了什么: 我在这些账户之间创建了 VPC 对等连接 互联网网关也连接到每个 VPC 还配置了路由表(以允许来自双方的流量) 情况1: 当这两个 VPC 在同一个账户中时,我成功测试了从另一个 La
我有一个名为 contacts 的表: user_id contact_id 10294 10295 10294 10293 10293 10294 102
我正在使用 Magento 中的新模板。为避免重复代码,我想为每个产品预览使用相同的子模板。 特别是我做了这样一个展示: $products = Mage::getModel('catalog/pro
“for”是否总是检查协议(protocol)中定义的每个函数中第一个参数的类型? 编辑(改写): 当协议(protocol)方法只有一个参数时,根据该单个参数的类型(直接或任意)找到实现。当协议(p
我想从我的 PHP 代码中调用 JavaScript 函数。我通过使用以下方法实现了这一点: echo ' drawChart($id); '; 这工作正常,但我想从我的 PHP 代码中获取数据,我使
这个问题已经有答案了: Event binding on dynamically created elements? (23 个回答) 已关闭 5 年前。 我有一个动态表单,我想在其中附加一些其他 h
我正在尝试找到一种解决方案,以在 componentDidMount 中的映射项上使用 setState。 我正在使用 GraphQL连同 Gatsby返回许多 data 项目,但要求在特定的 pat
我在 ScrollView 中有一个 View 。只要用户按住该 View ,我想每 80 毫秒调用一次方法。这是我已经实现的: final Runnable vibrate = new Runnab
我用 jni 开发了一个 android 应用程序。我在 GetStringUTFChars 的 dvmDecodeIndirectRef 中得到了一个 dvmabort。我只中止了一次。 为什么会这
当我到达我的 Activity 时,我调用 FragmentPagerAdapter 来处理我的不同选项卡。在我的一个选项卡中,我想显示一个 RecyclerView,但他从未出现过,有了断点,我看到
当我按下 Activity 中的按钮时,会弹出一个 DialogFragment。在对话框 fragment 中,有一个看起来像普通 ListView 的 RecyclerView。 我想要的行为是当
我是一名优秀的程序员,十分优秀!