Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Как лучше хранить текст в файлах


Автор: ZC1989 25.1.2007, 13:14
как лучше хранить текст в фалах набранный в прогу... я его после этого сохраняю во внешний файл, на данный момент храню в файле не ток текст но и некоторые параметры, что заставляет прибегать к синтаксису...

получется что-то вроде этого в файле
Код

REPORT{
    NAME       Какое-то_имя_человека
    TEXT         Тут_скажем_находится_набранный_им_текст
}


как видно из этого минимального примера, в место пробелов используется андерлайн... просто когда я читалкой прохожучь по файлу получаю "Какое-то_имя_человека" в переменную и заменяю на нормальные пробелы эти подчёркивания...

это сразу лишает возможности использовать "_" в тексте, если его даж и набрать, потом он будет заменён... вот как лучше такие файлы организовывать?

есть мысля, что не символы просто сохранять, а код этих символов, это как вообще, нормальная идея?

Автор: Anikmar 25.1.2007, 13:24
Можно сделать структурами.
Первая структура - заголовок файла
Потом структура списка людей.
При таком подходе - любые символы и служебная информация будут храниться без проблем

Автор: ip127001 25.1.2007, 13:41
struct+vector+fstream

проблема не совсем ясна... smile 
приведи конкредный пример ввода и нужного вывода

Автор: ZC1989 25.1.2007, 14:33
ip127001,  я хочу теоретически разобрать эту делему... потому что читаю немного разными способами...

строка может содеражть не только название (что бы быть уверенным в чтении) но и некоторые параметры

пример:
загаловок     текст    параметр1   параметр2

если скжет строка будет иметь вид

NAME    test    1    0

то тут всё пучком, text будет прочитано в строку, первый и второй паматры расшифруются (к примеру это мой enum) и всё будет работать как положено, но если будет записана строка

NAME    test bad    1    0

то тот же ifstream передаст в строку только text, в первый паметр bad а во второй 1, последний же параметр вообще пропадёт... для этого и пишу text_bad, что бы текстовая строка не разрывалась на 2 слова smile 

яснее объяснил проблем?

Автор: Anikmar 25.1.2007, 14:41
Я бы набросал все возможны типы данных, которые необходимо хранить в файле, и уже основываясь на этом списке разрабатывал проект формата файла.

Например, в файле могут быть соранены несколько параметров? содержащих имя и два int
Затем несколько параметров, содержащих имя и 3 int, неограниченное количество строк.

Тогда формат файла можно представить как-нибудь так:
int - Количество параметров 1-го типа
Массив структур для данных 1-го типа
int - Количество параметров 2-го типа
Массив структур параметров 2-го типа
int - Количество произвольных строк 
Массив строк

Либо универсальная структура, которая может содержать внутри себя все типы параметров (потребует больше памяти)
{
int Type;
int Param1;
int Param2;
int Param3;
char string[250];
}

В общем вариантов для раздумий уйма. Например, как лучше хранить строку (т.е. структуры переменного размера) и т.п.

Автор: ZC1989 25.1.2007, 14:48
Anikmar, получается что я должен буду как-то разобрать содержимое в строке, получается не совсем цикл к которому я привык... smile 
Цитата

Например, в файле могут быть соранены несколько параметров?


могут быть и больше, я пытаюсь универсальное сворганить детище..... может там ещё и дроби нужно будет и всякое такое... просто ед. оптимальным вариантом мне видится перевод символов в их кодировку и уже сохранение этой кодировки... к примеру получилось бы так

NAME    2321665361727217836763635623661231832736712    1    0

но в то же время не совсем уверен в правильности... а тот вариант что ты предложил мне кажется не оч практичным, если будет та же ерунда с "text bad" помоему, глюка даст это...  smile 

Автор: Anikmar 25.1.2007, 14:53
Тяжело что-то советовать не зная постановки задачи.

Какие данные надо сохранять?

Например, можно воспользоваться готовым ini файлом и забыть про парсинг...

Автор: KelTron 25.1.2007, 14:53
а можно в файле записать, например, так
Код

NAME    test bad;    1    0

и считывать так:
Код

string str;
getline(file, str, ';');
file >> par1;
file >> par2;

Вряд ли тебе в имени нужно хранить ';' поэтому его удобно использовать в качестве разделителя

