IPB
ЛогинПароль:

> Внимание!

1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным.
В описании темы указываем язык!!!

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

 
 Ответить  Открыть новую тему 
> stl vector, multiple definition error., C++\eclipse cdt 3.4.0
сообщение
Сообщение #1


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


/////

Сообщение отредактировано: Andrewshkovskii -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гость






Цитата
Смотрел я в стловском заголовке, нет там вектора с тем же названием. В чем проблема?
Проблема не в STL совсем... А в том, что в твоём проекте 2 разных CPP-файла подключают Realiz.H, и в итоге FileA получается определённым дважды. А этого делать нельзя...

Опиши FileA как внешнюю переменную в Realiz.H
#include <vector.h>
#include <string.h>
#include <windows.h>
/* GLOBAL VARIABLES GOES HERE*/
extern std::vector <std::string> FileA;
/*==========================================================*/

/*FUNCTIONS PROTOTYPE GOES HERE*/
std::vector<std::string> GetFileList(int argc, char *argv, std::vector<std::string>&);
/*==========================================================*/
, а само определение переменной FileA вынеси в любой из CPP-файлов...

 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


а можно как-нибудь обойтись без extern переменной, но решить проблему с мультивлючаймостью?
Я не вижу просто выхода из этой ситуации, кроме как последовать твоему совету.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гость






Цитата
можно как-нибудь обойтись без extern переменной, но решить проблему с мультивлючаймостью?
Нет... Для успешной сборки проекта переменная должна быть описана (declared) в каждой единице компиляции, т.е., в каждом файле, и определена (defined) только в одном месте. Другими средствами (кроме описания внешней переменной: extern) это недостижимо.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


Получается так, что мне надо в main.cpp и в realiz.h описать вектор как extern, а в realiz.cpp описать как обычно?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Гость






Цитата
мне надо в main.cpp и в realiz.h описать вектор как extern
Зачем описывать его еще и в main.CPP? Ты ж подключаешь там realiz.H... В этом-то и весь смысл, что в одном, заголовочном, файле переменная описывается как внешняя, и этот файл подключается ко всем CPP, в которых нужно описание переменной. А один CPP-файл мало того, что включает тот же header, так еще и содержит определение, то бишь выделение памяти под переменную. А потом уж линкер разруливает все это...

Иначе представляешь, что было бы, если б тебе в десятке-другом CPP-файлов пришлось добавлять extern-описание? smile.gif
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


Ну теперь то понятно, но всё равно, не работает..
в хидере как экстерн объявил, в файле реализации описал как подобает. Всё тоже самое. А если объявить и в хидере и в реализации как экстерн, то программа выполняется не корректно.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Гость






На самом деле при внимательном рассмотрении твоей программы выясняется, что
1) функция GetFileList написана неправильно: ты вторам параметром передаешь в нее char*, и тут же внутри этой функции обращаешься:
lstrcat(&(argv[1]),"\\*.txt");
, и что, по-твоему, это должно делать? Куда будет записываться результирующая строка? Ты ж весь стек себе испортишь...

2) тебе действительно не нужно extern-переменных... Все проще гораздо. Смотри:

realiz.h
#ifndef __REALIZ_H__
#define __REALIZ_H__

#include <vector>
#include <string>

/*FUNCTIONS PROTOTYPE GOES HERE*/
void GetFileList(int argc, char *argv, std::vector<std::string>& vect);

/*==========================================================*/

#endif /* VARS_H_ */



realiz.cpp
#include <iostream>
#include <windows.h>

#include "realiz.h"
using namespace std;

void GetFileList(int argc, char *argv, std::vector<std::string>& vect)
{
WIN32_FIND_DATA dFile;
HANDLE hFile;
std::string path;

if (argc < 2 || argc == 1) {
cout << "Not enought parametrs ";
exit(0);
}

char s[MAX_PATH] = "";
lstrcpy(s, argv); path = s;
lstrcat(s,"\\*.txt");

path += "\\";
hFile = FindFirstFile(s, &dFile);
if (hFile!=INVALID_HANDLE_VALUE) {
do {
vect.push_back(path + dFile.cFileName);
} while (FindNextFile(hFile,&dFile)!=0);
FindClose(hFile);
}
}

, и наконец, main.cpp:
#include <iostream>
#include <time.h>

#include "realiz.h"

using namespace std;

int main(int argc, char *argv[])
{
std::vector<std::string> FileA;
GetFileList(argc, argv[1], FileA); // передаешь локально описанную переменную по ссылке
for(unsigned int i = 0; i < FileA.size(); i++)
cout << FileA[i] << endl;
return 0;
}



Все работает...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


что, спасибо за советы. Но я опять к вас с вопросами и проблемами:) :
Переписал код, получилось вот что :
main.cpp :


#include <iostream.h>
#include <time.h>
#include <fstream.h>
#include "functions_interface.h"


