首页 > 解决方案 > 简化从文件读取的功能

问题描述

我想编写一个函数来简化 file_in.get 过程,这样我在读取文件时就不需要重复相同的行。但我在实施它时遇到了麻烦。我可以使用的唯一库是<iostream> <fstream> <cstring><cctype>我想象的功能将是这样的:

void Link_Info::Read_Pointer()
{    
    char temp[MAX]; 
    file_in.get(temp, MAX, '~'); 
    file_in.ignore(100, '~');
    array = new char [ strlen(temp) + 1];
    strcpy(array, temp);
}

void Link_Info::Load()
{
    ifstream file_in; 

    file_in.open("appt_info.txt");
    if (file_in) 
    {
        Read_Pointer(link_name);
        Read_Pointer(address);
        Read_Pointer(description);
    }
}

这就是我现在所拥有的:

void Link_Info::Load()
{
    ifstream file_in; 

    file_in.open("appt_info.txt");
    if (file_in) 
    {
        char temp[MAX]; 
        file_in.get(temp, MAX, '~'); 
        file_in.ignore(100, '~');
        link_name = new char [ strlen(temp) + 1];
        strcpy(link_name, temp);

        file_in.get(temp, MAX, '~'); 
        file_in.ignore(100, '~');
        address = new char [ strlen(temp) + 1];
        strcpy(address, temp);

        file_in.get(temp, MAX, '~'); 
        file_in.ignore(100, '~');
        description = new char [ strlen(temp) + 1];
        strcpy(description, temp);

        file_in.get(temp, MAX, '~'); 
        file_in.ignore(100, '~');
        misc = new char [ strlen(temp) + 1];
        strcpy(misc, temp);  


    }
    file_in.close();
}

标签: c++

解决方案


看起来你真的很亲近。以下是我会做的一些不同的事情:

// Define an exception to throw when the file cannot be read.
// If the file can't be read, you might as well pass the buck up the call 
// stack until it reaches a point that's capable of deciding what to do.
// This is a perfect time to use an exception 
class inv_file: public std::exception
{
public:
    const char* what() const noexcept
    {
        return "unable to parse input file";
    }
};

// Return the allocated string rather than passing it in.
// Passing in a pointer gets kinda tricky because while passing an object by pointer 
// is a form of pass by reference, the pointer itself is passed by value and won't 
// be updated if you change where it points inside the function. You have to pass the 
// pointer itself by reference. Just returning the pointer is less of a fuss.
char * Link_Info::Read_Pointer()
{    
    char temp[MAX]; 
    // always test for successful IO transaction. You do not want to use bad or 
    // incomplete data. The world is littered with programs that crash and computers 
    // enslaved by botmasters or otherwise twisted to the will of an attacker because 
    // this simple rule was not followed.
    if (file_in.get(temp, MAX, '~') &&
        file_in.ignore(100, '~'))
    { // successfully read up to a ~ and then ignored to the next ~
        // do what you did.
        array = new char [ strlen(temp) + 1];
        strcpy(array, temp);
        return array; // and return the result
    }
    throw inv_file(); // did not read expected data so we report the failure 
                      // in a way that cannot be easily ignored 
}

void Link_Info::Load()
{
    ifstream file_in; 

    file_in.open("appt_info.txt");
    if (file_in) 
    {
        link_name = Read_Pointer(); // accepts returned value. We don't have 
                                    // to worry about garbage because the exception 
                                    // thrown if the read failed is not caught.
                                    // it stops this function dead and the caller 
                                    // needs to deal with it or allow it to continue
                                    // back up the call stack.
        address = Read_Pointer();
        description = Read_Pointer();
    }
}

推荐阅读