С Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 39, средняя оценка - 4.85
Ольга_1993
0 / 0 / 0
Регистрация: 09.02.2011
Сообщений: 25
#1

Файловый ввод/вывод - C++

09.02.2011, 17:43. Просмотров 5522. Ответов 15
Метки нет (Все метки)

Ребят, не могу никак понять файловый ввод вывод текстовой информации в с++. Знаю сто открытие через fopen, а как создать сам текстовый файл в самой с++, а потом его считать?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.02.2011, 17:43
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Файловый ввод/вывод (C++):

Заменить в программе, переводящую строку в двоичный код, консольный ввод/вывод на файловый ввод/вывод - C++
Добрый день! Помогите, пожалуйста, с программой. Программа считывает строку с клавиатуры и переводит её в двоичный код. затем наоборот...

Поменять консольный ввод-вывод на файловый ввод-вывод - C++
вот у меня калькулятор как мне сделать что б числа вводились из файла и результат записывался в новый файл ? // ОБРАТНАЯ...

Файловый ввод-вывод, ввод с клавиатуры и обработка массива структур - C++
Добрый вечер)) У меня небольшой вопрос. Почему первые буквы (в названии книг) не выводит на экран? Само задание: О каждой книге ...

Реализовать вывод массива объектов типа Student на консоль (файловый ввод/вывод) - C++
Как сделать чтобы список студентов выводился на экран в конце? #include<iostream> #include<stdio.h> #include<stdlib.h> ...

Поиск в массиве структур по заданному полю и вывод в алфавитном порядке (файловый ввод/вывод) - C++
Помогите с функцией void runFile() что бы с файла брал и выводил в алфавитном порядке список товаров, хранящихся больше месяца, стоимость...

Вывод суммы в файл (файловый ввод/вывод) - C++
Добрый день! Я пытался написать программу, которая должна вводить данные из файла №1, потом вычислять их сумму и полученное значение...

15
talis
792 / 544 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
09.02.2011, 18:24 #2
Давайте определимся, что вы хотите: C или C++. fopen() - это функция C. Прототип выглядит так:

C
1
FILE * fopen ( const char * filename, const char * mode );
filename - имя файла
mode - режим. Выглядит как C-строка (массив char с нуль-терминатором в конце). Может иметь значения:
"r"Чтение. Файл должен существовать.
"w"Запись с перезаписью. Если файл не существует, он создаётся.
"a"Запись с дописыванием в конец. Если файл не существует, он создаётся.
"r+"Чтение-запись. Файл должен существовать.
"w+"Чтение-запись с перезаписью. Если файл не существует, он создаётся.
"a+"Чтение-запись с дописыванием в конец. Если файл не существует, он создаётся.

Чтение в стиле C:

C
1
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
Чтение из stream элементов данных в количестве не более nmemb (каждый размером в size байт) в область памяти, указанную ptr;

Запись в стиле C:

C
1
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
Запись в stream элементов данных в количестве nmemb (каждый размером в size байт) из области памяти, указанной ptr;

Обе функции возвращают количество записанных данных.

Вот пример программы (используя вызовы C):

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <stdio.h>
 
void write( const char * fileName );
void read( const char * fileName );
 
int main()
{
    write( "test_file.txt" );
    read( "test_file.txt" );
 
    return 0;
}
 
void write( const char * fileName )
{
    const char * data = "Hello, world!"; //14 байт (учитывая 0x00 в конце)
    FILE * myFile = fopen( fileName, "w" );
 
    if( myFile == 0 )
    {
       printf( "Error opening %s for writing.\n", fileName );
       return;
    }
 
    int wrote = fwrite( data, sizeof(char), 14, myFile );
    printf( "Wrote %i bytes\n", wrote );
 
    fclose( myFile );
}
 
void read( const char * fileName )
{
    char data[255] = {0};
 
    FILE * myFile = fopen( fileName, "r" );
 
    if( myFile == 0 )
    {
       printf( "Error opening %s for reading.\n", fileName );
       return;
    }
 
    int read = fread( data, sizeof(char), 254, myFile );
    printf( "Read %i bytes:\n%s\n", read, data );
 
    fclose( myFile );
}
C-компилятор может не компилировать, я использовал C++-компиллер.

