Так что у меня была эта часть кода, которая работала нормально. Затем я добавил несколько строк (код ниже), и теперь он сбой при выполнении. Из тестов, которые я сделал, он, кажется, застрял в цикле while. Я новичок, и я не вижу, как эти изменения повлияли
EDIT: программа компилируется без ошибок. Это сообщение появляется во время исполнения: это приложение запросило Runtime для его необычного завершения. И теперь это не позволит мне использовать отладчик... (я использую Dev C++)
int main() {
char fileName[] = "espion.txt";
std:: string infoEspion;
Espion *cur = 0, *first = 0, *last = 0, *add = 0;
std :: ifstream readFile;
readFile.open(fileName, std::ios::in);
if(!readFile.is_open())
exit(EXIT_FAILURE);
while(std::getline(readFile, infoEspion)) {
if(first == NULL){ //head
add = new Espion;
add -> name = infoEspion.substr(0,30);
add -> next = NULL;
first = add;
cur = add;
last = add;
} else if(findName(first, infoEspion.substr(0,30)) == NULL ) {
// adding only if not on the list already
add = new Espion;
add -> name = infoEspion.substr(0,30);
add -> next = NULL;
cur -> next = add;
last = add;
cur = add;
}
}
printList(first);
printList(sortAlpha(first));
readFile.close();
system("pause");
return 0;
}
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cerrno>
struct Pays
{
std:: string name; /* nom du pays */
Pays *next; /* pointeur sur le prochain pays */
};
struct Espion
{
std:: string name; /* nom de lespion(ne) */
Espion *next; /* pointeur sur le prochain espion */
Pays *begListPays; /* tête de liste des pays visités */
Pays *endListPays;
};
Espion *findName(Espion* ptr, std::string nameToCompare)// returns pointer or NULL
{
while (ptr)
{
if(ptr->nom.compare(nameToCompare) == 0)
return ptr;
ptr = ptr->next;
}
ptr = NULL;
return ptr;
}
int main() {
char fileName[] = "espion.txt";
std:: string infoEspion;
Espion *cur = 0, *first = 0, *last = 0, *add = 0, *curP = 0;
Pays *firstP = 0, *lastP = 0, *addP = 0;
std :: ifstream readFile;
readFile.open(fileName, std::ios::in);
if(!readFile.is_open())
exit(EXIT_FAILURE);
while(std::getline(readFile, infoEspion)) {
if(first == NULL){ //head
add = new Espion;
add -> name = infoEspion.substr(0,30);
add -> next = NULL;
first = add;
cur = add;
last = add;
addP = new Pays;
addP-> name = infoEspion.substr(30,20);
addP-> next = NULL;
add-> begListPays = addP;
add-> endListPays = addP;
//changes up to here run OK!
} else if(findName(first, infoEspion.substr(0,30)) == NULL ) {
// adding only if not on the list already
add = new Espion;
add -> name = infoEspion.substr(0,30);
add -> next = NULL;
cur -> next = add;
last = add;
cur = add;
addP = new Pays;
addP->name = infoEspion.substr(30,20);
addP->next = NULL;
add->begListPays = addP;
add->endListPays = addP;
} else {
addP = new Pays;
addP-> name = infoEspion.substr(30,20);
addP-> next = NULL;
findName(first, infoEspion.substr(0,30))->endListPays->next = addP;
findName(first, infoEspion.substr(0,30))->endListPays = addP;
}
}
printList(first);
printList(sortAlpha(first));
readFile.close();
system("pause");
return 0;
}
Ваш while
цикл не принимая во внимание, что последняя строка будет пустой, если файл заканчивается разрывом строки, таким образом, substr(30,20)
вызывают исключение.
Кроме того, ваш код цикла имеет ненужное дублирование кода. Вы можете значительно упростить логику.
Попробуй это:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cerrno>
#include <string>
struct Pays
{
std::string name; /* nom du pays */
Pays *next; /* pointeur sur le prochain pays */
};
struct Espion
{
std::string name; /* nom de lespion(ne) */
Espion *next; /* pointeur sur le prochain espion */
Pays *begListPays; /* tête de liste des pays visités */
Pays *endListPays;
};
Espion* findName(Espion* ptr, std::string nameToCompare)// returns pointer or NULL
{
while (ptr)
{
if(ptr->name.compare(nameToCompare) == 0)
return ptr;
ptr = ptr->next;
}
return NULL;
}
int main()
{
char fileName[] = "espion.txt";
std::string infoEspion, espionName, paysName;
Espion *first = 0, *last = 0, *add;
Pays *addP;
std::ifstream readFile;
readFile.open(fileName, std::ios::in);
if (!readFile.is_open())
exit(EXIT_FAILURE);
while (std::getline(readFile, infoEspion))
{
if (infoEspion.empty())
continue;
espionName = infoEspion.substr(0,30);
paysName = infoEspion.substr(30,20);
add = findName(first, espionName);
if (!add)
{
add = new Espion;
add->name = espionName;
add->next = NULL;
add->begListPays = NULL;
add->endListPays = NULL;
if (!first) first = add;
if (last) last->next = add;
last = add;
}
addP = new Pays;
addP->name = paysName;
addP->next = NULL;
if (!add->begListPays) add->begListPays = addP;
if (add->endListPays) add->endListPays->next = addP;
add->endListPays = addP;
}
printList(first);
printList(sortAlpha(first));
readFile.close();
system("pause");
return 0;
}
С учетом сказанного вам следует воспользоваться функциями C++, которые больше управляют логикой для вас:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cerrno>
#include <string>
#include <list>
#include <algorithm>
struct Pays
{
std::string name; /* nom du pays */
};
struct Espion
{
std::string name; /* nom de lespion(ne) */
std::list<Pays> ListPays; /* tête de liste des pays visités */
bool operator<(const Espion& rhs) const
{
return (name < rhs.name);
}
};
struct isEspionName
{
std::string _name;
isEspionName(const std::string &nameToCompare) : _name(nameToCompare) {}
bool operator()(const Espion& e) const
{
return (e.name == _name);
}
};
int main()
{
char fileName[] = "espion.txt";
std::string infoEspion, espionName, paysName;
std::list<Espion> ListEspion;
Espion *e;
std::ifstream readFile;
readFile.open(fileName, std::ios::in);
if (!readFile.is_open())
exit(EXIT_FAILURE);
while (std::getline(readFile, infoEspion))
{
if (infoEspion.empty())
continue;
espionName = infoEspion.substr(0,30);
paysName = infoEspion.substr(30,20);
std::list<Espion>::iterator iter = std::find_if(ListEspion.begin(), ListEspion.end(), isEspionName(espionName));
if (iter != ListEspion.end())
{
e = &(*iter);
}
else
{
Espion addE;
addE.name = espionName;
ListEspion.push_back(addE);
e = &(ListEspion.back());
}
Pays addP;
addP.name = paysName;
e->ListPays.push_back(addP);
}
readFile.close();
printList(ListEspion);
ListEspion.sort();
printList(ListEspion);
system("pause");
return 0;
}
std::list
реализуется как двойной список. Если вам действительно нужен односвязный список, C++ 11 добавил класс std::forward_list
в #include <forward_list>
.
(e.name.compare(_name) == 0)
почему бы не e.name == _name
compare()
а я его не менял.