string program

Pages: 12
I am probably well on the wrong path with this one which is why I can't get the program to compile in the slightest.

The assignment instructions are :

The Frozen Tongue Ice Cream Shop sells six flavors of ice cream: chocolate, vanilla, strawberry, mint, rocky road, and
mocha. The shop wants a program that tracks how many scoops of each flavor are sold each day. The console input for each transaction will be the name of a flavor followed by how many scoops of that flavor were sold in that transaction:

example of initial output:

Enter the flavor of the scoops sold (STOP to exit): vanilla
Enter how many scoops were sold: 3

If the user enters a flavor that doesn't match any of the known flavors, the program should display an error message. The user should be allowed to enter as many transactions as desired, and each flavor will likely appear in more than one transaction. Once the user enters "STOP", the program should terminate, and the program should display how many scoops of each flavor were tallied in the program run:

DAILY SCOOP REPORT:
Chocolate: 58
Vanilla: 65
Strawberry: 49
Mint: 23
Rocky Road: 37
Mocha: 31


One way to make sure that the scoops are added to the proper flavor counter is to have a series of decision statements comparing the user's input to each flavor. Another approach would be to use parallel arrays, with an array of strings storing the name of the each flavor and an array of integers storing the count for each flavor at the same index as the
flavor name in the other array.

Write your code so that it handles the flavor name with a space and so that the user's input will be matched to the correct flavor no matter what type of capitalization is used.

Position the output so that the number of scoops for each flavor is right-aligned (assume that the demand for flavors can vary, so the number of scoops for any flavor may be between one and three digits):

Example output:

DAILY SCOOP REPORT:
Chocolate: 92
Vanilla: 103
Strawberry: 89
Mint: 8
Rocky Road: 76
Mocha: 64


I tried to use the switch statement but not sure if that is correct. Also, it wouldn't allow the return of the flavors in the count function due to them being changed int when applying the update to the count, so I tried to use the atoi() but don't really know how to use it and the tutorials I read about it don't fit my situation close enough for me to manipulate it to make it work.

I hope that I have described things enough. Here is my code thus far.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;

String count (string& flavor, string& count, string& chocolate, string& vanilla, string& strawberry, string& mint, string& rocky_road, string& mocha);
int main()
{
	string stop, flavor, count = 0, chocolate, vanilla, strawberry, mint, rocky_road, mocha;
	
	cout << "Welcome to Frozen Tongue Ice Cream Shop\n"<<endl;
	cout << "Please enter the flavor of icecream sold or 'STOP' to exit.\n"<<endl;
		 << "Flavors avaliable:\n"<<endl;
		 << "chocolate\n"<<endl;
		 << "valnilla\n"<<endl;
		 << "strawberry\n"<<endl;
		 << "mint\n"<<endl;
		 << "rocky road\n"<<endl;
		 << "mocha\n"<<endl;
		 << "Enter flavor : ";
	cin.getline >> flavor;

	cout <<"Now enter number of scoops sold\n"<<endl;
	cin >> count;

	if (flavor = 'STOP' || 'stop')
	{
		cout<<"You have chosen to exit the program. Thank you."<<endl;
		exit(1);   
	}

	else count ( flavor, count, chocolate, vanilla, strawberry, mint, rocky_road, mocha);
	
	cout << "\nDAILY SCOOP REPORT: \n"<<endl;
		 << "chocolate :"<<chocolate<<"\n"<<endl;
		 << "vanilla :"<<vanilla<<"\n"<<endl;
		 << "strawberry :"<<strawberry<<"\n"<<endl;
		 << "mint :"<<mint<<"\n"<<endl;
		 << "rocky road :"<<rocky_road<<"\n"<<endl;
		 << "mocha :"<<mocha<<"\n"<<endl;
	
	return 0;
}

