How can I make my c++ program exit the while loop after processing the input?

  • C/C++
  • Thread starter Defennder
  • Start date
  • Tags
    Loop
In summary: } else if (curr=='$'||curr=='@'||curr=='%'){ //special cases } else { cout<<curr<<""; } } return 0; }
  • #1
Defennder
Homework Helper
2,593
5
I'm writing a c++ program which simulates the behaviour of notepad in this sense. Suppose we input (keyboard) 'high<<<<^^^^11'. Expected outout is '11'

Here '<' represents pressing left arrow key once, and ^ represents the delete key. '>' represents the right arrow key. To achieve this I made use of a doubly-linked list, whose implementation was done from scratch and is included within the same driver file.

I've checked the insertion operation and for some reason the program is not able to exit the "while" loop to print the result after processing the input. The "Test" line was included to see if it could exit, but so far it hasn't exited the while loop. I'm wonderin how cin works here.

Here is the code:
Code:
#include <iostream>
#include <list>

using namespace std;

class ListNode {
    private:
        char c;	
        ListNode *prev;
        ListNode *next;
    public:
        Default argument for *p and *n is NULL
        ListNode(char character, ListNode *p = NULL, ListNode *n = NULL) : c(character), prev(p), next(n) {}

        // define accessor methods

        ListNode* getprev(){
            return prev;}

        ListNode* getnext(){
            return next; }

        // define mutator methods
        void setprev(ListNode *cur){
            prev = cur;}
        void setnext(ListNode *cur){
            next = cur;}
        
        // method to print the list starting from current node

        void printList() {
            cout<<c;}

        // complete this method
};

int main() {
    char curr;	//current character from input
    ListNode *head = NULL;
    ListNode *cursor = NULL;

    while (cin>>curr) {
        switch (curr) {
            case '<' : if(cursor!=head)
                           cursor = cursor->getprev();
                       //this checks that the linked list is not
                       //already at the start before moving
                       break;

            case '>' : if(cursor->getnext()!=NULL)
                           //This checks the list has entries and that
                           //cursor is not already at the end before moving
                           //right
                           cursor = cursor->getnext();
                       break;

            case '^' : if(cursor->getnext()!=NULL){//over here deletion
                           //deletes the node after the one pointed to
                           //by cursor.  Note that the cursor does not
                           //move at all after deletion.
                           ListNode *delnode = cursor->getnext();
                           delnode->getnext()->setprev(cursor);
                           cursor->setnext(delnode->getnext());
                           delete delnode;
                           delnode = NULL;}
                           break;

            default : if(head==NULL){ //This part of the code initialises
                          //the linked list upon input of the first valid
                          // non space character.  When this is executed
                          // the linked list is no longer empty.  The head
                          // is effectively the dummy node since nothing
                          // is stored in it
                          head = new ListNode('\0');
                          ListNode *newPtr = new ListNode(curr,head,NULL);
                          //The head's next ptr now points to the first
                          //valid data node
                          head->setnext(newPtr);
                          //Here cursor points to the first valid entry
                          cursor = newPtr;
                          newPtr = NULL;
                          }
                          else {
                              //Insertion is done after the node which is
                              //pointed to by cursor
                              ListNode *newPtr;
                              newPtr = new ListNode(curr,cursor,cursor->getnext());
                              if (cursor->getnext()!=NULL)
                                  //This part assumes that insertion is not done
                                  //at the tail.
                              { (newPtr->getnext())->setprev(newPtr); }
                              cursor->setnext(newPtr);
                              cursor = newPtr;
                              newPtr = NULL;}
                              break;
        }
    }
    cout<<"End of while"<<endl;

    //Prints the List
    cout<<"Test"<<endl;
    ListNode *printnode = head->getnext();
    while (printnode!=NULL)
    {   printnode->printList();
        printnode = printnode->getnext();}
        return 0;
}

Suppose I enter "12345" as the input. After hitting the enter key, nothing happens as though the program is expecting some more input. How do I make it such that it recognises the return key as a input to terminate the while loop?
 
Technology news on Phys.org
  • #2
The break statement only breaks out of the inner most loop, in this case the switch statement. The easiest way is to have an extra bool that you set to true if you find the return, and add a test like.

bool bHaveReturn=false

while (!bHaveReturn && cin>>curr) {

// in the case with the return
bHaveReturn=true;
}
You could also use a goto ;-)
 
  • #3
Learn how to use exceptions.

Code:
void some_function()
{
  if (something went wrong) throw SomeError();
}

void function()
{
  try
  {
// throw exception - it will be handled by the catch below
    if (something went wrong) throw EndOfWork();

// blah blah code
    while (1)
    {
// if you throw exception it will be handled in the same place
      if (we are done) throw EndOfWork();

// call function - if the exception will be thrown there
// it will be handled by the catch below as well
      some_function();
    }   
  }

// it will catch everything, no matter where the exception is thrown
  catch (EndOfWork)
  {
// do whatever needs to be done
  }
}

You may have different exceptions thrown out from the same piece of code and each will be handled separately.
 
  • #4
