New to c++ displaying file contents to console

Pages: 12
'/*'
This is a multi-character constant. They're evil. Don't use them except maybe as magic numbers. No, just don't use them. Set your compiler to be as strict as possible so it will complain if you use them.

'*'
This is a single character. This is what you are reading from the file: one character at a time.

You have the right idea so far, except your character confusion is confusing you.

For example, on line 34, you are checking if ch == '/*'. It won't. Ever.

Here are the character sequences you are interested in when handling comments:

  // begins a newline-terminated comment. (Ends with a newline.)

  /* begins a "*/"-terminated comment. (Ends with the two character sequence */.)

  /c (where c is any other character) does not begin a comment.

So, if you read the first character in a potential comment sequence (a /), then you must check to see if it really is a comment. Otherwise it doesn't matter and you can continue on happily.

Again, I suggest you use a switch statement to help you:
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
    while (infile.get( ch ))
        {
        switch (ch)
            {
            case '/':  // Hey, we might be at a comment
                infile.get( ch );
                switch (ch)
                    {
                    case '/':  // newline-terminated comment
                        while ((infile.get( ch )) && (ch != '\n'))
                            ;
                        break;
                    case ...
                    }
                break;

            case '\"':  // Hey, this must begin a string literal! (If you do the next one right.)
                ...
                break;

            case '\\':  // Hmm, this could be something useful too.
                ...
                break;

            default:  // Well, nothing interesting was found.
                break;
            }
        }

Now, there are still a couple of ways you can take this. Keep in mind that comments cannot appear inside string literals. Hence:
1
2
3
4
5
6
#include <iostream>
int main()
  {
  std::cout << "// I am not a comment" << std::endl;
  return 0;
  }

Hope this helps.
Also, C comments (/* */) don't nest, but C++ comments (//) do. You can, however, embed a C comment within a C++ comment (and vice versa) or within a #if 0 ... #endif "comment."
Could you please explain why you put a slash before the double quote when looking for string literals? Why not just search for the double quote character?

Thanks
I think I am finally getting closer. I have another question however. How can I get it to skip things like '\"' because that double quote character is not the beginning of a new string literal, but the program thinks it is. I am assuming I have to check if the character is in between single quote characters somehow so I am going to try to code that.

EDIT: Why does this statement not work?

1
2
3
4
5
6
case "'": //What's inside the single quotes? If there is a double quote character, skip it!

				while (infile.get(ch) && (ch!="'"))
				{
				
				}


I get the error: error C2040: '!=' : 'int' differs in levels of indirection from 'const char [2]'

EDIT EDIT: I fixed the error by doing case '/'' and (ch='/'' and now the program is working great! Now I just need to tweak it to my teacher's expectations. There are 3 extras that give bonus marks that I may ask for help on however.

As for now, when I ask the user to type in a filename, what condition do I check for to see if the file exists or not? I want the program to loop back if the filename is entered incorrectly until a file is found.

Also I cannot get the line count correct. I am thinking I need to add a new case for \n and add one to my counter there?

One more thing haha. What are the last 2 cases you have for? When does a double backslash like that occur?

Thanks
Last edited on
Geez guys.

This '123' is a BAD THING. Don't do that.

This "z" is a STRING LITERAL. It is not a character literal.

This 'x' is a CHARACTER LITERAL. Since you are messing with characters, use them!

The examples I've given so far have been very clear.

Also, if you want to complete this assignment, you must understand escape sequences.
http://www.cppreference.com/wiki/escape_sequences
Duoas thanks for all the help! I have successfully completed the program except for one minor thing. At the beginning of the program when asking for the filename I want to loop until that filename exists. I know I need to use a while statement but not sure what to use as the condition. I tried while (!infile.good); but that did not work for me. I got an error.

Again thanks for all the help!
@th3pr0f37

To do that you can just use a while(1) loop, and then when you open the file just do a
1
2
if(myIfstream.is_open())
   break;


else it will keep repeating.
Last edited on
Thanks for the quick reply. I could not seem to get this code working for me though. Here is my loop.

1
2
3
4
5
6
7
8
9
10
11
12
while (1)
	{
	cout << "Please enter a filename: ";
	cin >> filename;

    ifstream infile(filename);

		if(infile.is_open())
		{
		break;
		}
	}
the problem is ifstream wants a char* and your passing a string, there's a function in string library that allows you to change a string to a char*. Change your code to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
ifstream infile;
while (1)
{
   cout << "Please enter a filename: ";
   cin >> filename;

   infile.open(filename.c_str());

   if(infile.is_open())
      break;
   else
      cout << "Cannot find file. " << endl;
}
Last edited on
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
ifstream infile;
char     ch;

