Вопрос с ошибкой доступа (код прилагается ниже) - PullRequest
1 голос
/ 02 мая 2020

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

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

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

ошибка Тема 1: EXC_BAD_ACCESS (код = 1, адрес = 0x0):

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;

vector<string> getVector(const string&);
string getName(const string&);
void selectionSort(vector<string>&);
bool search(const string&, const vector<string>&);
void displayResult(const string&, const string&, bool);
void writeToFile(const string&, const vector<string>&);
void reverseVector(vector<string>&);

int main()
{
    string boyName, girlName;
    bool boyNameFound, girlNameFound;


    vector<string> boyNames(getVector("BoyNames.txt"));
    vector<string> girlNames(getVector("GirlNames.txt"));


    boyName = getName("boy's");
    girlName = getName("girl's");

    selectionSort(boyNames);
    selectionSort(girlNames);

    boyNameFound = search(boyName, boyNames);
    girlNameFound = search(girlName, girlNames);

    displayResult("boy's", boyName, boyNameFound);
    displayResult("girl's", girlName, girlNameFound);

    writeToFile("Boynames_asc.txt", boyNames);
    writeToFile("Girlnames_asc.txt", girlNames);

    reverseVector(boyNames);
    reverseVector(girlNames);

    writeToFile("Boynames_desc.txt", boyNames);
    writeToFile("Girlnames_desc.txt", girlNames);

    cout<<endl;

    system("PAUSE");
    return 0;
}


void selectionSort(vector<string> &arr)
{

    int startScan, minIndex;
    string minValue;

    for (startScan = 0; startScan < (arr.size() - 1); startScan++)
    {
        minIndex = startScan;
        minValue = arr[startScan];
        for(int index = startScan + 1; index < arr.size(); index++)
        {
            if (arr[index] < minValue)
            {
                minValue = arr[index];
                minIndex = index;
            }
        }
        arr[minIndex] = arr[startScan];
        arr[startScan] = minValue;
    }


}// above is code the teacher provided
// below is where I have written code for the assignment
 vector<string> getVector(const string& fileName)
{
    string name;
    ifstream file;
    vector<string> namesFromFile;
    file.open(fileName);
    while(getline(file, name))
    {
        namesFromFile.push_back(name);
    }
    return namesFromFile;
}

string getName(const string& gender)
{
    string nameChoice;

    cout << "Enter a " << gender << " name, or N if you do not wish to enter a " << gender << " name: " << endl;
    getline(cin, nameChoice);

    return nameChoice;
}

bool search(const string& nameChoice, const vector<string>& names)
{


    for(int i = 0; i < names.size(); i++)
    {
        if(nameChoice == names.at(i)) // names[i]
        {

            return true;

        }

    }
    return false;
}

void displayResult(const string& gender, const string& names, bool nameFound)// change this function so either displays name found not found or chose //not to enter
{
    if(nameFound)
    {
       cout << names << "is one of the most popular " << gender << "names." << endl;
    }
    else if(!nameFound)
        cout << names << " is NOT one of the most popular " << gender << " names." << endl;

    else if(names == "N")
    {
        cout << "You chose not to enter a " << gender << " name." << endl;
    }

}

void writeToFile(const string& fileName, const vector<string>& names)
{

    ofstream outputFile;
    outputFile.open(fileName);
    for(int i = 0; i < names.size(); i++)
    {
        outputFile << names[i] << endl;

    }
}

void reverseVector(vector<string>& names) 
{
    string temp = 0;
    for(int i = 0; i < names.size(); i++)
    {
        temp = names[0];
        names[0] = names[names.size() - i];
        names[names.size() - i] = temp;
    }



}

Ответы [ 2 ]

0 голосов
/ 05 мая 2020

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

@ bruno помог мне понять, что я пытался получить доступ за пределами или в конце векторов / массивов. используя приведенный ниже код, я смог сохранить первый элемент в последнем и последний элемент с первым.