Hi, thanks for replying. I think the problem here is that the >> extractor basically ignores white spaces, and that includes newline which is the return key. Goto isn't covered in my course, so I assume it's not needed. Does using exceptions here really help? After if the input newline character is ignored the code won't execute, right? What should I use to make them not ignore the newline char?
 
  • #5
Goto is considered bad form so probably isn't covered in your course.
Exceptions are just goto in stylish new clothes - you shouldn't really use them for a normal event like an end of input, only for an 'exceptional' event
 
  • #6
mgb_phys said:
Exceptions are just goto in stylish new clothes - you shouldn't really use them for a normal event

Matter of style IMHO. You may use additional BOOL variable and test it in every nested loop, but it it makes code hard to read and analyze, in such case throwing exceptions makes code much more readable.

In the end it all boils down to jumps, whether we like it or not.
 
  • #7
Borek said:
In the end it all boils down to jumps, whether we like it or not.
One of the advantages of an exception or a goto, is that it's a lot easier to search for a label than for a nested right brace when browsing a program without a special editor.
 
  • #8
Well, that's for exceptions, which I don't think I need to use because there is no such thing as an invalid input here. The question is what should I use to make the program recognise the newline character as input to terminate and print the output?
 
  • #9
Exception doesn't mean "invalid input". It can mean whatever you want. It can mean "I have found newline in the input and I want to terminate the loop".

You don't have to use exception here, but it fits problem as described.
 
  • #10
I don't see how that answers the question I raised earlier. The problem I have is that cin>>curr does not recognise the newline character at all (I read this from my lecture notes), it ignores it as input, which is why it doesn't exit the while loop. But this part of the code was given as part of a pre-existing skeleton code the course instructors gave me, so I'm assuming I don't have to modify this part to make the program work (ie. exit the while loop to print the output). I've seen some of my other coursemates' code and they didn't appear to modify the that part of the code as well.

Now what can I use to get this to work?
 
  • #11
OK, sorry, I thought it is the problem mgb_phys signalled.

Perhaps use cin.get(curr)?
 
  • #12
Hi, I apologise if I sounded a little impatient earlier. I tried out your suggestion and I think while it does preserves white spaces in the input, it seems to ignore newline character as well. This is from a small test program:
Code:
1 #include <iostream>
  2 using namespace std;
  3 
  4 int main()
  5 {
  6     char curr;
  7 
  8     while(cin.get(curr)) {
  9         if(curr=='LF')
 10             break;
 11         cout<<curr; }
 12         
 13         return 0;
 14 }
Since I'm meant to do this on a Unix system, I looked up the ACSCII table and found that the character for newline is 'LF'. Compiling gave me an error as follows:

test.cpp:9:18: warning: multi-character character constant
test.cpp: In function `int main()':
test.cpp:9: warning: comparison is always false due to limited range of data type

And this suggests that C++ doesn't recognise 'LF' as the newline character. Indeed entering '12345' as the input gives me '12345' as the output without terminating the program. No luck here.
 
  • #13
An alternative to goto and exceptions would be to put the loops you're trying to exit in a function and use return instead of break/throw.
 
  • #14
'LF' is the name of the ascii character, the character code is '\n' or 0xa
it may also return carriage return '\r' or 0xd
 
  • #15
Defennder said:
Code:
 8     while(cin.get(curr)) {
  9         if(curr=='LF')
 10             break;
 11         cout<<curr; }
Since I'm meant to do this on a Unix system, I looked up the ACSCII table and found that the character for newline is 'LF'.

Use '\n' instead:

Code:
while (cin.get(curr)) {
    if (curr == '\n')
        break;
    cout<<curr; }

Or this, which eliminates the break:

Code:
while (cin.get(curr) && (curr != '\n')) {
    cout << curr;  }
 
  • #16
Hi guys, I tried it out and it works. So thanks!
 

FAQ: How can I make my c++ program exit the while loop after processing the input?

Why am I unable to exit a while loop?

There could be several reasons for being unable to exit a while loop. One possible reason is that the condition of the while loop is always evaluating to true, causing an infinite loop. Another reason could be that there is a bug in the code that prevents the loop from terminating.

How can I fix my while loop to exit properly?

To fix a while loop that is not exiting properly, you can check the condition of the loop and make sure it is evaluating to false at some point. You can also use a break statement to forcefully exit the loop when a certain condition is met.

Can a while loop be terminated from within the loop itself?

Yes, a while loop can be terminated from within the loop itself using a break statement. The break statement will immediately exit the loop and continue with the code outside of the loop.

What is the difference between break and continue statements in a while loop?

A break statement will terminate the loop and exit it completely, while a continue statement will only skip the current iteration of the loop and continue to the next iteration. This means that the loop will continue to run until the condition is met, but certain iterations will be skipped if the continue statement is used.

How can I prevent my while loop from becoming an infinite loop?

To prevent a while loop from becoming an infinite loop, make sure to check the condition of the loop and ensure that it will eventually evaluate to false. You can also use a counter variable to limit the number of times the loop runs, or use a break statement to forcefully exit the loop when a certain condition is met.

Similar threads

Replies
2
Views
3K
Replies
1
Views
1K
Replies
3
Views
1K
Replies
5
Views
2K
Replies
16
Views
4K
Replies
5
Views
3K
Back
Top