Hello, so my assignment was to take a text file that contains a properly written C++ program code and to go through that code character by character and output all the comments in that code to another text file.
This is what I got so far, basically I`m wondering how to start copying characters right after "//" or "/*", at the moment it would output all the comments like this "// this is a comment", it would also output the '/' operator and anything after it until a new line, since char can only hold a single symbol. I also don`t need "//" or "/*" to appear in the output. Thanks in advance.

#include <iostream>
#include <fstream>
using namespace std;
int main ()
{
    char c;
    ifstream fin ("given.txt");
    ofstream fout("comments.txt");
    if (fout.is_open())
    {
       fin.get(c);
       while (!fin.eof())
       {
           if (c == '/')
           {
               while (c != '\n')
               {
                   fout.put(c);
                   fin.get(c);
               }
               fout << endl;
           }
           fin.get(c);
       }
       fout.close();
    }
    fin.close();
}

Recommended Answers

All 12 Replies

Line 14. "/" is a legitimate C++ operator, not a comment. You'll be treating "8 / 2" as a partial comment. You have at minimum 4 tokens: "//", /*", "*/", "\n". Three of them are multi-character, so your code is going to have to be more complex than reading in a character and looking at it.

You have at least 3 states, key phrase is "at least". Get the algorithm down first with pencil and paper before you even start with the program.

1. C++ code.
2. Within a "//" comment.
3. Within a "/*" comment.

The tokens are paired and have a hierarchy. "//" comments are not parsed within a "/*" comment, so you stop looking for "//" and "\n" if you are between a "/*" and a "*/".

It also helps to comment your own code. Then you can use it to test itself.

One approach would be to read in a line at a time, and then parse the line rather than turning copying characters on and off. You can use some of the string operators to manipulate each line, and then write the resulting line to the output. You still will need to keep track of when you are in the “/*” state, since that sort of comment may span multiple lines. This is probably not as efficient and reading and writing character by character, but may be a little simpler to get working. If you do parse line by line, be careful about handling long lines. Vernon makes an important point: Be sure you properly handle the case where “//” occurs between “/*” and “*/”.

#include "stdafx.h"
#include <stdlib.h>
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	// Declaration of files we will use
        FILE *fin;
	FILE *fout;

	// An help-variable to get ascii from files
	int i;

	// Try open given.txt
	if ((fin  = fopen("given.txt", "r")) == NULL) {
		cout << "File <given> cannot open for read!" << endl;
		exit(1);
	}

	// Try open comments.txt
	if ((fout  = fopen("comments.txt", "a")) == NULL) {
		cout << "File <comments> cannot open for append!" << endl;
		exit(1);
	}

	// Non-stop loop, we will stop it inside with "break"
	for (; ;)
	{
		/** Start read letters, if letter equal "/" then we will 
			go inside if { } else we will go at next letter */
		i = fgetc(fin);

		if ( i == '/')
		{
			/** Again 1 non-stop loop, while the letter we want
				to read IS NOT EQUAL "\n" */
			for (; ;)
			{
				// As i wrote up, read while letter IS NOT EQUAL "\n"
				while (i != '\n')
				{ 
					// A secure check for end of file
					if (i == EOF)
					{
						// because it dont change line byself :/ 
						fputc('\n', fout);
						break;
					}

					// Get next letter
					i = fgetc(fin);
					// Write it on "fout" --> comments.txt
					fputc(i, fout);
				}
				
				// We done, lets get out from non-stop for 
				break;
			}
		}

		// A secure check for end of file
		if (i == EOF) 
		{
			// File end, we done, so lets close files :)
			fclose(fin);
			fclose(fout);
			break;
		}
	}

	return 0;
}
commented: Do NOT write homework programs for people. This site is NOT a homework service!! -4

Thanks for the tips, still got loads of cases to handle - stop looking for '//' while Im in a '/*...*/' comment, dont print '*' if its a part of '/*****' or '******/' (which is kinda what I got now), print otherwise, dont print '/' if its a part of '/////' in the beginning of a comment, print otherwise.

#include <iostream>
#include <fstream>
using namespace std;
int main ()
{
    char c, c2;
    int doubleSlash = 0, multiLine = 0;
    ifstream fin ("given.txt");
    ofstream fout("comments.txt");
    if (fout.is_open())
    {
       fin.get(c);
       while (!fin.eof())
       {
            if (c == '/' && c2 == '/') doubleSlash = 1;
            if (doubleSlash == 1 && c != '/')
            {
                fout.put(c);
            }
            if (c == '\n') doubleSlash = 0;

            if (c == '*' && c2 == '/') multiLine = 1;
            if (multiLine == 1 && c != '*')
            {
                fout.put(c);
            }
            if (c == '/' && c2 == '*') multiLine = 0;
            c2 = c;
            fin.get(c);
        }
    }
    fout.close();
    fin.close();
    return 0;
}

