Need help with understanding how to code

I'm at a total loss. I understand individual pieces. I know how cout, cin work. I know how variables, functions and data types work. I've coded programs before. But for the life of me, I can't figure out how to put the pieces together on this one.

My goal is to write a program that can correct titles so that the first letter is capitalized and all others lowercased. The output would eliminate any extra spacing.

"the 5TH wAVE
the cAT in thE HAT
onE fish two FISh red fISh bLuE Fish"

should become:

"The 5th Wave
The Cat In The Hat
One Fish Two Fish Red Fish Blue Fish"

The requirement is to use at least two functions and to use the string type, and that the content is to be read from another file via Linux redirection.

I know I should use Toupper and Tolower, the for loop and if/else to implement this. But I can't figure out how to piece everything together. This is what I have so 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

#include <iostream>
#include <cctype>
#include <string>
using namespace std;

int main()
{

  string sentence;
  size = getline;

  cin.getline >> sentence;

  sentence = toupper(sentence);
  for (int i = 1; i < size; i++)
    {
      if (sentence(i-1)	== ' ')
        sentence[1] = toupper;
      else
        sentence[1] = tolower;


  return 0;
}
So how would you do it on paper ?
just do it one character at a time, forgoing the toupper and tolower functions. Keep track of what the previous character was with a boolean.

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
#include <iostream>
#include <cctype>
#include <string>
using namespace std;

int main()
{

  string sentence;
  int size = 0;
  int i = 0;
  char a = 0;
  bool prevletter = 1; //capitalize first letter
  cout << "Write Some Stuff...\n";
  getline (cin, sentence);
  size = sentence.length();

  while (i < size)
    {
    a = sentence[i];
    if (prevletter) //uppercase
       {
       if (a < 123 && a > 96)
          {
          a=a-32;
          }
       } else { //lowercase
       if (a < 91 && a > 64)
          {
          a=a+32;
          }
       }
    cout << a;
    prevletter = 0;
    if (a==32) { prevletter = 1;} //a space
    i++;
    }
  return 0;
}


A variation would be to capitalize the first letter after ANY separator, not just a space.

Remember, a char is just an 8 bit int. Shorter than short.
Last edited on
There's the coding. It works.

The part you have to do is use C/C++ well enough to read it, and then write the same thing using the functions and methods you've been taught rather than raw like what I did, because if you hand that in you're gonna get reamed because its gonna look way different than what everyone else did.
Hello crackedice,

The first thing you should do is compile your program and try to resolve the errors before you post your code. Include
any error messages that you do not understand. It is best to copy and paste the exact error message.

In the code that you posted there are many errors that need corrected before you can proceed.

First is line 5.

Try to avoid using using namespace std; in your programs it may seem easy now, but WILL get you in trouble some day.

It is better to learn to qualify what is in the standard name space with "std::" and then to learn what is in the standard name space now while it is easy.

What you are most likely to use for now is "std::cout", "std::cin" and "std::endl". About a week or so of typing this and you will not even notice that you are doing it.

Line 10 should be qualified with "std::".

Line 11 will not work at all. The compiler is considering the name on each side of "=" as being a variable and neither has a type. Second at this point "getline" has no value to use.

Line 13 the "std::cin.getline" is uded in the wrong way see:
http://www.cplusplus.com/reference/istream/istream/getline/?kw=cin.getline

Line 15 looks like it is calling a function "toupper" that takes a string and returns a string. Then you follow this with a function that should be in a function. I would refrain from calling this function "toupper". "ChangeToUppercase" would be a better choice to avoid any conflict with any built in function called "toupper" which can be found in the "cctype" header file.

The for loop in the () size is an undefined variable at this point. C++ is a zero based language so your for loop is missing the first character of the string. You will either need to take care of this before the for loop or within the for loop. This should actually be in a function that returns the corrected string. Compiling the file would show that the for loop is missing the closing }.

You program has good potential, but needs some fixing up.