while (true)
{
    cout << "Please enter a filename: " << flush;

    string filename;
    getline( cin, filename );

    infile.open( filename.c_str() );
    if (infile.is_open())
    {
        break;
    }

    cout << "I could not open the file \"" << filename << "\".\n";
}

while (infile.get( ch ))
{
    ...
}

infile.close();

Hope this helps.
what he said ^^
yeah, what he said ^^

;-)
Thanks for the replies guys. However, in my original code I have filename declared as a char array so that should not have cause the error. In fact, I copied Duoas's post directly and I still get errors. For some reason whenever I have a while loop there I get errors. Any ideas?

EDIT: nvm. I added #include <string> and declared string filename outside of the loop and it worked! Thanks you everybody especially Duoas who helped me through this assignment. It is great to know that there are such great people out there who help people just for the sake of helping people. Again, THANK YOU very much and if I run into some problems another time I will be sure to return. Maybe someday I will be able to offer my own advice to people on this forum. Thanks again and see you soon.

ONE LAST QUESTION THOUGH :)
You get bonus marks to correctly process "/"" . How is this possible? Wouldn't the first and second double quote characters open/close the string and the third open a new one?
Last edited on
hi, i have code which is similar to th3pr0f37's code which he posted on page 1 but one i get i get into the while loop when it finds a commented line it no longer prints out the rest of the code from the file, so it will remove the commented line but it also removes everything that comes after the commented line with in the code
Hi I've just recently begun working on a similar assignment to the one everyones having problems with. I've read through this forum and have been trying to piece together my own code from ideas from user posts. It seemed to be starting to work.
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
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
	string filename;
	ifstream infile;

	//gets filename
	while (true){
    cout << "Please enter a filename: ";
    getline(cin, filename);
    infile.open( filename.c_str() );
		if ( infile.is_open() )	{
			break;
		}
    cout << filename << " is an invalid filename.\n";
	}
 
    char ch = 0;
	unsigned linenum = 1;
	
	while (infile.get( ch )) {
	
	////count line
	//cout.put( ch );
	//if (ch == '\n')	{
 //   cout << linenum << ": ";
 //   linenum++;
	//}		

	 switch (ch){
            case '/': 
                infile.get( ch );
                switch (ch){
                    case '/': 
                        while ((infile.get( ch )) && (ch != '\n'))
                        break;
                    }
                break;

            case '\"':
					while (infile.get(ch) && (ch!='"')){
						cout.put(ch);
					}
					break;

            case '\\': 
                break;

            default:
                break;
            }
        }
   

	}	


My switch statement is obviously incomplete, but when I put the while loop inside case '\"': the program stopped reading my filename correctly and told me every filename I entered was incorrect.
Use Proper Indentation.

Use Functions.

Your code should look something like this:
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
void skip_commentary( ifstream& infile, unsigned& line_number )
  {
  /* This function needs to read the next character from file.
     If it is an asterisk '*' then you need to read until you find another
     asterisk followed by a forward slash: '*' + '/'.
     If it is a forward slash, read until you find a newline: '\n'.
     If it is neither, simply return.
     Remember to bump the line number if you read past a newline '\n'.
   */
  }

void read_and_print_string_literal( ifstream& infile, unsigned& line_number )
  {
  /* This function needs to read and print every character until it encounters
     a '\"' that is not following a back slash '\\'.
     It is a nice touch to print the current line number before the string literal.
   */
  }

void skip_character_literal( ifstream& infile, unsigned& line_number )
  {
  /* This function needs to read (but not print) every character until it encounters
     a '\'' that is not following a back slash '\\'.
     Remember to bump the line number if you read past a newline '\n'.
   */
  }

int main()
  {
  unsigned line_number = 1;  // This is only useful if you wish to print the line number
                             // that the string literals you find are found on.
  ifstream infile;
  char     ch;

  // (get filename from user and open file here)

  // This is where we do our main processing: looking for one of:
  //  - a comment (potentially)
  //  - a string literal
  //  - an escaped character sequence
  //  - a character literal
  //  - a newline (you can skip this if you aren't counting lines)
  // Once found, we use a sub-function to process the specific entity.
  while (infile.get( ch ))
    switch (ch)
      {
      case '/':  skip_commentary( infile, line_number ); break;
      case '\"': read_and_print_string_literal( infile, line_number ); break;
      case '\\': infile.get( ch ); break;
      case '\'': skip_character_literal( infile, line_number ); break;
      case '\n': line_number++;
      }

  infile.close();
  return 0;
  }

This is a VERY BIG bone for you all. Good luck!
Topic archived. No new replies allowed.
Pages: 12