String count (string& flavor, string& count, string& chocolate, string& vanilla, string& strawberry, string& mint, string& rocky_road, string& mocha)
{
	string choc, van, str, mt, rrd, mch;

	chocolate = choc;
	vanilla = van;
	strawberry = str;
	mint = mt;
	rocky_road = rrd;
	mocha = mch;

	switch (count) 
	{
	case 'choc' :
		chocolate = count;
		break;
	case 'van':
		vanilla = count;
		break;
	case 'str':
		strawberry = count;
		break;
	case 'mt':
		mint = count;
		break;
	case 'rrd':
		rocky_road = count;
		break;
	case 'mch':
		mocha = count;
		break;
	default:
		cout<<"You have entered an unavaliable flavor. The program will now end."<<endl;
		exit(1);
	}

	cout << atoi(count ())

		return chocolate, vanilla, strawberry, mint, rocky_road, mocha;
}


Thanks in advance for any assistance.
the switch is fine in this case...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

switch (condition)
{
   case a:
      function;
      break;
   case b:
      function;
      break;
   case c:
      function;
      break;
   default:
      break;
}
Last edited on
Ahh there are quite a few errors. Firstly, when using string objects use the getline() function. So line 21 should be: getline(cin, flavor);

Secondly, when comparing a string you should use the pre-defined functions. Therefore line 26 should be: if(!flavor.compare("stop") // notice i have used '!' as this function returns 0 if both strings are the same On the same topic, you have use single quotes for a word; single quotes are only used for single characters. Also, in your assignment brief it says accept flavour names no matter how they are written(capitalization and what not) so I personally would take any input and force all letters to lower case and then do the if statement. Do as you see fit though

Hate to say it but functions aren't your friend, and you need to re-learn them!
http://www.cplusplus.com/doc/tutorial/functions/
(particularly function arguements and return values)

Post back with ammendments and we'll go from there - if need be :)
Last edited on
I have changed the code around quite a bit. Is this way of doing things progress?

I had to create the shortened names for the flavors because the switch statement was giving error that they were too long. I re-read the tutorial on converting the string to an int and I hope that I was able to understand it. The only error I get is that the compiler says that the "+" operator doesn't do anything when it's adding count to its respective flavor counter.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <iostream>
#include <cstdlib>
#include <string>
#include <cctype>
using namespace std;

int main()
{
	string stop, flavor, chocolate, choc, vanilla, van, strawberry, str, mint, mt, rocky_road, rrd, mocha, mc;
	int chocCount = 0, vanCount = 0, strCount = 0, mtCount = 0, rrdCount = 0, mochaCount = 0, flavorI, count = 0;
	
	cout << "Welcome to Frozen Tongue Ice Cream Shop\n"<<endl;
	cout << "Please enter the flavor of icecream sold or 'STOP' to exit.\n"<<endl;
	cout << "Flavors avaliable:\n"<<endl;
	cout << "chocolate\n"<<endl;
	cout << "valnilla\n"<<endl;
	cout << "strawberry\n"<<endl;
	cout << "mint\n"<<endl;
	cout << "rocky road\n"<<endl;
	cout << "mocha\n"<<endl;
	cout << "Enter flavor : ";
	getline (cin, flavor) >> flavor;
	
	flavor = tolower(flavor);

	choc = chocolate;
	van = vanilla;
	str = strawberry;
	mt = mint;
	rrd = rocky_road;
	mc = mocha;

	cout <<"Now enter number of scoops sold\n"<<endl;
	cin >> count;
	
	
	flavorI = atoi("flavor");


	if ( flavor != "STOP" || flavor != "stop")
	{
		switch (flavor) 
	{
	case 'choc' :
		chocCount + count;
		break;
	case 'van':
		vanCount + count;
		break;
	case 'str':
		strCount + count;
		break;
	case 'mt':
		mtCount + count;
		break;
	case 'rrd':
		rrdCount + count;
		break;
	case 'mc':
		mochaCount + count;
		break;
	default:
		cout<<"You have entered an unavaliable flavor. The program will now end."<<endl;
		exit(1);
	}
	}

	else 
	{
		cout<<"You have chosen to exit the program. Thank you."<<endl;
		exit(1);   
	}
	
	cout << "\nDAILY SCOOP REPORT: \n"<<endl;
	cout << "chocolate :"<<chocCount<<"\n"<<endl;
	cout << "vanilla :"<<vanCount<<"\n"<<endl;
	cout << "strawberry :"<<strCount<<"\n"<<endl;
	cout << "mint :"<<mtCount<<"\n"<<endl;
	cout << "rocky road :"<<rrdCount<<"\n"<<endl;
	cout << "mocha :"<<mochaCount<<"\n"<<endl;
	
	return 0;
}


The instructor assigned this project and set it's due date on the same day that we have a big test, so I'm having to both study and this at the same time as other classes and my job. I'm sorry if I miss something that I shouldn't. Thanks again for the assistance.
What is the purpose of all the strings named after the variables flavors?

Also you can't switch/case on a string; it must be an integral or character value. You'll need to use if/else chains to do that with strings. Also, take the others' advice and accept the input as a string, then convert it to lowercase before comparison.
Last edited on
I will post a version of this program for you later as I think you will benefit from seeing a working example more than us constantly sending you away
Right now this is an example program and does not contain everything required by the brief:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <string>

int main()
{
    std::string flavour_input; // string for user input
    std::string flavours[] = { "chocolate", "vanilla", "strawberry", "mint", "rocky road", "mocha" }; // string array containg names of flavours, will be used for parallel arrays mention in brief
    int scoop_count [6] = { 0, 0, 0, 0, 0, 0 }; // integer array to store amount of scoops, will also be used for parallel array with flavours[]
    bool valid_option; // boolean to check a valid input has been given
     
    // while loop so the user can enter values for different ice-cream until STOP is inputted. This is required in the brief - "The user should be allowed to enter as many transactions as desired"       
    while(true) { 
         std::cout << "Enter the flavor of the scoops sold (STOP to exit): ";
         getline(std::cin, flavour_input); // get flavour
         if(!flavour_input.compare("STOP")) // check for "STOP"
            break; // and exit loop 
         
         valid_option = false; // set to false
         
         // this loop checks your input to the text kept in the flavours array and sets 'valid_option' to true if a match is found
         for(int i=0;i<6;i++)
             if(!flavour_input.compare(flavours[i]))
               {
                 valid_option = true;
                 break;
               }
             
         if(!valid_option)
           {
             std::cout << "Invalid Option. Try again.\n\n"; // error message for invalid input
             flavour_input.clear();
             continue; // restart while loop
           }
         
         // This is where the parallel arrays come in use. User input is comapred to all element of the flavour array using 'i' as the index. 
        //Once a match is found, the same index value is used to store the number of scoops in the 'scoop_count' array.    
         for(int i=0;i<6;i++)
           {
             if(!flavour_input.compare(flavours[i])) 
               {
                 std::cout << "Enter how many scoops were sold: ";
                 std::cin >> scoop_count[i];
                 std::cin.ignore();
                 // do error checking
                 std::cout << '\n';
                 break;
               }
           }
    } // end of while loop
    
    // loop used to display contents, note it skips flavours that have no scoops
    for(int i=0;i<6;i++)
      {
        if(!scoop_count[i])
          continue;
        else
          {
            std::cout << flavours[i] << ": " << scoop_count[i] << "\n";;
          }
      }
    
    
    std::cin.get();
    return 0;
}


Study this carefully! It is not often I will do this for someone lol!
I am very very thankful for your assistance mcleano!

The issue I am having right from the start is that if the user enters say

chocolate
5
vanilla
10
chocolate
5
mint
7

the output shows
chocolate 5
vanilla 10
mint 7

It doesn't add the input if the user enters the same flavor 2+ times. How would I fix this?
You would need to add in another integer variable and assign that variable the amount of scoops for that flavour. Then you would just add it to scoop_count[i]:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int scoops = 0;
// rest of code...

for(int i=0;i<6;i++)
           {
             if(!flavour_input.compare(flavours[i])) 
               {
                 std::cout << "Enter how many scoops were sold: ";
                 std::cin >> scoops;
                 std::cin.ignore();
                 // do error checking
                 scoop_count[i] += scoops; // if you're not familiar with this it is equivalent to: scoop_count[i] = scoop_count[i] + scoops
                 scoops = 0; // reset scoops variable
                 std::cout << '\n';
                 break;
               }
           }
Thank you very much mcleano. I have changed around the code to include more of the details from the instructions, but I'm stuck on one last thing.

I have the program working other than a formatting setting that I can't figure out how to get to work.

I need to only print "DAILY SCOOP REPORT" once at the top of the output, but I've moved it around but due to the way the arrays are set up I don't know where to put it.

Here is my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <iostream>
#include <string>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#include <iomanip>

using namespace std;

int main()
{
	string flavor_input, Capitalize;
	string flavors[] = { "Chocolate", "Vanilla", "Strawberry", "Mint", "Rocky Road", "Mocha" }; 
	int scoop_count [6] = { 0, 0, 0, 0, 0, 0 }, scoops = 0, j, k;

	bool valid_option; 

	cout << "Welcome to Frozen Tongue Ice Cream Shop\n"<<endl;
	cout << "Flavors avaliable: "<<endl;
	cout << "Chocolate "<<endl;
	cout << "Valnilla "<<endl;
	cout << "Strawberry "<<endl;
	cout << "Mint "<<endl;
	cout << "Rocky Road "<<endl;
	cout << "Mocha \n"<<endl;

	while(true) { 

		cout << "Please enter the flavor of icecream sold or 'STOP' to exit.\n"<<endl;
		getline (cin, flavor_input); // getline causes rocky road to be accepted with a space between the words. 


		string::iterator it( flavor_input.begin());  //converting the first letter of input to uppercase if not already.

		if (it != flavor_input.end())
			flavor_input[0] = toupper((unsigned char)flavor_input[0]);

		while(++it != flavor_input.end())
		{
			*it = tolower((unsigned char)*it);
		}


		if (flavor_input == "STOP" || flavor_input == "Stop")
			break; 

		valid_option = false; 

		for(int i=0;i<6;i++)  //Checks to see if input matches those of possible inputs.
			if(!flavor_input.compare(flavors[i]))
			{
				valid_option = true;
				break;
			}

			if(!valid_option)
			{
				cout << "Invalid Flavor. Try again.\n\n"; 
				flavor_input.clear();
				continue; 
			}

			for(int i=0;i<6;i++)
			{
				if(!flavor_input.compare(flavors[i])) 
				{
					cout << "Enter how many scoops were sold: ";
					cin >> scoops;
					cin.ignore();
					scoop_count[i] += scoops; 
					scoops = 0; 
					cout << '\n';
					break;
				}
			}
	}


	for(int i=0;i<6;i++)
	{
		if(!scoop_count[i])
			continue;
		else
		{
			cout << "\nDAILY SCOOP REPORT: "<<endl;   
			cout << setiosflags( ios::left )
				<< setw( 11 )  << flavors[i]
			<< resetiosflags( ios::left )
				<< setw( 4 ) << scoop_count[i] << endl;

		}
	}


	cin.get();
	return 0;
}


Thanks again for all of the assistance. It is greatly appreciated.
Last edited on
Not a problem! I don't mind helping someone who is genuinely in need of it and is willing to put some effort in like you have!

It's simple. Just place that cout statement outside of the for loop so it doesn't get outputted on every iteration. When you come across problems like this try and "step-in" to the code, maybe with a pen and paper if need be, and see if you can find a solution tht way.

Something you might like to add just after the section of code where you change the first letter, you may want to then go onto to convert every letter thereafter to lowercase because what will happen if I enter "mInT"?

Also, you will need to slightly alter that setion because at the moment, "Rocky Road" wouldn't get accepted as valid input.
Thank you for all the assistance. I never implied that I wanted anyone to do the work for me and I appreciate your assistance in the areas I'm having problems with.

I figured out that why it wasn't working when I moved the "DAILY SCOOP REPORT" line around. I had renamed the file and when I compiled it, it was outputing the "last working configuration" kinda deal if that makes sense. So I created a new project (the .cpp file has to have a certain name for submission) and put the code in it. Now the line is printed only once.

In the code block below, I have it where it lowers casing for all other letters other than the first or so it seems to be doing. The reason I have the case coding the way I do is that the instructions want the flavor report to print out with first letter of each word cap and lower after that. I am going to look into how to cap the 2nd "R" in Rocky Road, but other than the ignore white-space I don't really know how. Do I need to parse the line?

I tried but it gives error that in the first if statement "syntax error : identifier 'flavor_input'".

1
2
3
4
5
6
7
8
9
10
11
12
13
string::iterator it( flavor_input.begin());  //converting the first letter of input to uppercase if not already.

		if flavor_input = "rocky road"
			(it != flavor_input.end())
			flavor_input[6] = toupper((unsigned char)flavor_input[6]);

		if (it != flavor_input.end())
			flavor_input[0] = toupper((unsigned char)flavor_input[0]);

		while(++it != flavor_input.end())
		{
			*it = tolower((unsigned char)*it);
		}
Also BTW you put:
cout << "valnilla\n"<<endl;


Don't know if you caught that yet ....
Thanks. I typed that part fast w/o thinking. fingers hit wrong key. I was showing my g/f the program as it was and she pointed it out. lol. I prob wouldn't have noticed it if no one had said anything. lol.

I'm still working on capitalizing "road" in rocky road. Anyone able to read my last post before this one and assist I would greatly appreciate it. Thanks again everyone for the assistance thus far.
Your only synatical problem there is on line 3 & 4 - not exactly correct lol (brackets). I'm assuming line 4 is a nested if statement.

Your other problems are with logic. If we take lines 3-5 first, personally I don't like hard-coding value like "flavor_input[6]". I prefer to actually have code that loops through and finds the spaces etc but that is entirely your choice and not really a problem.

However, your while loop is lol. It is undoing everything the code I just spoke about does. You increment the iterator with "++it" to skip the first character and loop through the rest of the text to change it to lower case. But what about flavor_input[6]? Isn't that meant to be a capital?

Also, check if a letter is lowercase before performing actions on it. Along with toupper() and tolower() there is also isupper() and islower().

Try and come up with a new code block to do this. There are multiple different ways to do this.

I've just noticed whilst writing this that the if statments you have don't really make sense. You testing if the iterator is at the end of the string object, but you do no iterator arithmetic to change what its pointing to.
The if statement about "rocky road" and element [6] and such is just something that I tried. I never intended for it to be considered a piece of the code I was confident in. It was only to attempt to get it to work as far as using toupper on the 6th element (the 'r' in "road"). The line means nothing to the actual program other than a failed attempt that I wanted feedback on to see if I was on the right path.

After taking out the if statement with "rocky road", I'm not sure what exactly is going on down to the exact detail, but from what I have made sense of the code is that the first statement converts whatever character that is at element [0] to a capital letter. Then the other if statement (not the one about "rocky road") iterates through the other characters and changes characters from element [1] through the end of string to lowercase.


If I take out the part about "rocky road", the program runs and works fine. The only issue I'm having is converting the 'r' in "road" to a capital 'R'.



I have searched the net and even tho it would eliminate the iterator, it looks as if it would work but I can't get it to merge into my program. The first code block is the original that I copied and pasted from the net. The 2nd block is how I altered it trying to get it to work within my program.


1st block : original copied from website

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <cctype>
#include <string>
using namespace std;

string capitalize_every_first_letter(string s)
{
  if( s.length() > 0 )
    s[0] = toupper(s[0]);

  for( size_t i = 1; i < s.length(); i++){
    if( s[i-1] == ' ' )
      s[i] = toupper(s[i]); 
  }

  return s;
}

int main()
{
  string s = "capitalize every first letter";
  
  cout << s << endl;
  
  s = capitalize_every_first_letter(s);

  cout << s << endl;
}



2nd block : how I altered it to try to make work but it didn't

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <cctype>
#include <string>
using namespace std;

string capitalize_every_first_letter(string flavor_input)
{
  if( flavor_input.length() > 0 )
    flavor_input[0] = toupper(flavor_input[0]);
}

  for( size_t i = 1; i < flavor_input.length(); i++)
{
    if( flavor_input[i-1] == ' ' )
      flavor_input[i] = toupper(flavor_input[i]); 
  }

  return flavor_input;
}