Hope that helps,

Andy
I tried to adapt the program zaphroud wrote, but I'm still having trouble.

I want to have a sepearate function handle the toupper/tolower stuff. I didn't understand zaphroud's method with the 123, 96 numbers, so I'm trying toupper instead.

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

#include <iostream>
#include <cctype>
#include <string>
  using namespace std;

void reformat(string& word)

  int main()
  {

    string sentence;
    int size = 0;
    int i = 0;
    char a = 0;
    getline (cin, sentence)
    return 0;
  }

{
  void reformat(string& word)
  int wlen;
  wlen = word.length();
  word[0] = toupper(word[0]);
  for (int i=1; i<wl
         en; i++)
    word[i] = tolower(word[i]);
}



It outputs errors:
1
2
3
4
5
assign.cpp:10:3: error: expected initializer before ‘intint main()
   ^
assign.cpp:21:1: error: expected unqualified-id before ‘{’ token
 {
Last edited on
Your compiler is giving you an error not because there's anything wrong with int main. You did that part fine. Look up a couple lines and there's a missing semicolon on the function definition line. C/C++ does that all the time - reports something not quite right about where the error in the code is. So if something seems right, trust yourself and check the areas around it instead.

The opening { for the reformat function is on the line above the void instead of the line below. Just move it down and that will fix the second problem.

..Then it will tell you where there's another missing ;

after that it compiles and asks for input successfully.

--

The numbers I used are just outside of the range of the uppercase and lowercase alphabet in the ASCII standard; in order for both conditions to be true (to satisfy the and &&) it has to be inbetween those numbers. Greater than or equal and less than or equal with values for A and Z probably would have been more clear, I guess...

Instead of checking the value and altering it if it needs altering, you can use toupper and tolower - and let the program decide which to use based on if the boolean tracking the previous character indicates a space was there.

Last edited on
Hello crackedice,

Much better. A few well placed blank lines would make reading easier.

An example. Notice the comments:

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
#include <iostream>
#include <cctype>
#include <string>

//using namespace std;  // <--- Best not to use.

void reformat(string& word);  // <--- Missing ';'

int main()
{

	std::string sentence;
	int size = 0;
	int i = 0;
	char a = 0;

	getline(cin, sentence);  // <--- Missing ';'.

	return 0;
}

//{  // <--- Wrong place.
void reformat(string& word)
{
	int wlen;

	wlen = word.length();
	
	word[0] = toupper(word[0]);
	
	for (int i = 1; i < wl
		en; i++)
}


The first error message is a good example of the error being on the line above the line number that is given in the error message. What it kind of says is that line 7 is being read a a function definition not the prototype it should be. It is easy to tell the difference a prototype ends in a ';' where a function definition does not.

The second error message is saying that line 20 should come after line 21. This is hard to understand for beginners, but in time you will come to understand error messages really mean after you have seen them several times.

The "reformat" function needs some work. As it looks, without testing, you are changing the first element of the string to upper case and everything else to lower case.

I would suggest that until you get this function figured out I would pass the string by value or const reference. then inside the function define a temp string and set it equal to the passed string. Then in the end return the temp back to main. You do not have to do it this way I just thought it was better than messing up the original string. The program is small enough that it really does not matter.

In zaphraud's example he/she is using the ASCII decimal value to check the value of a letter range. It is a workable way, but since you have included the header file <cctype> I would make use of the other functions that are available. See: http://www.cplusplus.com/reference/cctype/

To give you an idea I used one for loop starting at zero. The first if statement checked the loop counter being zero and changed the first letter to upper case if needed. Using the function "std::toupper(...)" will change to upper case if needed or do nothing if already upper case. Following this I used an if with two "else if" statements to deal with the rest of the string.

Another hint: for (std::size_t i = 0; i < word.length(); i++). Or you could use "word.size()". "std::size_t" is just another name for "unsigned int" which is what is returned by either function (length() or size()).

I do not want to just give you the code yet until you have a chance to work on it your-self, but I will do everything I can to help you through it.

Hope that helps,

Andy
Thanks. I've made the adjustments and worked more on the code. I think using namedpsace:std is required at this point. At least the instructor hasn't taught the other method yet.

Now it outputs: "The 5th Wave The Cat In The Hat 9th One "

I know it stops at ten words because I put in 10 in the for loop - how can I have it go until the data file is finished? Should I put in a while loop? while cin != end of the getline ? (how is this coded?)

Also, how do I have it put in the same linebreaks as in the data file?

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
#include <iostream>
#include <cctype>
#include <string>
  using namespace std;
 
void reformat(string& word);
 
  int main()
  {
 
    string sentence;
    int size = 0;
    int i = 0;
    char a = 0;
 
    for(i=0; i<10;i++)
      {
      cin >> sentence;
      reformat(sentence);
      cout << sentence << " ";
      }
    cout << endl;
    return 0;
  }
 
 
  void reformat(string& word)
  {
  int wlen;
  wlen = word.length();
  word[0] = toupper(word[0]);
  for (int i=1; i<wlen; i++)
    word[i] = tolower(word[i]);
}


Data file:

1
2
3
the       5TH    wAVE
the  cAT  in thE   HAT
9th onE fish two FISh     red fISh bLuE Fish
Last edited on
Hello crackedice,

I think using namedpsace:std is required at this point.
I would say that your instructor is lazy and does not want to teach what you should be learning now instead of later when you have to learn everything at one time.

At least the instructor hasn't taught the other method yet.
And may never teach you what you need because it is not in the design of what they are told to teach, but this should not hinder you from learning everything that you can where you can. Here you can get all you need to learn for free. All you have to do is read and ask the right questions. If you learn how to qualify what is in different name spaces it will make you look better for learning something that is not taught in class.

I see how the program works now that I have tested it. In main the use of the variable name "sentence" is misleading. I think of a variable name "sentence" as something that will hold several words or what would be an entire sentence. In main you can change "sentence" to "word" and that will not affect the use of "word" in the function because they are different scopes.

Since "cin >>" will read up to the first white space or new line which ever comes first. That why, along with the variable "sentence", I was a little confused.

The program works one word at a time, but you have done nothing to read from a file. You need to include the header file "<fstream>" and actually open a file stream to use a file.

This code is more than you need, but I found it useful when first learning to use a file stream.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
std::string iFileName{ "" };  // <--- Put file name here.

std::ifstream inFile;

inFile.open(iFileName);

if (inFile.is_open())
{
	std::cout << "\n File " << iFileName << " is open" << std::endl;
	std::this_thread::sleep_for(std::chrono::seconds(2));  // <--- Needs header files chrono" and "thread".
}
else
{
	std::cout << "\n File " << iFileName << " did not open" << std::endl;
	std::this_thread::sleep_for(std::chrono::seconds(3));  // <--- Needs header files chrono" and "thread".
	exit(1);  // <--- If it is not open there is no need to continue.
}

In the if statement you can comment out these lines when you do not need them any more. Then in place of the for loop I would use: while (inFile >> word). to read the whole file. This will allow you to read a whole file of unknown length. When you have learned more about using file streams this code can be shortened. When you learn how to do that you will have learned something useful.

In main I replaced the for loop with a while loop to allow reading the whole file. Inside the loop I used the code if (inFile.peek() == '\n') std::cout << '\n' << std::endl; to check for a new line (\n) and if true it prints a new line and a blank line before the next line. the "peek" function is a way of looking at the input stream without extracting the character from the input buffer. Although you could just as easily extract the new line from the buffer and print it.

The while loop looks like:
1
2
3
4
5
6
while (inFile >> word)
{
	reformat(word);
	std::cout << word << ' ';
	if (inFile.peek() == '\n') std::cout << '\n' <<  std::endl;
}


Hope that helps,

Andy
Topic archived. No new replies allowed.