Автор: Anikmar 25.1.2007, 15:02
Если файл планируется набирать вручную, то можно оставить текстовый формат.
А вот если файл создается из программы, то никакого смысла не вижу хранить тот же float в текстовом виде.

Автор: ip127001 25.1.2007, 15:02
Цитата(ZC1989 @  25.1.2007,  14:33 Найти цитируемый пост)
NAME    test    1    0

то тут всё пучком, text будет прочитано в строку, первый и второй паматры расшифруются (к примеру это мой enum) и всё будет работать как положено, но если будет записана строка

NAME    test bad    1    0

то тот же ifstream передаст в строку только text, в первый паметр bad а во второй 1, последний же параметр вообще пропадёт... для этого и пишу text_bad, что бы текстовая строка не разрывалась на 2 слова  

яснее объяснил проблем?

ок..теперь все понятно...можно попробывать ввести стоп-символы которые будут разграничевать
элементы строки...
пр.
Name|parameters..


ввод:
введите имя файла: 1.txt // ;жмешь ентер прога добавляет после имени стоп-символ(|)
и спомощью append добавляешь параметры....
у тя получиться стринговая переменная которая будет выглядеть примерно так
1.txt|1 2 3 213 3254 rgds trh
так ее в файл и кинешь
потом из файла считаешь и с опираясь на стоп символ раскидаешь строку....самый просто способ помоему...немного правда неэлегантный)) smile

Добавлено @ 15:03 
и будет тебе цикл)))

Добавлено @ 15:04 
Цитата(KelTron @  25.1.2007,  14:53 Найти цитируемый пост)
а можно в файле записать, например, так

Без подсветки    
1:    
NAME    test bad;    1    0    

и считывать так:

код C++    
1:    
2:    
3:    
4:    
string str;    
getline(file, str, ';');    
file >> par1;    
file >> par2;    

Вряд ли тебе в имени нужно хранить ';' поэтому его удобно использовать в качестве разделителя


во келтрон мене чуть опередил)

Автор: Voldemar2004 25.1.2007, 15:08
Строго не судите:
Код
#include <stdio>

#include <iostream>
#include <sstream>

class Class
{

std::stringstream buffer;

public:

void Add(char*);
std::string  Show(void);

};


void Class::Add(char *FileName)
{

FILE *in;

in = fopen(FileName, "rt");

   char Fam[100];
   char info[100];

        do
        {
        fscanf(in, "%s%s", &Fam, &info);
        buffer << Fam << " " << info << '\n';
        }
        while (!feof(in));

fclose(in);

}



std::string Class::Show(void)
{

return buffer.str();

}


int main()
{

Class My;

My.Add("D:\\Text");

std::cout << My.Show();

std::cin.get();

return 0;
}

Автор: Vyacheslav 25.1.2007, 18:39
Код

#include<iostream>
#include<iterator>
#include <algorithm>
#include <fstream>
#include<vector>

#pragma hdrstop
using namespace std;

struct MyClass {
    MyClass( string name, string text, int param1, int param2):
        name_(name), text_(text),param1_(param1), param2_(param2) {}
    MyClass(){}
    string name_;
    string text_;
    int param1_;
    int param2_;
};


ostream& operator<<( ostream& stream, const MyClass&  myClass)
{
    stream << myClass.param1_ << ' ';
    stream << myClass.param2_ << ' ';
    stream << myClass.name_.length() << ' ';
    stream << myClass.text_.length() << ' ';
    stream << myClass.name_ <<  myClass.text_;

    return stream;
}

istream& operator>>( istream& stream, MyClass&  myClass)
{
    int length1;
    int length2;
    stream >> myClass.param1_ >> myClass.param2_ >> length1 >> length2;
    if(!stream.eof()) {
        auto_ptr<char> tmp( new char[ length1 + length2 + 2 ]);
        stream.getline(tmp.get(), length1 + length2 + 2 );
        string str( tmp.get());
        myClass.name_ = str.substr(1,length1);
        myClass.text_ = str.substr(length1+1);
    }
    return  stream;
}

//---------------------------------------------------------------------------

