У меня есть тип данных, который принимает идентификатор и местоположение записи. Файл содержит около 1000 элементов, каждый из которых содержит идентификатор, имя, фамилию, средний балл (средний балл в каждом элементе 25 символов). Моя программа ищет 25 символов для каждого цикла, берет только идентификатор, помещает идентификатор и номер записи в таблицу и т. Д.

Затем пользователь вводит идентификатор, я извлекаю элемент из таблицы на основе данного идентификатора, после этого я получаю номер записи, ищу элемент в файле и затем читаю подробности.

Предоставляются заголовки классов recordlocation и arrayhashtable, некоторые элементы были удалены, чтобы сделать его короче

class  RecordLocation{
public:    
    RecordLocation(int idd = -1, int rno = -1);     
    void setId(int);
    int  getId();
    void setRNo(int);
    int getRNo();
    int Hash();    
    int LinearRehash(int initial_hash_value);           
private:
    int id;
    int r_no;
};

/

    typedef RecordLocation ItemType;
    class  ArrayHashTable{  //declares a class data type

    public:
        ArrayHashTable();//Fill info with null studnets
        Error_Code RetrieveItem(ItemType&  item, bool&  found);
        Error_Code InsertItem(ItemType  item);
        Error_Code DeleteItem(ItemType  item);
        void PrintAllItems();
    private:
        ItemType info[MAX_ITEMS];
        int items;
    };

/ data.txt сокращенная версия

4609:hhhhh    hhhhh   :2:4737:ggggg    ggggg   :4:5530:rrrrr    rrrr   :4:4849:ttttttt tttttttttt:2:5563:ddddd    dddd    :2:4959:aaaa    aaaaaaa  :4:

/

void main(){    
    char buffer[26] = { '0' };
    char id_buff[5];
    int id;
    ArrayHashTable object;
    RecordLocation temp;
    ifstream input("data.txt");
    if (!input){
        cout << "Unable to open file " << endl;
        exit(1);
    }

    int i = 0;
    int c;

//location 1    
    do{
        input.seekg(25 * i);
        input.read(id_buff, 4);
        id = convert(id_buff);

        temp.setId(id);
        temp.setRNo(i);
        object.InsertItem(temp);

        i++;

    }while (input);

//location 2        

    input.close();      
}

Что сбивает с толку, так это со следующим утверждением:

input.seekg(25 * 3);//3 is arbitrary
    input.read(buffer, 25);
    cout << buffer << endl;

Если он должен быть помещен в ячейку 1, то это нормальный вывод. Если он находится в ячейке 2, то на выходе будет 0. Если он одновременно в ячейке 1 и 2, то оба выхода нормальные.

Один из способов решить эту проблему - завершить выполнение оператора do while, а затем закрыть файл и открыть его снова, выполнить оператор, и все будет нормально. Но это не осознанное решение.

То, что я в основном говорю, это то, что я закончил читать файл, и после этого мне кажется, что я не могу извлечь из него больше информации. Я также не добавил эту часть, чтобы запросить у пользователя идентификатор (чтобы было проще)

Thy Gamosh

Ответов: 2

Ответы (2)

If any call to input.read fails, your program never notices, because you never check the return code of the read method. So we have to work out what happened, rather than seeing it. Fortunately, that's not too difficult in this case but in general you will find life to be easier if you get into the habit of checking for error returns.

We know that when Location 2 is reached, input's failbit is set. That must be true, because the while loop doesn't exit until input is false.

Since the failbit is set, neither the seekg nor the read do anything useful. The stream position is not modified, no data is read and the buffer is unmodified.

So when the program sends buffer to std::cout, what it is sending is whatever was previously in buffer. If the code shown is at Location 1, then the fourth record will still be in buffer. Otherwise, buffer will contain a single '0' followed by NULs, since it was initialized to that. (0 and '0' are not the same.)

That perfectly explains the observed behaviour. Before you do the seekg, you need to clear input's failbit.


In fact, the while loop is also incorrect. After the last entry is read, input will still be good, and the loop will repeat. The read will then fail, leaving id unmodified but since you don't check, the program wiil contnue, using the bogus id. Now 'input' is false and the parse fails.

What you need to do is exit the loop if either the read or the seekg fail. The explicit test of the boolean conversion of input is completely unnecessary and not useful because it comes too late.

Согласно cplusplus.com, для C ++ 98:

Если перед вызовом установлен флаг eofbit, функция не работает (устанавливает failbit и возвращает).

Итак, как только вы достигли конца файла, устанавливается бит EOF (конец файла), и его необходимо сбросить перед использованием этой функции.

Обратите внимание, что для C ++ 11:

Функция сбрасывает флаг eofbit, если он установлен перед вызовом.

Итак, вы можете попробовать более новый компилятор или сбросить флаг eof, используя clear, например: * 100004*

input.clear();

2022 WebDevInsider