int main()
{
  string flavor_input;
  
  flavor_input = capitalize_every_first_letter();

}


I am going to continue looking at this as well as other ways to get the output as the instructions require. Even after searching Google with many different phrases and wordings, I haven't found a site that has anything that I am able to understand and/or able to take info from. I take notes in class via typing as he talks (especially getting anything he writes on the boards) and even tho I've never missed a class, I don't have any notes on how to do this type of formatting. I've looked through the book to see if it had it and he just didn't cover it, and still came up with nothing.

Any assistance or pointing to somewhere I can get useful information would be greatly appreciated. It's due Tue, but I work every day between now and then and wont have much time to work on it.

Thanks for all of your assistance mcleano. I greatly appreciate all that you have done.
Last edited on
Whats wrong with the code above?

1
2
3
4
5
6
7
8
if( flavor_input.length() > 0 )
    flavor_input[0] = toupper(flavor_input[0]);

for( size_t i = 1; i < flavor_input.length(); i++)
  {
     if( flavor_input[i-1] == ' ' )
       flavor_input[i] = toupper(flavor_input[i]); 
  }
it will allow "rocky road" to be input and print out "Rocky Road" as is instructed, but it won't accept any flavor that has random case. ie "chOcoLate" or "roCkY roAd". Whereas the iterator would lower case all letters behind the first.