Time to back up...

Read a line
Search for // then /*
If you found one of them, process that comment style.
If you found both, which one's first? Process that one only.

If you get a // the rest of the line is a comment -- done.
If you get a /* search for */ -- everything between is a comment
-- if */ not found, read another line and search again. Keep it up until you've found it.

Remember, this is legal:

if (val /*the number being tested*/ != 0 /*has a good value*/ (

I gotta do it character by character.

So when you find a / read the next character.
1) If it's a *, read until */
2) If /, read until EOL
3) If neither, continue on.

Seems about right?
I can`t understand one thing tho, line 34. it wont work properly with logical AND but works just fine with logical OR, I dont get why, cuz the loop should stop when c is '/' AND the previous symbol was '*' but somehow it only works with || :\

#include <iostream>
#include <fstream>
using namespace std;
int main ()
{
    char c;
    int star = 0, starCounter = 0;
    ifstream fin ("given.txt");
    ofstream fout("comments.txt");
    if (fout.is_open())
    {
       fin.get(c);
       while (!fin.eof())
       {
            if (c == '/')
            {
                fin.get(c);
                if(c == '/')
                {
                    fin.get(c);
                    while (c != '\n') //if two consecutive slashes have been found, write until '\n'
                    {
                        fout.put(c);
                        fin.get(c);
                    }
                    fout << endl;
                }
                if (c == '*')
                {
                    while (c == '*') //in case of '/******** ....' the multiple '*' are not outputted since they are most likely used to format the comment
                    {
                        fin.get(c);
                    }
                    while (c != '/' || star != 1) //write until '*/'
                    {
                        if (c == '*')
                        {
                            while (c == '*') //if present, all the '*' symbols are counted in case its a '******/' and they do not need to be outputted, just like before
                            {
                                starCounter++;
                                fin.get(c);
                            }
                            star = 1;
                            if (c == '/') break; //if one or multiple '*' symbols are followed by a '/' stop writing  
                            else //and if one or multiple '*' are not followed by a '/' output them
                            {
                                for (int i=0;i<=starCounter;i++)
                                {
                                    fout << '*';
                                }
                                starCounter = 0;
                            }
                        }
                        else
                        {
                            star = 0;
                        }
                        fout.put(c);
                        fin.get(c);
                    }
                    fout << endl;
                }
            }
            fin.get(c);
        }
    }
    fout.close();
    fin.close();
    return 0;
}

DeMorgan’s Theorem:

A AND B = NOT( (NOT A) OR (NOT B) )
A OR B = NOT( (NOT A) AND (NOT B) )

In your case, you want to stop when c = ‘/’ and star = 1. This is the same as NOT ((c = ‘/’) OR (star != 1)), which is exactly what you have in your code (The “NOT” comes from it being a “while” loop – “while” loops use a “continue” conditional, not a “stop” conditional. If you wanted to write it as a “AND”, you would use ((c = ‘/’) AND (star = 1)), but this gives the “stop” condition, not the “continue” condition. So you would add another negation: while (NOT ((c = ’/’) AND (star = 1))). The first way is more readable, but either should work. This is a place that begs for a comment as to what your logic is supposed to be. Quoting from your post: // loop should stop when c is '/' AND the previous symbol was '*'

It’s great to see you have some decent comments in your code. Don’t be afraid to use detailed comments to explain you logic. Most programmers can read the code and figure out what it is doing. What that can’t always do is read the original programmer’s mind to know what he or she wanted the code to do!

Oh, now I see how it works, thank you very much for pointing that out to me :) Using (!(c == '/' && star == 1)) as a condition works fine as well! Basically the variable star keeps track of whether the last symbol was '*' or not, switching from 1 to 0 as for true and false, so if c equals '/' and star equals 1, it means that it is a '*/' and therefore the end of the comment. I guess I wrote the code in the samme manner as if I was doing that on a piece of paper with my pencil,could have also used a bunch of other variables respresenting a bunch of different states, but oh well, seems to be working fine at the moment.

There are many cases you must catch and is little confused, but this is the way, like you done for // you can do it for other symbols

you must find right place to put other if-elseif-while statement to do that

personaly i cant help you anymore bcause im really boring ;p, i can say you just the way

You must read char by char, when you got /,/*,// then stop copying, when you find */ then start again copying

Will be good for you, ;p that is "like" cheese, make you thing ;p

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.