Но если вы хотите C++, используйте потоки файлового вывода-вывода (ifstream - ввод, ofstream - вывод, fstream - ввод и вывод). Подробнее тут: Чем отличается fstream от ofstream?

Удачи.
2
WinstonCherchil
7 / 7 / 0
Регистрация: 20.01.2011
Сообщений: 73
09.02.2011, 23:03 #3
Хорошо написал. Спасибо.
0
half-node
21 / 18 / 1
Регистрация: 12.08.2010
Сообщений: 206
11.02.2011, 04:01 #4
Подниму тему, дабы не плодить.
Разбираюсь в потоках.
Объясните пожалуйста, что не так в фукции read()?
write() пишет в файл все на ура. По крайней мере, размер файла соответствует тому, сколько объектов в него записано.
А вот чтение не проходит. Прям беда. Притом ошибка происходит уже после выполнения if(inFile.eof())
код, собственно:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
void Distance::write()
{
    ofstream outFile;
    outFile.open("DIST.DD", ios::trunc|ios::binary);
    if(!outFile)
    {cerr << "\nНевозможно открыть файл для записи данных.\n"; _getch(); exit(1);}
 
    for(int i=0; i<count; i++)
    {
        outFile.write((char*)(arrap[i]), sizeof(Distance));
    }
    if(!outFile)
    {cerr << "\nЗапись в файл невозможна.\n"; _getch(); exit(1);}
    outFile.close();
}
 
void Distance::read()
{
    ifstream inFile;
    inFile.open("DIST.DD", ios::binary);
    if(!inFile)
    {cerr << "\nНевозможно открыть файл для чтения данных.\n"; _getch(); exit(1);}
    int i=0;
    while(true)
    {
        arrap[i] = new Distance;
        inFile.read((char*)arrap[i], sizeof(Distance));
        if(inFile.eof())
            break;
        i++;
    }
    if(!inFile)
    {cerr << "\nНевозможно произвести чтение из файла.\n"; _getch(); exit(1);}
    inFile.close();
}
Уже даже не знаю что и думать. Где -то завис.
0
talis
792 / 544 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.02.2011, 11:36 #5
Так работает:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include <iostream>
#include <fstream>
#include <string.h>
 
using namespace std;
 
const int count = 15;
 
struct Distance
{
    int x, y;
}
* arrap[ count ];
 
 
void write()
{
    ofstream outFile;
    outFile.open("DIST.DD", ios::trunc|ios::binary);
    if(!outFile)
    {
        cerr << "\nCould not open for writing.\n";
        return;
    }
 
    for(int i=0; i<count; i++)
    {
            outFile.write((char*)(arrap[i]), sizeof(Distance));
    }
 
    if(!outFile)
    {
        cerr << "\nWrighting is impossible.\n";
        return;
    }
    outFile.close();
 
}
 
void read()
{
    ifstream inFile;
    inFile.open("DIST.DD", ios::binary);
 
    if(!inFile)
    {
        cerr << "\nCould not open for reading.\n";
        return;
    }
 
    int i=0;
    while(true) //тут бы так: while( i < count ), иначе рискуете схватить переполнение буфера.
    {
            arrap[i] = new Distance;
            memset( arrap[i], 0, sizeof(Distance) ); //если не прочитает - значения x и y будут == 0
            inFile.read((char*)arrap[i], sizeof(Distance));
 
            if(inFile.eof())
                break;
 
            i++;
    }
    if(!inFile)
    {
        cerr << "\nReading is impossible.\n";
        return;
    }
 
    inFile.close();
}
 