void reverseVector (vector & names)

 {
string temp;
for(int i = 0; i < names.size(); i++)
{
    temp = names[i];
    names[i] = names[names.size() - 1 - i];
    names[names.size() - 1 - i] = temp;

}

} Исходный поток ошибка доступа была вызвана тем, что, хотя учитель предоставил

код над функцией getVector, я должен был понять основную идею c, что мне все еще нужно изменить полный путь к файлу.

error Thread 1: EXC_BAD_ACCESS (код = 1, адрес = 0x0):

vector<string>         boyNames(getVector("/Users/Desktop/comp165/assignment8/BoyNames.txt"));
vector<string>





 Thank you all for your help
0 голосов
/ 03 мая 2020

error Поток 1: EXC_BAD_ACCESS (код = 1, адрес = 0x0):

Это происходит из-за вашего определения reverseVector по двум причинам: во-первых, string temp = 0;, где вы инициализируете свою строку с char*, равным NULL с неопределенным поведением, просто используйте string temp;

, второе - на первом l oop, когда i 0 означает доступ к names[names.size()], так что после последнего элемента. Из-за этого ваш алгоритм некорректен с более чем 3 элементами в векторе, потому что вы всегда обмениваетесь с name[0]. Вы должны обменяться name[0] с именами [names.size () - 1] and name 1 with names[names.size()-2] et c, go вернется к этой функции в конце моего ответ

учитель написал функцию сортировки выбора, поэтому я не изменил ее

поэтому скажите вашему учителю, что его функция предполагает, что вектор не пуст, и когда он тест пуст:

for (startScan = 0; startScan < (arr.size() - 1); startScan++)

всегда ложно arr.size() возвращает size_t, равное без знака , поэтому при пустом значения ~ 0u, что самое большое возможное значение size_t.

Скажите, что он смешивает (подписано) int и (без знака) size_t неверно и обычно сигнализируется компилятором, и мы в C ++, а не в C, они имеют итераторов .

О main

Чтобы избежать ошибки в selectionSort проверьте, что вектор не пуст, прежде чем вызывать его, поэтому:

if (! boyNames.empty())
  selectionSort(boyNames);
if (! girlNames.empty())
  selectionSort(girlNames);

У вас есть специальный случай N в getName , когда вход имя N вы не должны учитывать ввод:

if (boyName != "N") {
  boyNameFound = search(boyName, boyNames);
  displayResult("boy's", boyName, boyNameFound);
}

if (girlName != "N") {
  girlNameFound = search(girlName, girlNames);
  displayResult("girl's", girlName, girlNameFound);
}

Примечание основной сделать два раза одно и то же, один раз для мальчика и один раз для девушка, добавить функцию позволяет не дублировать весь код.

Но, кажется, main тоже написано вашим учителем, как жаль на самом деле.

In getVector может быть, вы можете создать сообщение, когда вы не можете прочитать файл. Чтобы помочь чтению кода, я рекомендую вам добавлять пустую строку после каждого объявления частей, конструктор ifstream позволяет открыть файл, чтобы вы могли иметь

vector<string> getVector(const string& fileName)
{
    string name;
    ifstream file(fileName);
    vector<string> namesFromFile;

    while(getline(file, name))
    {
        namesFromFile.push_back(name);
    }

    return namesFromFile;
}

или

vector<string> getVector(const string& fileName)
{
  vector<string> namesFromFile;
  ifstream file(fileName);

  if (! file)
    cerr << "cannot read " << fileName << endl;
  else
  {
    string name;

    while(getline(file, name))
    {
      namesFromFile.push_back(name);
    }
  }

  return namesFromFile;
}

О getName

Он не управляет регистром EOF, а также если имя не пустое или содержит только пробелы или пробелы в начале и / или конце.

Если имя должно быть уникальным словом, поэтому «Джон» не «Джон Доу», вы можете заменить использование getline на cin >> nameChoice; и заставить N , если EOF:

