none
2D string array input and output problems RRS feed

  • Question

  • Hello and thank for the help I am getting! When I execute the first choice in this program, it skips the first element when it asks to input data. It will enter the title and actor for a DVD collection. Then for the second choice, it won't print anything. I want it to show the input entered. How or what do I need to do?

    Thanks,

    # include <iostream>
    # include <string>
    
    using namespace std;
    struct DVD
    {
    	string title[3][3];
    	const int SIZE = 3;
    };
    int getChoice(int);
    DVD enterData(string[3][3], int);
    void showData(string[3][3], int);
    void sortData(string[3][3], int);
    void swap(string &, string &);
    
    int main()
    {
    	const int ENTER_DATA = 1,
    		SHOW_DATA = 2,
    		SORT_DATA = 3,
    		EXIT = 4;
    	int choice = 0;
    	while (choice != 4)
    	{
    		choice = getChoice(choice);
    		DVD collect;
    		switch (choice)
    		{
    
    		case ENTER_DATA:
    			enterData(collect.title,collect.SIZE);
    			break;
    		case SHOW_DATA:
    			showData(collect.title,collect.SIZE);
    			break;
    		case SORT_DATA:
    			sortData(collect.title,collect.SIZE);
    			break;
    		
    		}
    	}
    	system("pause");
    	return 0;
    
    }
    int getChoice(int choice)
    {
    	cout << "Brian's DVD collection" << endl;
    	cout << "Choose from the following :" << endl;
    	cout << "1. Enter the title and main actor in the DVD : " << endl;
    	cout << "2.Show the DVD's : " << endl;
    	cout << "3.Sort the titles " << endl;
    	cout << "4. Exit :" << endl;
    	cout << "What is you choice? : " << endl;
    	cin >> choice;
    	while (choice > 0 || choice < 5)
    	{
    		return choice;
    
    	}
    	return 0;
    }
    DVD enterData(string title[3][3], int SIZE)
    {
    	int i, j;
    	DVD comedy;
    	for (i = 0; i < SIZE; i++)
    	{
    		for (j = 0; j < SIZE; j++)
    		{
    			cout <<"Enter element [" << i << "][" << j << "]: ";
    			cin.clear();
    			getline(cin,comedy.title[i][j]);
    			cout << endl;
    		}
    	}
    	return comedy;
    
    
    }
    void showData(string title[3][3], int SIZE)
    {
    	int i, j;
    	DVD show;
    	cout << "Here are the DVD titles :" << endl;
    	for (i = 0; i <SIZE; i++)
    	{
    		for (j = 0; j < SIZE; j++)
    		{
    			cout << show.title[i][j]<<endl;     
    		}
    		cout<<"Done"<<endl;
    	}
    }
    void sortData(string title[3][3], int SIZE)
    {
    	int x;
    	for (int k = 0; k < 3; k++)
    	{
    		for (int m = 0; m < 3; m++)
    		{
    			x = m + 1;
    			for (int i = k; i < 3; i++)
    			{
    				for (int j = x; j < 3; j++)
    				{
    					if (title[k][m] > title[i][j])
    						swap(title[k][m], title[i][j]);
    				}
    				x = 0;
    			}
    		}
    	}
    
    	for (int i = 0; i < 3; i++)
    	{
    		for (int j = 0; j < 3; j++)
    		{
    			cout << title[i][j] << " ";
    		}
    	}
    }
    void swap(string &x, string &y)
    {
    	string temp = x;
    	x = y;
    	y = temp;
    }

    Saturday, October 19, 2019 10:16 PM