int main()
{
    for( int i = 0; i < count; i++ )
    {
        arrap[i] = new Distance;
        arrap[i]->x = 5; //инициализировать заведомо известными числами
        arrap[i]->y = 8; //инициализировать заведомо известными числами
    }
 
    write();
 
    for( int i = 0; i < count; i++ )
    {
        delete [] arrap[i];
    }
 
    read();
 
    cout << "\n-- Read data: ---------------------\n";
 
    for( int i = 0; i < count; i++ )
    {
        cout << arrap[i]->x << ';' << arrap[i]->y;
 
        if( arrap[i]->x == 5 && arrap[i]->y == 8 )
           cout << " - OK" << endl;
        else
           cout << " - FAIL" << endl;
 
        delete [] arrap[i];
    }
}
Ваша ошибка в том, что вы проверяете ( !inFile ). inFile будет == false в том числе, если установлен eof-bit. Открыт файл, или нет, проверяют с помощью ( inFile.is_open() == true )
1
4ance
1 / 1 / 0
Регистрация: 02.11.2010
Сообщений: 78
11.02.2011, 11:59 #6
Цитата Сообщение от WinstonCherchil Посмотреть сообщение
Хорошо написал. Спасибо.
присоединяюсь.
Файлы ещё не проходил, поэтому сразу сохранил себе этот пост
0
half-node
21 / 18 / 1
Регистрация: 12.08.2010
Сообщений: 206
11.02.2011, 15:07 #7
Цитата Сообщение от talis Посмотреть сообщение
Ваша ошибка в том, что вы проверяете ( !inFile ). inFile будет == false в том числе, если установлен eof-bit. Открыт файл, или нет, проверяют с помощью ( inFile.is_open() == true )
Спасибо большое! Почерпнул новой информации от Вас.
Но вот, крутил-крутил головой. В методе read(), фактически, ничего не поменялось, кроме дополнительного метода при чтении. (отдельное спасибо за него.) Почему же работает тогда? Я имею в виду, что такого поменялось, что код непосредственно чтения не изменился, но стал работать?
0
talis
792 / 544 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.02.2011, 15:13 #8
Да, собственно, ничего. Вы писали:

C++
1
2
3
4
5
6
7
8
if(!inFile)
{
    cerr << "\nНевозможно произвести чтение из файла.\n";
    _getch();
    exit(1); //это завершало программу преждевременно. Я просто вернул из функции.
               //кроме того, вторая такая проверка после цикла чтения (как и после цикла записи) избыточна
               //и не имеет смысла.
}
Старайтесь не пользоваться функцией exit(); Её часто применяют в игрушках. Знаете, когда игра вылетает без объяснений на середине сохранения, и пол-вечера игры псу под хвост? Вот это, скорее всего, оно. Когда винда прерывает игру - вы видите "Отправить отчёт - Не отправлять отчёт", а это именно игрушка вылетает. В функциях, в которых возможна ошибка - старайтесь возвращать либо bool (успешно/не успешно), либо int с кодом конкретной ошибки. Тогда вы сможете судить о том, что пошло не так, а не просто вылетать.
0
half-node
21 / 18 / 1
Регистрация: 12.08.2010
Сообщений: 206
11.02.2011, 15:23 #9
В общем я так понял, чтобы наверняка, нужно для начала вычислить (если файлу открывается уже после нового запуска программы, что обнуляет count), сколько объектов класса записано в файл. И делать цикл i<count
Иначе ничего не получается.
1
talis
792 / 544 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.02.2011, 15:30 #10
Да, так и нужно делать. Но не то, чтобы не получится... Понимаете, если вы например выделили память под массив из 5 int'ов - это 5 * 4 = 20 байт:

00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

И начали их читать, но прочитали 6 int'ов:

00 00 00 40 | 00 00 80 1A | 7F FF FF FF | F0 00 0A 13 | DE AD BE EF | 00 00 40 0D

Вы вылезете за пределы массива. Компилятор вам ничего не скажет. Вы либо схватите ошибку сегментации памяти - SEGFAULT, либо затрёте какую-то информацию, которая была на месте 5'го int'а.

Поэтому нужно точно знать, сколько байт вам нужно.
1
half-node
21 / 18 / 1
Регистрация: 12.08.2010
Сообщений: 206
11.02.2011, 16:00 #11
В общем, я даже не знаю что делать.
1 - записываю три объекта в файл. Каждый объект занимает 8 байт (4 инт, 4 флоат)
2 - на выходе получаю файл размером 24 байта.
3 - при чтении, проверяю, сколько объектов записано в файл и считываю их в цикле.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void Distance::read()
{
    ifstream inFile;
    inFile.open("DIST.DD", ios::in|ios::binary);
    if(!inFile)
    {cerr << "\nНевозможно открыть файл для чтения данных.\n"; return;}
    inFile.seekg(0,ios::end);
    int endpos = inFile.tellg();
    int num = endpos/sizeof(Distance);
    cout << "\nИдет чтение " << num << " записей.\n";
    for(int i=0; i<num; i++)
    {
        arrap[i] = new Distance;
        memset( arrap[i], 0, sizeof(Distance) );
        inFile.read((char*)arrap[i], sizeof(Distance));
    }
    if(!inFile)
    {cerr << "\nНевозможно произвести чтение из файла.\n"; return;}
    inFile.close();
}
Итог - "Невозможно произвести чтение из файла."
0
talis
792 / 544 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.02.2011, 16:04 #12
Ну правильно. Зачем-то после цикла считывания вы проверяете
C++
1
2
3
if(!inFile)
        {cerr << "\nНевозможно произвести чтение из файла.\n"; return;}
        inFile.close();
