【发布时间】:2019-11-08 17:00:47
【问题描述】:
我是 C 的新手,来自 Python。我想将 .xyz 文件读入一个动态大小的数组,以便稍后在程序中用于各种计算。文件格式如下:
Title
Comment
Symbol 0.000 0.000 0.000
Symbol 0.000 0.000 0.000
....
前两行不是必需的,应该跳过。文件的“符号”部分是化学符号——例如H、Au、C、Mn——.xyz 文件格式用于存储原子的 3D 坐标。它们也需要被忽略。我对空格分隔的十进制数字感兴趣。因此,我想:
- 跳过前两行,或以某种方式忽略它们。
- 跳过每行的第一部分直到第一个空格。
- 将三列数字(坐标)存储在一个数组中。
到目前为止,我已经能够打开一个文件进行读取,然后我尝试检查文件的长度,以便根据需要存储多少坐标集来改变数组的大小.
// Variable declaration
FILE *fp;
long file_size;
// Open file and error checking
fp = fopen ("file_name" , "r");
if(!fp) perror("file_name"), exit(1);
// Check file size
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
rewind(fp);
// Close file
fclose(fp);
我已经能够使用fscanf(fp, "%*[^\n]") 跳过前两行,以跳到行尾。但是,我无法弄清楚如何循环遍历文件的其余部分,同时仅将十进制数字存储在数组中。
如果我理解正确,我需要为数组分配内存,使用类似malloc() 和file_size 的东西,然后使用fread() 将数据复制到数组中。
以下是实际 .xyz 文件内容的示例:
10 atom system
Energy: -914941.6614699
Ag 0.96834 1.51757 0.02281
Ag 0.96758 -1.51824 -0.02206
Ag -1.80329 2.27401 0.03179
Ag -3.58033 0.00046 0.00126
Ag -1.80447 -2.27338 -0.03537
Ag -0.96581 0.02246 -1.51755
Ag -0.96929 -0.02231 1.51463
Ag 1.80613 0.03321 -2.27213
Ag 3.58027 0.00028 0.00206
Ag 1.80086 -0.03407 2.27455
【问题讨论】:
-
使用
fgets逐行读取 -
带有
fseek和ftell的那个东西会给你字节 的文件大小,它几乎不告诉你有多少行,因此有多少坐标是你的三倍'将不得不阅读。 (您可能可以将它用作将有多少行的估计,方法是除以您设法确定的一些平均行长度,但由于您将不得不无论如何都要掌握动态分配和增长的东西,我建议现在跳过文件大小的确定。) -
fscanf(fp, "%*[^\n]")是一种从文件中读取行的不必要的麻烦、困难且容易出错的方法。只需使用fgets。 -
如果要分配正确的内存量(不使用
realloc),则需要计算文件中的行数(并减去2)。你可以使用fgets来做到这一点。然后分配内存,rewind文件,用fgets读取每一行。用sscanf从每一行提取xyz坐标。 -
一旦您的初步版本工作正常,您应该返回并重写盲目跳过前两行的代码。您应该让它检查前两行,如果它们不符合预期,请抱怨。迟早,有人会在错误类型的文件上运行您的程序,如果它盲目地阅读(没有注意到格式错误),这可能会导致神秘的失败。