Thread: Tips for improvement

  1. #1
    Registered User
    Join Date
    Apr 2013
    Posts
    21

    Tips for improvement

    This is a code that I actually wrote in C and then changed to C++. It takes a NFA as input and translates it to productions of regular grammar.

    Code:
    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    using namespace std;
    int main(void)
    {
    	char *state = 0, *sym = 0, c,  ns[10][5][5];
    	state = new char [3];
    	sym = new char [3];
    		
    	int statenos, symnos, counter[10][5], i, j, k=0, finstateflag[10];
    
    
    		
    	cout<<"Enter number of states required: ";
    	cin>>statenos;
    	
    	if ( statenos > 11 )
    	{
    		cout<<"Overflow!";
    		exit(0);
    	}
    	
    	cout<<"Enter name of initial state: ";
    	cin>>state[0];
    	for (i=0; i < statenos; i++)
    	{
    		finstateflag[i] = 0;
    	}
    
    
    	for ( i = 1; i < statenos; i ++ )
    	{
    		cout<<"\nEnter name of state "<<i+1<<" : ";
    		cin>>state[i];
    		
    		cout<<"If it is a final state press Y, else press N: ";
    		cin>>c;
    				
    		switch(c)
    		{
    		case 'Y':
    			finstateflag[i] = 1;
    			break;
    		
    		case 'y':
    			finstateflag[i] = 1;
    			break;
    		
    		case 'N':
    			finstateflag[i] = 0;
    			break;
    		
    		case 'n':
    			finstateflag[i] = 0;
    			break;
    
    
    		default:
    			cout<<"Wrong input! Aborted!";
    			exit(0);
    		}
    	}
    			
    	cout<<endl<<"Enter number of symbols: ";
    	cin>>symnos;
    
    
    	if ( symnos > 10 )
    	{
    		cout<<"Overflow!!";
    		exit(0);
    	}
    	  
    	for ( i = 0; i < symnos; i++ )
    	{
    		cout<<"Enter symbol "<<i+1<<" : ";
    		cin>>sym[i];
    	}
    
    
    	for (i = 0; i < 10; i++)
    	{
    		for (j = 0; j < 5; j++)
    		{
    			counter[i][j] = 0;
    			for (k = 0; k < 5; k++)
    			{
    				ns[i][j][k] = '0';
    			}
    		}
    	}
    
    
    
    
    
    
    	for ( i = 0; i < statenos; i++ )
    	{
    		if (finstateflag[i] == 1)
    			continue;
    		else
    		{
    			for ( j = 0; j < symnos; j++ )
    			{
    				k = 0;
    
    
    				do
    				{
    					cout<<"Enter NS for "<<state[i]<<" when "<<sym[j]<<" is entered: ";
    					cin>>c;
    					
    					if ( c != '0')
    					{
    						ns[i][j][k] = c;
    						k++;
    						counter[i][j] = k; 
    					}
    					else
    						break;
    				} while ( c != '0');
    				
    			}
    		}
    	}
    	
    
    
    	for ( i = 0; i < statenos; i++ )
    	{
    		if (finstateflag[i] == 1)
    		{
    			cout<<endl<<state[i]<<" -> lamda";
    			continue;
    		}
    		else
    		{
    		for ( j = 0; j < symnos; j++ )
    		{
    			k = counter[i][j] - 1;
    			while ( k >= 0 )
    			{				
    				cout<<endl<<state[i]<<" -> "<<sym[j]<<ns[i][j][k];
    				k--;
    			}
    		}
    		}
    	}
    getchar();
    }
    I want to create a Class for States with a two-dimensional vector in it for NS. However, the size of NS is an unknown and will be entered by the user. So, how am I supposed to initialize the vector? Also, the number of objects of class States depends on the user's input. Am I supposed to create a pointer of objects? Can anybody help me on its implementation? Just a few tips would do.

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    I want to create a Class for States with a two-dimensional vector in it for NS. However, the size of NS is an unknown and will be entered by the user.
    Vectors are dynamic data structures, they can grow or shrink to fit the data.

    So, how am I supposed to initialize the vector?
    There are several ways, you may want to start by studying documentation for the vector class.

    Also, the number of objects of class States depends on the user's input. Am I supposed to create a pointer of objects?
    This is really a design issue, but I recommend trying to stay away from pointers if at all possible. Start by figuring out what data the class will hold, then determine if you need one or several classes to encapsulate this information.

    I also recommend you start using std::string instead of C-strings.

    Jim

  3. #3
    Registered User
    Join Date
    Apr 2013
    Posts
    21
    Thanks for that link, Jim. I understand that for resizing a vector, we need to write vectorname.resize(newsize). Now, how can I do that for a 2D-vector? I mean, suppose in the class States, I'm declaring and initialising a 2D character vector like this: vector< vector<char> > NextState( 10, vector<char>(10,'0')). This gives me a 2d 10x10 vector, right? Now, if I want it to be, say of size statenos. X statenos., what am I supposed to do? Writing state1.Nextstate.resize(statenos) won't do it. What should we write then?
    Last edited by Mycroft Holmes; 04-17-2013 at 04:14 AM.

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    How about

    std::vector< std::vector<char> > NextState( statenos, std::vector<char>(statenos) );

    ?
    Just create the vector after you've inputted the size.
    Here's something more to ponder, as well:
    SourceForge.net: Safer arrays in Cpp - cpwiki

    You can also get rid of the "void" in main. That's a legacy required in C, but optional in C++.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Registered User
    Join Date
    Apr 2013
    Posts
    21
    Well, can I do it a bit differently? Suppose in class States, we define the vector as vector< vector<char> > NextStates; and then in main function, we resize it using
    State1.NextStates.resize( statenos , vector<char>( statenos, 'NULL' ) ). Another problem is that the number of states depends on the user input statenos. So the number of objects is also a variable. How am I supposed to define and initialise the objects? Will it be another vector? I'm a bit lost here. The hierarchy is like this: There are 'statenos' number of states. Each state has a bunch of Nextstates for each symbol. The number of symbols is also a variable. How am I supposed to implement this without 3d vectors or pointers?

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I'm a bit lost on what you are trying to convey.
    std::vector is a dynamic array. That means you can decide its size entirely at runtime with a size stored in a variable inputted from the user, if you so want.
    std::vector also supports push_back. Unless you absolutely need to choose the size at the beginning, you can also use that (though it may be a little tougher with 2d arrays).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    It really sounds like you should be using classes that contain vectors instead of using raw vectors.

    What exactly are you trying to accomplish?

    What exactly is a "NFA"?

    Jim

  8. #8
    Registered User
    Join Date
    Apr 2013
    Posts
    21
    NFA is Non-deterministic Finite Automation. An example: Tips for improvement-capture-jpg
    See the circles? They are states. Here we have 3 states: A, B, C.
    B has a double circle, indicating it's a final state.
    Now see those arrows with letters on it? The arrows are transitions and letters are symbols.
    Here we have two symbols: a, b. Hence, the statenos = 3, symnos = 2.
    Now, notice the arrows.
    From state A, there's one arrow going to B with symbol a, one to C with symbol a, and there's one self-loop with symbol b. So, we say, for state A and symbol a, the Next States are (B, C) and for state A and symbol b, the Next States are (A).
    Similarly for state B, we have Next States (B) for symbol a and we have Next States (C) for symbol b.
    And, as for state C, we have (A) for symbol b, and the Next State for symbol a is empty.
    So, it boils down to this. We have a variable number of states and symbols. For each state and symbol, we have a set of Next States. The number of states in the set Next State for each state and symbol is again a variable but will be at most equal to statenos. This is the gist of it.

  9. #9
    Registered User
    Join Date
    Apr 2013
    Posts
    21
    Phew. That took me half an hour to post. Every time I tried to post it, it asked to to put Code Tags. At last I figured out that it was because I used braces instead of parentheses.

  10. #10
    Registered User
    Join Date
    Apr 2013
    Posts
    21
    That's the point, Elysia. How am I supposed to push back in a 2D array?

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Either you preallocate:

    std::vector<std::vector<T>> v(N, std::vector<T>(M));
    v[a][n] = ...;

    Or you allocate new rows as needed:

    std::vector<std::vector<T>> v;

    v.push_back(std::vector<T>());
    //v.emplace_back(); // <--- Even better - requires C++11
    v[0].push_back(...);

    // ...

    v.push_back(std::vector<T>());
    //v.emplace_back(); // <--- Even better - requires C++11
    a[b].push_back(...);
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Registered User
    Join Date
    Apr 2013
    Posts
    21
    I wrote the code sans class. The problem is that I had to use a 3D Vector. And while debugging, whenever I try to assign a value to its element [0][0][0], it crashes, saying "Vector Subscript out of range". Here's the code.
    Code:
    #include <cstdio>#include <cstdlib>
    #include <iostream>
    #include <vector>
    
    
    
    
    using namespace std;
    
    
    
    
    char flagcheck ( char );
    
    
    
    
    char flagcheck( char flag )
    {
        while (( flag != 'Y' ) && ( flag != 'y' ) && ( flag != 'N' ) && ( flag != 'n' ))
        {
            cout<<"Wrong input! Try again!" ;
            cin>>flag;
        }
    
    
        return flag;
    }
    
    
    
    
    int main()
    {
        vector<char> state;
        vector<char> symbol;
        vector<int> finstateflag;
    
    
        char a, flag;
        int i, j, k, statenos, symnos, c;
    
    
    
    
        cout<<"Enter the initial state: ";
        cin>>a;
        state.push_back (a);
        finstateflag.push_back (0);
    
    
        
        for  ( i = 2; a != '0'; i++ )
        {
            cout<<"Enter state "<<i<<". Press 0 to end: ";
            cin>>a;
            if ( a == '0')
            {
                break;
            }
            state.push_back (a);
    
    
            cout<<"Press Y if the state is a final state, else press N: ";
            cin>>flag;
            
            flag = flagcheck( flag );
            
            switch(flag)
            {
            case 'Y':
                finstateflag.push_back (1);
                break;
            
            case 'y':
                finstateflag.push_back (1);
                break;
            
            case 'N':
                finstateflag.push_back (0);
                break;
            
            case 'n':
                finstateflag.push_back (0);
                break;
    
    
            default:
                cout<<"Wrong input! Aborted!";
                exit(0);
            }
        }
    
    
        cout<<"Enter symbol 1: ";
        cin>>a;
        symbol.push_back (a);
        
        for  ( i = 2; a != '0'; i++ )
        {
            cout<<"Enter symbol "<<i<<". Press 0 to end: ";
            cin>>a;
            if ( a == '0')
            {
                break;
            }
            symbol.push_back (a);
        }
    
    
        statenos = state.size();
        symnos = symbol.size();
    
    
        vector < vector < vector < char > > > NextState ( state.size(), vector < vector < char > > ( symbol.size(), vector < char > ( state.size(), 'A' )));
        vector < vector < int > > counter ( state.size(), vector < int > ( symbol.size(), 0 ));
    
    
    
    
        for ( i = 0; i < statenos; i++ )
        {
            if (finstateflag[i] == 1)
                continue;
            else
            {
                for ( j = 0; j < symnos; j++ )
                {
                    k = 0;
    
    
                    do
                    {
                        cout<<"Enter Next State for "<<state[i]<<" when "<<symbol[j]<<" is entered. ";
                        cout<<"Press 0 if there is no state left : ";
                        cin>>c;
                        
                        if ( c != '0')
                        {
                            NextState[i][j][k] = c;
                            k++;
                            counter[i][j] = k; 
                        }
                        else
                            break;
                    } while ( c != '0');
                    
                }
            }
        }
    
    
        for ( i = 0; i < statenos; i++ )
        {
            if (finstateflag[i] == 1)
            {
                cout<<endl<<state[i]<<" -> lamda";
                continue;
            }
            else
            {
    
    
                for ( j = 0; j < symnos; j++ )
                {
                    k = counter[i][j] - 1;
                    while ( k >= 0 )
                    {                
                        cout<<endl<<state[i]<<" -> "<<symbol[j]<<NextState[i][j][k];
                        k--;
                    }
                }
            }
    
    
        }
    
    
        getchar();
    }
    Now, I believe when I'm initialising a vector using:
    Code:
    vector < vector < vector < char > > > NextState ( state.size(), vector < vector < char > > ( symbol.size(), vector < char > ( state.size(), 'A' )));
    , the vector size is [statesize][symbolsize][statesize] and all elements are initialised with A. Then why does the program crash when i'm trying to change the value of the element [0][0][0]?

  13. #13
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    the vector size is [statesize][symbolsize][statesize]
    First I would test you assumption by printing the sizes of the vector and the contents. Place this right after you define you vector<vector<vector>>>.
    Code:
    cout << NextState.size() << " ";
    cout << NextState[0].size() << " ";
    cout << NextState[0][0].size() << endl;
    
       for(size_t i = 0; i < NextState.size(); ++i)
       {
          cout << "I: " << i << endl;
          for(size_t j = 0; j < NextState[i].size(); ++j)
          {
             cout << "J: " << j << endl;
             for(size_t k = 0; k < NextState[i][j].size(); ++k)
             {
                cout << NextState[i][j][k] << " ";
             }
             cout << endl;
          }
       }
    Jim

  14. #14
    Registered User
    Join Date
    Apr 2013
    Posts
    21
    Well, I used a breakpoint at line 140 of my code, and saw the locals. Nothing seems to be wrong. Tips for improvement-locals-jpg

  15. #15
    Registered User
    Join Date
    Apr 2013
    Posts
    21
    Sorry to bother you. I got my error, I think. c is declared to be an integer, not a character.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Any Room For Improvement?
    By Clinthill98 in forum C++ Programming
    Replies: 2
    Last Post: 04-01-2010, 07:11 AM
  2. An improvement for the board...
    By Queatrix in forum A Brief History of Cprogramming.com
    Replies: 37
    Last Post: 09-19-2006, 05:32 PM
  3. code improvement before i go further!!
    By samirself in forum C Programming
    Replies: 2
    Last Post: 06-24-2005, 11:52 PM
  4. Howz this for improvement!
    By cyberCLoWn in forum C++ Programming
    Replies: 5
    Last Post: 01-18-2004, 06:58 PM
  5. C++ improvement
    By frenchfry164 in forum A Brief History of Cprogramming.com
    Replies: 7
    Last Post: 11-17-2003, 12:46 AM

Tags for this Thread