Linux -> problem z wczytaniem słowa przez ifstream, zaczynającego się od cudzysłowa

0

Dzień dobry.

Napisałem krótki program do znajdywania anagramów w tekście angielskim. Jednak program zgłasza double free or corruption (out), gdy chcę wczytać słowo zaczynające się od ". To powszechne w linuxie?

#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
#include <cctype>
#include <fstream>
#include <cstdlib>
#include <vector>
#include <utility>
#include <regex>

using namespace std;

char lower(char ch)
{
    return char (tolower(ch));
}

void openFile(ifstream & fin)
{
    cout << "Enter file name: ";
    string fName;
    getline(cin, fName);
    
    fin.open(fName);
    
    if (!fin.is_open())
        exit(-1);
}

void readWords(ifstream & fin, vector<string> & words)
{
    string word;
    fin >> word;
    
    cout << "OK";
    
    while (fin)
    {
        transform(word.begin(), word.end(), word.begin(), lower);
        regex e ("[\\^\\$\\\\\\.\\*\\+\\?\\(\\)\\[\\]\\{\\}\\|,;:'\\\"]+");
        word = regex_replace(word, e, "");
        
        words.push_back(word);
        
        fin >> word;
    }
    
    fin.close();
}

void countLetters(vector<pair<char, int>> & letters, string & str)
{
    if (str.size() > 0)
        letters.push_back(make_pair(str[0], 1));    
    
    for (int i = 1; i < str.length(); i++)
        for (int j = 0; j < letters.size(); j++)
        {
            if (letters[j].first == str[i])
                letters[j].second++;
            
            else if (isalpha(str[i]))
            {
                letters.push_back(make_pair(str[i], 1));
                break;
            }
        }
}

string makeCompareStr(vector<pair<char, int>> & letters)
{
    static const string Let = "abcdefghijklmnopqrstuvwxyz";
    string cmpStr           = "00000000000000000000000000";
    
    for (auto it = letters.begin(); it != letters.end(); it++)
    {
        size_t pos = Let.find((*it).first);
        cmpStr[pos] += (*it).second;
    }
    
    return cmpStr;
}

int searchAnagrams(vector<pair<vector<string>, int>> & an, string & str)
{
    
    vector<pair<char, int>> letters;
    vector<pair<char, int>> anLetters;
    
    countLetters(letters, str);
    
    for (auto it = an.begin(); it != an.end(); it++)
        for (auto it2 = (*it).first.begin(); it2 != (*it).first.end(); it2++)
        {
            anLetters = vector<pair<char, int>> ();
            
            if ((*it2) == str)
                return 1000000000 + (it - an.begin());
        
            countLetters(anLetters, *it2);
            
            if ((makeCompareStr(letters) == makeCompareStr(anLetters)))
                return it - an.begin();
            
        }
   
    return -1;
}

bool checkForExist(pair<vector<string>, int> & wordList, string & str)
{
    for (auto it = wordList.first.begin(); it != wordList.first.end(); it++)
        if (str == *it)
            return true;
    
    return false;
}

int main()
{
    ifstream fin;
    openFile(fin);
    
    vector<string> words;
    readWords(fin, words);
    
    vector<pair<vector<string>, int>> anagrams;
    
    for (auto it = words.begin(); it != words.end(); it++)
    {
        int i;
        
        if ((i = searchAnagrams(anagrams, *it)) == -1)
        {
            pair<vector<string>, int> p = make_pair(vector<string> (), 0);
            p.first.push_back(*it);
            p.second = 1;
            
            anagrams.push_back(p);
        }
        
        else if (i > 999999999)
            anagrams[i % 1000000000].second++;
        
        else
        {
            if (checkForExist(anagrams[i], *it))
                anagrams[i].second++;
            
            else
            {
                anagrams[i].first.push_back(*it);
                anagrams[i].second++;
            }
        }
    }
    
    for (auto it = anagrams.begin(); it != anagrams.end(); it++)
    {
        for (auto it2 = (*it).first.begin(); it2 != (*it).first.end(); it2++)
            cout << *it2 << " ";
        
        cout << (*it).second << endl;
    }

    return 0;
}

plik

“Hi Amy! Your mum sent me a text. You forgot your inhaler. Why don’t you turn your phone on?” Amy didn’t like technology. She never sent text messages and she hated Facebook too.

Proszę o wskazówki
Dzięki.
M.

1

To nie jest zwykły cudzysłów, tylko jakiś znaczek z wyższych partii unicode - tak wygląda on po wczytaniu do stringa:
screenshot-20201029215232.png

Jak widać jego reprezentacja zajmuje 3 znaki, a nie jeden i zapewne to jest problematyczne dla implementacji std::regex, którą dostarcza libgcc. Niestety, chyba jedyną sensowną radą jaką mogę dać jest użycie innego silnika do regexów. Ale może ktoś mnie tu poprawi.</del>
Wygląda na to, że złapałem się sam we własne sidła i miałem coś naknocone ze środowiskiem

0

Wow. Dzięki. To buraki wrzucili taki plik...

0
>> ord('“')
8220

Problem jest taki, ze to char u Ciebie

vector<pair<char, int>> letters;
vector<pair<char, int>> anLetters;

Moze na stringu by zadzialalo?

1

@kq:

screenshot-20201029221955.png

2

Prawdą jest, że znaczek wykracza poza zakres ASCII, ale błąd nie jest w regeksach, a w funkcji makeCompareStr, jak zrobisz tak, to błąd się nie objawia:

string makeCompareStr(vector<pair<char, int>> & letters)
{
    static const string Let = "abcdefghijklmnopqrstuvwxyz";
    string cmpStr           = "00000000000000000000000000";

    for (auto it = letters.begin(); it != letters.end(); it++)
    {
        size_t pos = Let.find((*it).first); // co jeśli nie znajdziemy?
        if (pos != string::npos) {
            cmpStr[pos] += (*it).second;
        }
    }

    return cmpStr;
}

To co w oryginalnym kodzie się działo, to robiłeś czasem

cmpStr[-1] += (*it).second;

W mojej wersji gcc, std::string stringi długości >15 alokuje na stercie. Dostęp do indeksu -1 powoduje odwołanie się do metadanych alokacji (tak przynajmniej robi malloc w glibc), przez co dostajesz taki błąd.

@kq niestety to chyba nie ma się w ogóle do std::stringa :p

1

Masz korupcję tutaj:

    for (auto it = letters.begin(); it != letters.end(); it++)
    {
        size_t pos = Let.find((*it).first); // <---- sprawdź czy != npos
        cmpStr[pos] += (*it).second; 
    }

1 użytkowników online, w tym zalogowanych: 0, gości: 1