string getName(const string& gender)
{
    string nameChoice;

    cout << "Enter a " << gender << " name, or N if you do not wish to enter a " << gender << " name: " << endl;
    return (!(cin >> nameChoice)) ? string("N") : nameChoice;
}

Если имя может быть составлено, после вызова необходимо удалить пробелы в начале и конце, а затем проверить, является ли введенное имя пустое в силу N :

string getName(const string& gender)
{
    string nameChoice;

    cout << "Enter a " << gender << " name, or N if you do not wish to enter a " << gender << " name: " << endl;
    getline(cin, nameChoice);

    size_t b = 0;

    for (;;) {
      if (b == nameChoice.size())
        return "N";
      if (!std::isspace(nameChoice[b]))
        break;
      b += 1;
    }

    size_t e = nameChoice.size();

    while ((e != 0) && std::isspace(nameChoice[--e]))
      ;

    return (e >= b) ? nameChoice.substr(b, e - b + 1) : string("N");
}

Поскольку в коде учителя нет итератора , я не буду использовать их здесь и позже. Заметьте, может быть, вам также придется удалить лишние пробелы в составленном имени, чтобы заменить «Джон Доу» на «Джон Доу»?

О search

векторы имен сортируются благодаря вызову selectionSort , поэтому поиск во всем векторе бесполезен, если имя меньше, чем имя в векторе

bool search(const string& nameChoice, const vector<string>& names)
{
    for(size_t i = 0; i < names.size(); i++)
    {
        if(nameChoice == names[i])
        {
            return true;
        }
        if (nameChoice < names[i])
        {
            return false;
        }
    }
    return false;
}

в любом случае, даже при такой небольшой оптимизации ваш поиск все еще находится в O (N)

Вы также можете иметь более эффективный поиск в O (log (N)) сравнивая с половиной (под) векторов, делая это самостоятельно или используя std :: binary_search :

About displayResult

nameFound это true из false это не может быть что-то еще, поэтому вы не можете достичь else if(names == "N"), вам нужно сначала проверить этот случай, и бесполезно проверять if(!nameFound), когда вы знаете, что if(nameFound) равно ложно , например (например, name вместо names потому что есть только одно имя):

void displayResult(const string& gender, const string& name, bool nameFound)// change this function so either displays name found not found or chose //not to enter
{
    if(name == "N")
      cout << "You choose to not enter a " << gender << " name." << endl;
    else if(nameFound)
      cout << name << " is one of the most popular " << gender << "names." << endl;
    else
      cout << name << " is NOT one of the most popular " << gender << " names." << endl;
}

или

void displayResult(const string& gender, const string& name, bool nameFound)// change this function so either displays name found not found or chose //not to enter
{
    if(name == "N")
      cout << "You choose to not enter a ";
    else 
      cout << name << " is" << ((nameFound) ? "" : " NOT")
       << " one of the most popular ";

    cout << gender << " name." << endl;
}

О writeToFile

Как и для ifstream Конструктор ofstream позволяет открыть файл

Вы не проверяете, можете ли вы записать в файл, это опасно, потому что скрыть Проблема, лучше сделать, например:

void writeToFile(const string& fileName, const vector<string>& names)
{
    ofstream outputFile(fileName);

    if (! outputFile)
      cerr << "Cannot open " << fileName << " to write it" << endl;
    else
    {
      for(size_t i = 0; i < names.size(); i++)
        outputFile << names[i] << endl;
    }
}

О reverseVector

Как я уже сказал, его определение не правильно, он коротким путем должен использовать std :: reverse , остальное делать самостоятельно:

void reverseVector(vector<string>& names) 
{
    string temp;
    size_t pos = 0, sup = names.size();

    while ((pos + 1) < sup)
    {
        temp = names[pos];
        names[pos++] = names[--sup];
        names[sup] = temp;
    }

    for (auto s : names) cout << s << ' ';
    cout << endl;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...