Answers

  • Hello and thank for the help I am getting! When I execute the first choice in this program, it skips the first element when it asks to input data. It will enter the title and actor for a DVD collection. Then for the second choice, it won't print anything. I want it to show the input entered. How or what do I need to do?

    Thanks,

    # include <iostream>
    # include <string>
    
    using namespace std;
    struct DVD
    {
    	string title[3][3];
    	const int SIZE = 3;
    };
    int getChoice(int);
    DVD enterData(string[3][3], int);
    void showData(string[3][3], int);
    void sortData(string[3][3], int);
    void swap(string &, string &);
    
    int main()
    {
    	const int ENTER_DATA = 1,
    		SHOW_DATA = 2,
    		SORT_DATA = 3,
    		EXIT = 4;
    	int choice = 0;
    	while (choice != 4)
    	{
    		choice = getChoice(choice);
    		DVD collect;
    		switch (choice)
    		{
    
    		case ENTER_DATA:
    			enterData(collect.title,collect.SIZE);
    			break;
    		case SHOW_DATA:
    			showData(collect.title,collect.SIZE);
    			break;
    		case SORT_DATA:
    			sortData(collect.title,collect.SIZE);
    			break;
    		
    		}
    	}
    	system("pause");
    	return 0;
    
    }
    int getChoice(int choice)
    {
    	cout << "Brian's DVD collection" << endl;
    	cout << "Choose from the following :" << endl;
    	cout << "1. Enter the title and main actor in the DVD : " << endl;
    	cout << "2.Show the DVD's : " << endl;
    	cout << "3.Sort the titles " << endl;
    	cout << "4. Exit :" << endl;
    	cout << "What is you choice? : " << endl;
    	cin >> choice;
    	while (choice > 0 || choice < 5)
    

    Is there any value for which this expression will evaluate to false?  What happens if the user enters 6?

    	{
    		return choice;
    
    	}
    	return 0;
    }
    DVD enterData(string title[3][3], int SIZE)
    {
    	int i, j;
    	DVD comedy;
    	for (i = 0; i < SIZE; i++)
    	{
    		for (j = 0; j < SIZE; j++)
    		{
    			cout <<"Enter element [" << i << "][" << j << "]: ";
    			cin.clear();
    			getline(cin,comedy.title[i][j]);
    			cout << endl;
    		}
    	}
    	return comedy;
    

    What happens to the data in comedy after this function returns?

    }
    void showData(string title[3][3], int SIZE)
    {
    	int i, j;
    	DVD show;
    	cout << "Here are the DVD titles :" << endl;
    	for (i = 0; i <SIZE; i++)
    	{
    		for (j = 0; j < SIZE; j++)
    		{
    			cout << show.title[i][j]<<endl; 
    

    What data do you think is present in the members of show?

    } cout<<"Done"<<endl; } } void sortData(string title[3][3], int SIZE) {
    //snip } void swap(string &x, string &y) { string temp = x; x = y; y = temp; }



    • Marked as answer by Brian Holcer Sunday, October 20, 2019 10:27 PM
    Sunday, October 20, 2019 6:04 AM

All replies

  • Here is a radical suggestion.

    Try using the debugger to step through your code as it executes to determine the reasons why it does not perform as desired.

    Posting code in the forum and asking others to debug it for you is easy.  Many community members will be glad to help and provide code fixes for you, but you will learn much more if you try to do it yourself.

    If you have questions about how to debug, feel free to ask them.

    Saturday, October 19, 2019 10:26 PM
  • I have three big questions.

    1) Why do you pass in the title parameter to both enterData and showData if you don't use them?

    2) Why do you return a DVD structure from enterData if you don't save it to anything?

    3) The collect variable that you have in the loop in the main function, you do realise that the lifetime of the structure is bound to the while loop right? This means:

    while (choice != 4)
    {
    	//stack space may be allocated for collect here
    	choice = getChoice(choice);
    	DVD collect; //collect would be initialised here
    	switch (choice)
    	{
    	case ENTER_DATA:
    		enterData(collect.title, collect.SIZE);
    		break;
    	case SHOW_DATA:
    		showData(collect.title, collect.SIZE);
    		break;
    	case SORT_DATA:
    		sortData(collect.title, collect.SIZE);
    		break;
    	}
    	//collect is destroyed here
    	//the stack space for collect may be deallocated here
    }

    So even if you didn't ignore it, the data wouldn't be saved between iterations of the loop.

    To show this in effect here is a little sample:

    #include <iostream>
    #include <string>
    
    struct test
    {
    	std::string string_array[3][3];
    };
    
    int main()
    {
    	int counter = 0;
    
    	while (counter != 4)
    	{
    		std::cout << "Start of loop\n";
    		test test_struct;
    		for (int i = 0; i < 3; ++i)
    		{
    			for (int j = 0; j < 3; ++j)
    			{
    				std::cout << test_struct.string_array[i][j] << "\n";
    			}
    		}
    
    		for (int i = 0; i < 3; ++i)
    		{
    			for (int j = 0; j < 3; ++j)
    			{
    				test_struct.string_array[i][j] = std::to_string(i) + " " + std::to_string(j);
    			}
    		}
    
    		for (int i = 0; i < 3; ++i)
    		{
    			for (int j = 0; j < 3; ++j)
    			{
    				std::cout << test_struct.string_array[i][j] << "\n";
    			}
    		}
    
    		++counter;
    		std::cout << "End of loop\n";
    	}
    }

    This uses a while loop, but it does four iterations of the loop and is not based upon the choice. The output of this starts off as:

    Start of loop









    0 0
    0 1
    0 2
    1 0
    1 1
    1 2
    2 0
    2 1
    2 2
    End of loop
    Start of loop







    If you notice, at the start of the second loop the values in the structure has reset. If you want the contents of this variable to last longer than a single iteration of the loop you must either copy the contents out of the loop into a longer lasting variable or define the variable in a scope outside of the while loop.

    #include <iostream>
    #include <string>
    
    struct test
    {
    	std::string string_array[3][3];
    };
    
    int main()
    {
    	int counter = 0;
    	test test_struct;
    
    	while (counter != 4)
    	{
    		std::cout << "Start of loop\n";
    		for (int i = 0; i < 3; ++i)
    		//rest of the while loop is the same as the last time
    	}
    }

    With test_struct here and not in the while loop, the variable will last until the end of the main function. If you run this code now, you will notice that the contents of the strings will now last between iterations of the loop.

    I would seriously suggest you look up the C++ scoping rules again if you are getting this wrong. The C++ scoping rules can be hard to understand and it can seemingly work because of variable hiding. But to put it simply, a variable defined in a function between any set of {} will only last until the }. So:

    int main()
    {
    	int a;
    	for (int i = 0; i < 10; ++i)
    	{
    		int b = i;
    	} //i and b last until here
    	//b is not available here
    }//a lasts until here

    Notice how each variable will only last until the } closing the block that it was defined in?

    As a more extreme but illustrative example:

    int a; //1
    int main()
    {
    	int a; //2
    	//a here refers to a number 2
    	for (int i = 0; i < 10; ++i)
    	{
    		int a; //3
    
    		//a in the for loop refers to a number 3
    	}
    	//a here refers to a number 2
    }
    
    //a in the global scope refers to a number 1
    
    void fun()
    {
    	//a in here referes to a number 1
    }
    
    void fun2(int a) //4
    {
    	//a here refers to the parameter a, a number 4
    }

    Notice how what a refers to can change? So you have to be very careful of scopes in C++.


    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    Sunday, October 20, 2019 1:05 AM
  • Hello and thank for the help I am getting! When I execute the first choice in this program, it skips the first element when it asks to input data. It will enter the title and actor for a DVD collection. Then for the second choice, it won't print anything. I want it to show the input entered. How or what do I need to do?

    Thanks,

    # include <iostream>
    # include <string>
    
    using namespace std;
    struct DVD
    {
    	string title[3][3];
    	const int SIZE = 3;
    };
    int getChoice(int);
    DVD enterData(string[3][3], int);
    void showData(string[3][3], int);
    void sortData(string[3][3], int);
    void swap(string &, string &);
    
    int main()
    {
    	const int ENTER_DATA = 1,
    		SHOW_DATA = 2,
    		SORT_DATA = 3,
    		EXIT = 4;
    	int choice = 0;
    	while (choice != 4)
    	{
    		choice = getChoice(choice);
    		DVD collect;
    		switch (choice)
    		{
    
    		case ENTER_DATA:
    			enterData(collect.title,collect.SIZE);
    			break;
    		case SHOW_DATA:
    			showData(collect.title,collect.SIZE);
    			break;
    		case SORT_DATA:
    			sortData(collect.title,collect.SIZE);
    			break;
    		
    		}
    	}
    	system("pause");
    	return 0;
    
    }
    int getChoice(int choice)
    {
    	cout << "Brian's DVD collection" << endl;
    	cout << "Choose from the following :" << endl;
    	cout << "1. Enter the title and main actor in the DVD : " << endl;
    	cout << "2.Show the DVD's : " << endl;
    	cout << "3.Sort the titles " << endl;
    	cout << "4. Exit :" << endl;
    	cout << "What is you choice? : " << endl;
    	cin >> choice;
    	while (choice > 0 || choice < 5)
    

    Is there any value for which this expression will evaluate to false?  What happens if the user enters 6?

    	{
    		return choice;
    
    	}
    	return 0;
    }
    DVD enterData(string title[3][3], int SIZE)
    {
    	int i, j;
    	DVD comedy;
    	for (i = 0; i < SIZE; i++)
    	{
    		for (j = 0; j < SIZE; j++)
    		{
    			cout <<"Enter element [" << i << "][" << j << "]: ";
    			cin.clear();
    			getline(cin,comedy.title[i][j]);
    			cout << endl;
    		}
    	}
    	return comedy;
    

    What happens to the data in comedy after this function returns?

    }
    void showData(string title[3][3], int SIZE)
    {
    	int i, j;
    	DVD show;
    	cout << "Here are the DVD titles :" << endl;
    	for (i = 0; i <SIZE; i++)
    	{
    		for (j = 0; j < SIZE; j++)
    		{
    			cout << show.title[i][j]<<endl; 
    

    What data do you think is present in the members of show?

    } cout<<"Done"<<endl; } } void sortData(string title[3][3], int SIZE) {
    //snip } void swap(string &x, string &y) { string temp = x; x = y; y = temp; }



    • Marked as answer by Brian Holcer Sunday, October 20, 2019 10:27 PM
    Sunday, October 20, 2019 6:04 AM