Во-первых, скажите зачем? Во-вторых, в конце чтения вы упираетесь в конец файла и выставляется бит eof (end-of-file). Проверка !inFile выполняется и вам выводится сообщение "Невозможно произвести чтение из файла". Уберите эту проверку вообще, она там не нужна. Лучше проверьте, что вы прочитали - скорее всего, данные будут верны.
0
half-node
21 / 18 / 1
Регистрация: 12.08.2010
Сообщений: 206
11.02.2011, 16:10 #13
Да, убрал, сразу же после того как написал. Считывание проходит, но забивается все нулями. Сразу ясно, что в целом что-то не то. Наверняка я ошибся много ранее, раз такое происходит.
В общем, вот весь код программы:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// 12_1.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <fstream>
#include <process.h>
#include <windows.h>
using namespace std;    
 
const int MAXARR = 100;
 
 
class Distance
{
private:
    int feet;
    float inches;
    static int count;
    static Distance* arrap[];
public:
    void getdata()
    {
        cin.ignore(10,'\n');
        cout << "Введите футы: "; cin >> feet;
        cout << "Введите дюймы: "; cin >> inches;
    }
 
        void putdata()
    {
        cout << "Feets: " << feet;
        cout << "Inches: " << inches;
    }
 
    static void add();
    static void write();
    static void read();
    static void display();
};
 
int Distance::count=0;
Distance* Distance::arrap[MAXARR];
 
 
void Distance::add()
{
    arrap[count] = new Distance;
    arrap[count++]->getdata();
}
 
void Distance::write()
{
    ofstream outFile;
    outFile.open("DIST.DD", ios::trunc|ios::binary);
    if(!outFile)
    {cerr << "\nНевозможно открыть файл для записи данных.\n"; return;}
 
    for(int i=0; i<count; i++)
    {
        outFile.write((char*)(arrap[i]), sizeof(Distance));
    }
    if(!outFile)
    {cerr << "\nЗапись в файл невозможна.\n"; return;}
    outFile.close();
}
 
void Distance::read()
{
    ifstream inFile;
    inFile.open("DIST.DD", ios::in|ios::binary);
    if(!inFile)
    {cerr << "\nНевозможно открыть файл для чтения данных.\n"; return;}
    inFile.seekg(0,ios::end);
    int endpos = inFile.tellg();
    int num = endpos/sizeof(Distance);
    cout << "\nИдет чтение " << num << " записей.\n";
    for(int i=0; i<num; i++)
    {
        arrap[i] = new Distance;
        memset( arrap[i], 0, sizeof(Distance) );
        inFile.read((char*)arrap[i], sizeof(Distance));
    }
    //if(!inFile)
    //{cerr << "\nНевозможно произвести чтение из файла.\n"; return;}
    inFile.close();
}
 
void Distance::display()
{
    for(int i =0; i<count; i++)
        arrap[i]->putdata();
}
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    char choice;
    while(true)
    {
        cout << "\nЧто? a/w/r/d/x/p: ";
        cin >> choice;
        switch(choice)
        {
        case 'a':
            Distance::add(); break;
        case 'w':
            Distance::write(); break;
        case 'r':
            Distance::read(); break;
        case 'd':
            Distance::display(); break;
        case 'x':
            exit(0);
        default:
            cout << "Неверный атрибут.\n";
        }
    }
 
    _getch();
    return 0;
}
0
talis
792 / 544 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.02.2011, 16:45 #14
Зачем в class Distance ваше Distance* arrap[]; ? Вы в объекте типа Distance храните указатели на объекты типа Distance, которые хранят указатели на объекты типа Distance, которые хранят указатели на объекты типа Distance, которые хранят указатели на объекты типа Distance... Чего вы пытаетесь этим добиться?