int main(int argc, char *argv[])
{
std::vector<std::string> Paths;//массив путей к файлам
std::vector<std::string> Strings;//массив ЦЕЛЫХ строк из файлов.
GetFileList(argc,argv[1], Paths);//получение списка файлов по заданной маске в заданном каталоге

for(unsigned int i=0;i<Paths.size();i++)
Strings[i]=GetStringsFromFile(Paths,i);
for(unsigned int i=0;i<Strings.size();i++)
std::cout<<Strings[i];
return 0;
}



functions_realization.cpp :

std::string GetStringsFromFile (std::vector<std::string>& vect,unsigned int& i )
{

std::ifstream xfile(vect[i].data());//, std::ios::binary);
std::stringstream ss;
ss<<xfile.rdbuf();

return ss.str();

}


functions_interface.h :


#ifndef FUNCTIONS_INTERFACE_H_
#define FUNCTIONS_INTERFACE_H_
#include <vector.h>
#include <windows.h>
#include <string.h>
#include <fstream>
#include <sstream>

/*FUNCTIONS PROTOTYPE GOES HERE*/
// Получает список файлов по заданной маске
void GetFileList(int argc, char *argv, std::vector<std::string>& vect);

//Находит 5 самых длинных строк.
void Get_5_LargestStrings (std::vector<std::string>& vect);

//std::vector<std::string>& Strings);//получает ЦЕЛЫЕ строки из файлов
std::string GetStringsFromFile (std::vector<std::string>& vect, unsigned int& i );

//разделяет большую строку, на маленькие путем поиска символа '.'
std::vector<std::string> DevideStrings(std::string& xstr);

/*==========================================================*/

#endif /* FUNCTIONS_INTERFACE_H_ */



Программа крашиться при попытке обращения к вектор Strings. Почем? вроде бы и тип ф-ции string, и тип вектора такой же..Где-то переполнение идет??..
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Гость






Цитата
Программа крашиться при попытке обращения к вектор Strings. Почем?
Потому, что ты описать-то Strings описал, но памяти-то под него сколько-нибудь выделил? Одно дело, если б ты заполнял Strings с использованием push_back(), но ты же хочешь сразу начать присваивать значения конкретному элементу вектора? А чему равен его размер, перед тем, как ты делаешь в первый раз (да и не только в первый)
Strings[ i ] = GetStringsFromFile(Paths,i);
? Нулю... Отсюда и крах:
Цитата( Nicolai M. Josuttis: C++ STL)
The most important issue for the caller is whether these operations perform range checking. Only at() performs range checking. If the index is out of range, it throws an out_of_range exception (see Section 3.3). All other functions do not check. A range error results in undefined behavior. Calling operator [], front(), and back() for an empty container always results in undefined behavior


Сообщение отредактировано: volvo -
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


Доброго времени суток всем! Особенно volvo, потому что он он один разбирается во всем бреде, что я пищуsmile.gif)
В общем я опять пришёл за помощью. Программа, которую я пытаюсь написать, должна считывать из файлов строки.разбивать строки на предложения и для каждого из файлов найти 5 самых длинных предложений. Ну там ещё надо учитывать что бы время обработки было не менее 0.2с и пр. Но сейчас суть не в этом.
Вот исходники :
main.cpp :

#include <algorithm>
#include <iostream.h>
#include "functions_interface.h"

int main(int argc, char *argv[])
{
clock_t S, En, El;
std::string fname = NameGenerator(argv);
if (argc < 3)
{
cout << "Not enought parametrs or wrong files number ";
exit(0);
}
S = clock();
MainFunction(argv,fname);
En = clock();
El = En - S;
return 0;
}



functions_interface.h :


#ifndef FUNCTIONS_INTERFACE_H_
#define FUNCTIONS_INTERFACE_H_
#include <vector.h>
#include <windows.h>
#include <string.h>
#include <fstream>
#include <fstream.h>
#include <time.h>

/*FUNCTIONS PROTOTYPE GOES HERE*/
void GetFileList(char *argv[], std::vector<std::string>& vect);// Получает список файлов по заданной маске

std::string GetStringsFromFile(std::vector<std::string>& Paths, unsigned int &i);//получает ЦЕЛЫЕ строки из файлов

std::string Parser(std::string & s, char& devider);//разделяет большую строку на маленькие ,путем поиска делителя devider

unsigned int GetDividerCount(std::string &s, char& devider);//Возвращает кол-во разделителей в общей строке

bool comp(std::string s1, std::string s2); // предикат для сортировки вектора

void SaveResults(std::string fname, std::vector<std::string> &PS,
unsigned int &filecount, std::size_t &parsedst,
std::vector<std::string> &Paths);//Сохраняет результаты выполнения программы

void MainFunction(char *argv[], std::string &fname);

std::string NameGenerator(char *argv[]);//генерирует имена файлов в следующем формате : Result_N_H_M_S.txt,
//где N- кол-во использованных файлов,введенных при запуске, H,M,S - вермя запуска.

/*==========================================================*/

#endif /* FUNCTIONS_INTERFACE_H_ */




function_realization.cpp :


#include "functions_interface.h"
#include <windows.h>

