用printf循环到文件末尾 [英] loop to end of file with printf

查看:154
本文介绍了用printf循环到文件末尾的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,



我正在尝试循环浏览文本文件,这样我就可以按照重新排序的方式打印内容。我有以下代码,它工作正常,但是当涉及到fprintf我只能循环到固定数量的行,目前我的文本环境为16。有人可以帮助我循环到文件的末尾,因为我不知道如何。我不知道文本文件中会有多少行,但可能会有数十万行。



Hi Everyone,

I''m trying to loop through a text file so that I can print the content out in a re-ordered way. I have the following code, which works fine, however when it comes to fprintf I can only loop to a fixed number of rows, which is currently 16 for my text environment. Can someone help me loop to the end of the file as I don''t know how to. I don''t know how many lines will be in the text file, but can be in the hundreds of thousands.

// CProgtest.cpp : main project file.
#include <stdAfx.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
int main()
{
    char line[200];
    int i = 0;
    long NodeName[50];
    double x[50];
    double y[50];
    double z [50];

    FILE *pFile, *sacsout;
    pFile = fopen("ASASIN.txt", "r");
    //fgets gets a string from a file//one string per line
    while(fgets(line, sizeof line, pFile) != NULL)
    {
    if(sscanf_s(line, "%d %lf %lf %lf", &NodeName[i], &x[i], &y[i], &z[i]) == 4)
        {
            ++i;
        }
    }
    //Close the file


    if( (sacsout = fopen("Sacs1.inp", "w" )) != NULL )
    {
    }
    else
    {printf( "Problem creating SACS Output file\n");}

    for (i = 0; i < 16; i++)

    fprintf(sacsout,"%d %lf %lf %lf\n", NodeName[i], x[i], y[i], z[i]);
    /*{
    ++i;
    }    */
    fclose(pFile);
    fclose (sacsout);
}

推荐答案

除了Jochen在他的解决方案1中指出的,你的代码最大的问题是你正在缓冲目前50个固定大小的数组输入。这些是NodeName,x,y和z。只要这些阵列的固定容量为50,您将无法读取超过50行的文件。



解决方案是:首先确定文件中的行数。然后回到开头。现在使用new或使用std :: vector动态分配数组。最后再次读取文件并将行解析成阵列。



更好的是:使用上面的方法,但是这些变量进入一个结构然后分配一个数组这些结构,无论是new还是std :: vector< mystructure>。这简化了循环,并且您始终将所有数据都属于结构中的一个对象。这将简化您的程序扩展时的参数传递。



[修改]



好​​的,让我解释一下更详细一点。首先,我将定义一个包含单行所有数据的结构。例如:

Besides what Jochen pointed out in his solution 1, the biggest problem with your code is that you are buffering the input in various arrays of fixed size, 50 at the moment. These are NodeName, x, y, and z. As long as these array have a fixed capacity of 50 you will not be able to read files with more than 50 lines.

The solution to this is: First determine the number of lines in your file. Then go back to the beginning. Now allocate your arrays dynamically with new or by using std::vector. And finally read the file again and parse the lines into your arrays.

Better yet: Use the above approach, but these variables into a structure and then allocate an array of these structures, either with new or std::vector<mystructure>. That simplifies looping and you always have all data belong to one object in a structure. This will simplifiy argument passing when your program is being expanded.

[AMENDED]

Ok, let me explain a little more detailed. First I would define a structure that hold all the data of a single line. For example:
struct Node
{
   long name;
   double x, y, z;
};



要存储任意数量的此类结构,您可以使用STL向量。以下是您定义的方法:


To store an arbitrary number of such structures you could use an STL vector. Here is how you would define that:

#include <vector> // at the beginning of your .cpp file
...
std::vector<Node> nodes;



要访问第5个这样的节点,您只需编写:nodes [4]。当然,你必须告诉数组,它应该分配多少个节点存储。这是通过调用resize函数来完成的:


To access the 5th such node you would simply write: nodes[4]. Of course you have to tell the array, for how many nodes it should allocate storage. That is done by calling the resize function:

nodes.resize (1000);



这将分配1000个Node类型的结构。问题是,在读完整个文件之前,您还不知道需要多少个节点。您可以在读取文件的下一条记录之前调用resize,每次都使用比上一次更高的数字。另一种方法是使用push_back函数,该函数仅在数组的末尾附加一个结构。所以你的循环看起来像这样:


This would allocate 1000 structures of type Node. The problem is that you don''t know how many nodes you need until you have read the entire file. You could call resize before reading the next record of your file, each time with a number that is 1 higher than the previous time. Another way is to use the push_back function, which appends just one more structure to the end of the array. So your loop would look like this:

while (fgets(line, sizeof line, pFile) != NULL)
{
    Node newNode;
    int cntRead = sscanf_s(line, "%d %lf %lf %lf",
        &newNode.name[i], &newNode.x[i], &newNode.y[i], &newNode.z[i]);
    if (cntRead != 4)
    {
        ... output error message
        return -1; // line has illegal format
    }
    nodes.push_back (newNode);
}



读完整个文件后,您现在可以按任意顺序访问节点。例如,向后循环看起来像:


After having read the entire file you can now access your nodes in arbitrary order. For example a backwards loop would look like:

for (int idx = (int) nodes.size() - 1; idx >= 0; --idx)
{
    const Node& node = nodes[idx];
    // ... do something with node
}



我希望能让你知道如何继续。



BTW,如果你只想重新排序该文件中的行,您不必使用sscanf解析它。只需将文件的行存储在矢量中,必须如上所示,然后以相反的顺序输出这些行。我把它作为一个小练习留给你。


I hope that gives you an idea on how to proceed.

BTW, if you only want to re-order the lines in that file, you don''t have to parse it with sscanf. Simply store the lines of your file in a vector, must like shown above, and then output those lines in reverse order. I leave that as a little exercise for you.


当从文件中读取数据时,你使用变量 i 计算行数。因为你的缓冲区大小为50,你也应该在这里检查:

When reading data from the file, you are counting the lines using the variable i. Because your buffers have a size of 50, you should also check this here:
while( i < 50 && fgets(line, sizeof line, pFile) != NULL)
// Or better:
while( i < sizeof(x) / sizeof(x[0]) && fgets(line, sizeof line, pFile) != NULL)





但真正的问题是你正在重新使用 i 输出循环。只需使用另一个变量让 i 保持不变或保存行数:



But the real problem is that you are re-using i in the output loop. Just use another variable letting i unchanged or save the number of lines:

int nLines = i;
for (i = 0; i < nLines; i++)
    fprintf(sacsout,"%d %lf %lf %lf\n", NodeName[i], x[i], y[i], z[i]);


这篇关于用printf循环到文件末尾的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