Добавлено через 7 минут
Я бы сделал так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class Distance
{
private:
        int feet;
        float inches;
public:
        void getdata()
        {
                cin.ignore(10,'\n');
                cout << "Введите футы: "; cin >> feet;
                cout << "Введите дюймы: "; cin >> inches;
        }
 
        void putdata()
        {
                cout << "Feets: " << feet;
                cout << "Inches: " << inches;
        }
 
        void setInches( float _inches ){ inches = _inches; };
        void setFeet( int _feet ){ feet = _feet ; };
 
        float getInches(){ return inches; };
        int getFeet(){ return feet; };
};
 
const int arrap_count;
Distance* arrap[ arrap_count ];
 
 
void write()
{
//...
   file.write( (char*)(arrap_count), sizeof(arrap_count) );
 
   for( int i = 0; i < arrap_count; i++ )
   {
      float inches = arrap[i]->getInches();
      int feet = arrap[i]->getFeet;
      file.write( (char*)(inches), sizeof(inches) );
      file.write( (char*)(feet), sizeof(feet) );
   }
//...
}
 
void read()
{
//...
   float inches
   int feet
   file.read( (char*)(inches), sizeof(inches) );
   file.read( (char*)(feet), sizeof(feet) );
   arrap[i]->setInches( inches );
   arrap[i]->setFeet( feet );
//...
}
Добавлено через 6 минут
А ещё лучше как-то так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
class Distance
{
private:
        int feet;
        float inches;
public:
        Distance( int feet, float inches ){ setFeet( feet ); setInches( inches ); };
 
        void getdata()
        {
                cin.ignore(10,'\n');
                cout << "Введите футы: "; cin >> feet;
                cout << "Введите дюймы: "; cin >> inches;
        }
 
        void putdata()
        {
                cout << "Feets: " << feet;
                cout << "Inches: " << inches;
        }
 
        void setInches( float _inches ){ inches = _inches; };
        void setFeet( int _feet ){ feet = _feet ; };
 
        float getInches(){ return inches; };
        int getFeet(){ return feet; };
};
 
list<Distance>arrap;
 
void write()
{
//...
   file.write( (char*)(arrap.size), sizeof(arrap.size) );
 
   list<Distance>::iterator it = arrap.begin();
 
   for( int i = 0; i < arrap.size; i++ )
   {
      float inches = (*it)->getInches();
      int feet = (*it)->getFeet;
      file.write( (char*)(inches), sizeof(inches) );
      file.write( (char*)(feet), sizeof(feet) );
      it++;
   }
//...
}
 
void read()
{
   
//...
   int size;
   file.read( (char*)(size), sizeof(size) );
 
   arrap.clear();
 
   for( int i = 0; i < size; i++ )
   {
      float inches;
      int feet;
 
      file.read( (char*)(inches), sizeof(inches) );
      file.read( (char*)(feet), sizeof(feet) );
 
      Distance dist ( feet, inches );
      arrap.push_back( dist );
   }
//...
}
1
half-node
21 / 18 / 1
Регистрация: 12.08.2010
Сообщений: 206
11.02.2011, 17:01 #15
Спасибо.
В Ваших случаях, для меня, пока-что много пробелов.
0
11.02.2011, 17:01
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.02.2011, 17:01
Привет! Вот еще темы с ответами:

Файловый ввод и вывод - C++
Посмотрел примеры сложения двух чисел на С++. Никак не пойму: где нужно создавать этот текстовый файл? Создал в папке, где проект, так...

Файловый ввод / вывод - C++
где я ошибся? #include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include &lt;fstream&gt; using namespace std; int...

Файловый ввод/вывод в С++ - C++
Здравствуйте не подскажите как организовать файловый ввод вывод в С++ Скажем есть файл 1 из него надо прочитать 2 переменные и записать...

файловый ввод-вывод - C++
посоветуйте пожалуйста какие нужно использавать функции для файлового ввода-вывода блоками данных (не строками а то строковые функции сами...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.