void GetFileList(char *argv[], std::vector<std::string>& vect)
{
WIN32_FIND_DATA dFile;
HANDLE hFile;
std::string path;

char s[MAX_PATH] = "";
lstrcpy(s, argv[1]);
path = s;
lstrcat(s, "\\*.txt");

path += "\\";
hFile = FindFirstFile(s, &dFile);
if (hFile != INVALID_HANDLE_VALUE)
{
do
{
vect.push_back(path + dFile.cFileName);
} while (FindNextFile(hFile, &dFile) != 0);
FindClose(hFile);
}
}

std::string GetStringsFromFile(std::vector<std::string>& Paths, unsigned int &i)
{
std::string xstr;
std::ifstream xfile;
xfile.open(Paths[i].data(), std::ios::binary);
xfile.seekg(0, std::ios_base::end);
xstr.resize(xfile.tellg());
xfile.seekg(0, std::ios_base::beg);
//копируем данные
char mychar[xstr.size()];
xfile.read(mychar, xstr.size());
xfile.close();
xstr = mychar;
return xstr;
}

unsigned int GetDividerCount(std::string &s, char& devider)
{
int count = 0;
for (unsigned int i = 0; i < s.size(); i++)
if (s.at(i) == devider)
count++;
return count;
}

std::string Parser(std::string &s, char& devider)
{
std::string bufs;
int n = s.find('.');
bufs.append(s, 0, n);
s.erase(0, n + 1);
return bufs;
}

bool comp(std::string s1, std::string s2)
{
return s1.size() > s2.size();
}

void MainFunction(char *argv[], std::string& fname)
{
std::vector<std::string> Paths;//массив путей к файлам
std::string String;//целая строка из файла
std::vector<std::string> PS;// вектор разбитых строк
char d = '.';//разделитель предложений
std::size_t parsedst = 0;//кол-во обработанных строк
unsigned int dcount = 0;//кол-во разделителей в файле определяет кол-во предложений в файле.
GetFileList(argv, Paths);
unsigned int filecount = atoi(argv[2]);//кол-во файлов, задается как 2ой параметр при запуске
for (unsigned int i = 0; i < filecount; i++)
{
String = GetStringsFromFile(Paths, i);
dcount = GetDividerCount(String, d);
for (unsigned int j = 0; j < dcount; j++)
PS.push_back(Parser(String, d));
std::sort(PS.begin(), PS.end(), comp);
parsedst = PS.size();
SaveResults(fname, PS, filecount, parsedst, Paths);
PS.erase(PS.begin(), PS.end());
String.clear();
}
}

std::string NameGenerator(char *argv[])
{
std::string fname = "Result____.txt";
SYSTEMTIME st;
GetSystemTime(&st);
fname.insert(7, argv[2]);
char ch[3];
itoa(st.wHour + 3, ch, 10);
fname.insert(9, ch);
itoa(st.wMinute, ch, 10);
fname.insert(12, ch);
itoa(st.wSecond, ch, 10);
fname.insert(15, ch);
return fname;
}

void SaveResults(std::string fname, std::vector<std::string> &PS,
unsigned int &filecount, std::size_t &parsedst,
std::vector<std::string> &Paths)
{

ofstream outfile(fname.data());
outfile.seekp(0, std::ios_base::end);
// outfile << "\nNumber of files parsed : " << filecount;
// outfile << "\nParsed files : \n";
// for (unsigned int i = 0; i < filecount; i++)
// outfile << i + 1 << " - " << Paths[i] << "\n";
for (unsigned int i = 0; i < filecount; i++)
{
outfile << "Five longest strings for file " << Paths[i] << " : \n";
for (unsigned int i = 0; i < 5; i++)
outfile << i + 1 << " - " << PS[i] << "\n";
}
outfile << "\nTotal count of parsed strings for this file : " << parsedst;
outfile.close();
}



Суть проблемы : Почему-то в файла результатов записывается информация только о последнем файле. Почему - я так и не понял. Попробовал делать промежуточные выводы - вектор PS шалит, полностью не заполняется предложениями. Почему - тоже не понял. Наверное тупой или устал.. Если кто-то будет запускать приложение, вот параметры запуска : имяфайла.exe путькфайлу(например C:\1) кол-во файлов к обработке (например 3).
Я пока не стал делать перехваты ошибок при запуске, не до этого...хочу сначала с этим разобраться. И ещё кое-что, в приложенном файле примеры файлов для обработки, 3 текстовых файла.

Сообщение отредактировано: Andrewshkovskii -


Прикрепленные файлы
Прикрепленный файл  1.zip ( 455 байт ) Кол-во скачиваний: 129
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Гость






Цитата
Почему-то в файла результатов записывается информация только о последнем файле.
Открывай файл для дозаписи, как положено:
	ofstream outfile(fname.data(), std::ios::app);

вместо
	ofstream outfile(fname.data());
outfile.seekp(0, std::ios_base::end);
, и ты поймешь, что происходит...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


Блин..какой же я не внимательный..в цикле одно и тоже писать.сспасибо.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 24.01.2022 11:14
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name