В то время как цикл зацикливается в третий раз, хотя его состояние в моих глазах не соблюдается и поэтому выводит нулевую строку - PullRequest
0 голосов
/ 05 апреля 2019

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

Мой код работает вплоть до перечисления станций теперь, когда первая (одна после запуска) была названа.Он зацикливается на дополнительное время и, конечно же, не может печатать пустую строку, поэтому возникает ошибка.Как я могу исправить эту ошибку и насколько я глуп?

using namespace std;

struct Station
{
    string name;
    Station *next;
};


int main()
{
    string startName = "Start";

    Station *start = new Station;   
    start->name = startName;
    start->next = NULL; 

    Station *pointer = NULL;

    char addkey = 'n';
    char response;
    bool adding = true;

    cout << "Enter 'n' to add a New Station" << endl;
    cin >> response;

    if (response == addkey)
    {
        do
        {
            char addAgain;
            string newName;
            string fromStation;

            Station *beforePointer = pointer;

            cout << "\nEnter New Station Name" << endl;
            cin >> newName;

            pointer = start;

            cout << "\nStation List:" << endl << start->name << endl;   
            do
            {
                beforePointer = pointer;
                cout << beforePointer->name << endl; // Issue running this line the second run of the code, third run of the do-while loop. String at start->next->next->name; a nullptr
                pointer = pointer->next; 
            }
            while (beforePointer->next != nullptr);

            cout << "\nEnter Station it is from (top to bottom)" << endl;
            cin >> fromStation;

            pointer = start->next;

            bool pointed;
            pointed = false;

            if (start->name == fromStation)
            {
                string placeholdString;
                Station *placeholdPointer;

                Station *newStation = new Station;

                if (start->next != NULL) // Hasn't been tested as of yet
                {
                    placeholdString = start->next->name;
                    placeholdPointer = start->next;
                    start->next = newStation;
                    start->next->name = newName;
                    start->next->next = placeholdPointer;
                    start->next->name = placeholdString;
                    pointed = true;
                }
                else
                {
                    start->next = newStation;
                    start->next->name = newName;
                    pointed = true;
                }

            }
            else
            {
                pointer = start->next;

                do
                {
                    if (pointer->name == fromStation)
                    {
                        string placeholdString;
                        Station *placeholdPointer;

                        Station *newStation = new Station;

                        if (pointer->next != NULL) // Hasn't been tested as of yet
                        {
                            placeholdString = pointer->next->name;
                            placeholdPointer = pointer->next;
                            pointer->next = newStation;
                            pointer->next->name = newName;
                            pointer->next->next = placeholdPointer;
                            pointer->next->name = placeholdString;
                            pointed = true;
                        }
                        else
                        {
                            pointer->next = newStation;
                            pointer->next->name = newName;
                            pointed = true;
                        }       
                    }
                    if (pointed == false)
                    {
                        pointer = pointer->next;
                    }
                }
                while (pointer->next != NULL);
            }


            cout << "\nWould you like to add more?" << endl << "Enter 'n' again" << endl;
            cin >> addAgain;

            if (addAgain != addkey)
            {
                adding = false;
            }
            else if (addAgain == addkey)
            {
                adding = true;
            }
        } 
        while (adding == true);
    }

    system("pause");
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 09 апреля 2019
                        Station *newStation = new Station;

Проблема в том, что вы не инициализируете свой новый объект структуры. new не дает никаких гарантий о состоянии памяти, которую он возвращает. Таким образом, ваша newStation-> next может иметь любое значение, в результате чего она потенциально может не пройти проверку nullptr / NULL.

0 голосов
/ 05 апреля 2019

Из вашего кода (цикл do-while):

    /* Add #include <assert.h> at top of file */

    // Run #1
    assert( pointer != NULL ) ;
    beforepointer  = pointer ; // beforepointer == pointer == start

    assert( beforepointer != NULL ) ;
    assert( beforepointer->name != NULL ) ;

    cout << beforepointer->name << endl ; // Will print 'Start'
    pointer = pointer->next ; // pointer->next == start->next == NULL
    assert( pointer != NULL ) ; // SHOULD FAIL HERE (will abort)

    // (pointer is now NULL)

    // Run #2
    beforepointer = pointer ; // beforepointer == pointer == NULL
    assert( beforepointer != NULL ) ; // This would fail too
    cout << beforepointer(== NULL)->name << endl ; // *** Segmentation violation!
    ...

Вы больше не указываете на что-либо действительное во 2-м цикле, перед указателем NULL.

Лучший способ распечатать список:

beforepointer = pointer ;
assert( beforepointer != NULL ) ;

while ( beforepointer != NULL ) {
    assert( beforepointer->name != NULL ) ;

    cout << beforepointer->name << endl ;
    beforepointer = beforepointer->next;
}

EDIT: Перефразируя ваш пример кода и используя стандартную библиотеку c ++, вы можете упростить все это следующим образом (используя векторы):

/**
 * Wrapper function to prompt user for input
 */
istream & queryUser( const string & prompt, string & answer ) {
  cout << prompt << ' ' << flush ;
  getline( cin, answer ) ;
  return cin;
}

/** Always useful emptiness test function */
bool isBlankOrEmpty( const string & s ) {
    return s.empty() || s.find_first_not_of( " \t") == string::npos ;
}
/**
 * The big main
 */
int main() {
  vector<string> stations ; // list of station names

  // ... Accept user input as long as input is entered
  string newStationName ;
  while( queryUser( "Enter new station name (or hit ENTER to exit)", newStationName ) ) {

    // ... Quit if the line is empty
    if ( isBlankOrEmpty( newStationName ) ) {
        break ;
    }

    // ... Locate insertion point
    vector<string>::iterator insertionPoint = stations.end() ; // append by default

    // ... Have user specify where to insert the new station (if there is such an option)
    if ( stations.size() > 1 ) {

        // ... Where to insert?
        string fromStation ;
        if ( queryUser("Enter station it is from (top to bottom)", fromStation) && ! isBlankOrEmpty( fromStation ) ) {
            vector<string>::iterator it = std::find( stations.begin(), stations.end(), fromStation ) ;
            if ( it != stations.end() ) {
                insertionPoint = ++it ; // move to position after the fromStation
            }
        }
    }

    // ... Insert the new station name
    stations.insert( insertionPoint, newStationName ) ;

    cout << "Your station list:" << endl ;
    for ( auto & stationName : stations ) {
        cout << stationName << endl ;
    }
  }

  return 0 ;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...