#pragma argsused
int main(int argc, char* argv[])
{
    {
        vector<MyClass> v;
        v.push_back( MyClass("aaa1","bbb1 ccc1 ddd1", 1,1) );
        v.push_back( MyClass("aaa2","bbb2 ccc2 ddd2", 2,2) );
        v.push_back( MyClass("aaa3","bbb3 ccc3 ddd3", 3,3) );
        v.push_back( MyClass("aaa4","bbb4 ccc4 ddd4", 4,4) );

        // тестовый вывод на консоль
        copy(v.begin(),v.end(),ostream_iterator<MyClass>(cout,"\n"));

        //сохранение в файле
        ofstream os( "test.txt");
        copy(v.begin(),v.end(),ostream_iterator<MyClass,char>(os,"\n"));
    }
    {
     vector<MyClass> v;

     //чтение из файла
     ifstream is( "test.txt");
     copy(istream_iterator<MyClass,char>(is), istream_iterator<MyClass, char>(), inserter(v, v.begin()));

     // тестовый вывод на консоль
     cout << v.size() << endl;
     copy(v.begin(),v.end(),ostream_iterator<MyClass, char >(cout,"\n"));
    }

 }


Автор: VectorMan 25.1.2007, 18:57
можно использовать xml  smile 

Автор: Rockie 25.1.2007, 21:31
Цитата(VectorMan @  25.1.2007,  18:57 Найти цитируемый пост)
можно использовать xml  smile  

VectorMan, то, что доктор прописал smile

http://ru.wikipedia.org/wiki/XML


Автор: ZC1989 25.1.2007, 23:05
Rockie, дайте вам волю вы тут придёте ещё к HTML разметке... smile 

проблем в том что во первых я не горю желаением использовать символы для пробелов или разделения каких-то параметров от строк... - это черевато во первх не возможностью использовать этот символ, во вторых не практично просто...

тут некоторые сказали что использовать надо в конце ; - а если этот символ будет через пробел написан в тексте... получается ошибочная трактовка читалкой... smile 

Автор: bsa 25.1.2007, 23:13
Ты должен в читалке и писалке это учесть. Например, использовать обратный слеш для указания, что следующий за ним символ надо рассматривать, как символ, а не как конец строки:
Код
this is text\; text2 \\ end; param1; param2

Здесь текст будет иметь следующий вид (после декодирования): "this is text; text2 \ end"

Автор: ZC1989 25.1.2007, 23:27
bsa, но опять же остаётся возможно шибка... это катит не для всех вариантов... если, скажем, замутить это для хранения имён то да, а если для курсовухи по информатике...

Автор: bsa 25.1.2007, 23:38
Цитата(ZC1989 @ 25.1.2007,  23:27)
bsa, но опять же остаётся возможно шибка... это катит не для всех вариантов... если, скажем, замутить это для хранения имён то да, а если для курсовухи по информатике...

в чем проблема? Проблемный пример приведи.

Автор: Rockie 26.1.2007, 00:59
Цитата(KelTron @  25.1.2007,  14:53 Найти цитируемый пост)
getline(file, str, ';');

Шило на мыло. Получается что пробел нельзя а точку с запятой можно.

Цитата(ZC1989 @  25.1.2007,  23:05 Найти цитируемый пост)
тут некоторые сказали что использовать надо в конце ; - а если этот символ будет через пробел написан в тексте... получается ошибочная трактовка читалкой...  smile  

Цитата(ZC1989 @  25.1.2007,  14:48 Найти цитируемый пост)
могут быть и больше, я пытаюсь универсальное сворганить детище.....

ZC1989, так вы постепенно прийдете к xml smile

Цитата(ZC1989 @  25.1.2007,  14:33 Найти цитируемый пост)
то тут всё пучком, text будет прочитано в строку, первый и второй паматры расшифруются (к примеру это мой enum) и всё будет работать как положено, но если будет записана строка 
NAME    test bad    1    0
то тот же ifstream передаст в строку только text, в первый паметр bad а во второй 1, последний же параметр вообще пропадёт... для этого и пишу text_bad, что бы текстовая строка не разрывалась на 2 слова  smile  


Цитата(ZC1989 @  25.1.2007,  14:33 Найти цитируемый пост)
пример:загаловок     текст    параметр1   параметр2


заголовок[\n]
текст текст текст[\n]
параметр1[\n]
параметр2[\n]


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)