When I typed in the instructions/brief in the very first post, I condensed some lines to stay within the character count limit as well as I thought that "...and so that the user's input will be matched to the correct flavor no matter what type of capitalization is used." would be close enough to show what I needed the code to do.

This is the quote from the actual instructions.

Remembering that the comparison operations for strings in C++ use lexicographic ordering, so if a user enters a flavor name with an uppercase letter, the name will not match. Write your code so that the user's input will be matched to the correct flavor no matter what type of capitalization is used.


Would he not be including random case in that as well?

I'm going to try to combine the iterator as well as this code above.
I think I got it to work!

I run the program and type in random caps inlcuding space with "rocky road" and the program runs and outputs the way I believe the insturctor wants.

Here is how I combined them to make it work:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
		string::iterator it( flavor_input.begin());  

		if( flavor_input.length() > 0 )
			flavor_input[0] = toupper(flavor_input[0]);

		while(++it != flavor_input.end())

			*it = tolower((unsigned char)*it);


		for( size_t i = 1; i < flavor_input.length(); i++)
		{
			if( flavor_input[i-1] == ' ' )
				flavor_input[i] = toupper(flavor_input[i]); 
		}


Do you think that from the quote block on my post previous to this that I have things correct?

From what I can see the program looks completely fine, except one thing!

Change the line: if (flavor_input == "STOP" || flavor_input == "Stop") to use the compare function given in the string class, and don't compare this way whether you're using string objects or C-Strings!!!
Pages: 12