c++ begginer program help

S

srenusa

hi, I am quite new to c++ programming and I would need some help with
my college assigment:
write a program which reads input c++ file and removes commentary. The
commentary can be oneline(//) and block commentary(/**/. The name of
the file is read from the command line. use functions and global
variables if neccesary.
here is my code. Thanks in advance


#include <fstream>
#include <stdlib.h>
#include <iostream.h>
#include <stdio.h>
ifstream fp;
ofstream fpp;

void remove (int kraj, char *line){ //removes '//' and saves to file
int i;
for (i = 0; i <= kraj; i++) {
fpp<<line;
}
}
void proceed (int kkraj, char *line,int lenght){
int i;
for (i = kkraj; i<=lenght; i++) {
fpp<<line;
}

}


void main(){
int i ,k, k2,k3;
char filename[12];
char *line;
cout<<"what is the name of the file";
cin>>filename;
fp.open (filename, ios :: in); //file to read from
if (!fp){
cout<<"\n error opening\n";
exit(0);
}
fpp.open("no commentary", ios:ut); //file to save non commentary
program to
if (!fpp){
cout << "Error opening file.\n";
}


while(line=fgets(fp)){
for(i=0; i<strlen(line); i++){
if ((line=='/')&&(line[i+1]=='/')) {
k=i-1;
remove(k, line);

}
if ((line=='/')&&(!begin)&&(line[i+1]=='*')) {
k2=i-1;
remove(k2, line);
begin=1;

}
if ((line=='*')&&(begin)&&(line[i+1]=='/')){
k3=i-1;
begin=0;
proceed(k3, line, strlen(line)) ;
}

}
fp.close() ;
fpp.close() ;
return;
}

}
 
O

osmium

srenusa said:
hi, I am quite new to c++ programming and I would need some help with
my college assigment:
write a program which reads input c++ file and removes commentary. The
commentary can be oneline(//) and block commentary(/**/. The name of
the file is read from the command line. use functions and global
variables if neccesary.
here is my code. Thanks in advance

What kind of help do you want? I didn't try, but I would not expect this to
compile.
I would like to see descriptions as to what the remove and proceed functions
are intended to perform. I would like to see indentation. Does your program
allow for the fact the /* and the matching */ can be on different lines?

void remove (int kraj, char *line){ //removes '//' and saves to file

Surely not!? The instructions were to remove the commentary, not the thing
that indicates it *is* a commentary
fpp.open("no commentary", ios:ut); //file to save non commentary

I'm basing what I said on not compiling on that line. I think it should be
ios::eek:ut. *Two* changes I just scanned the code idly to see if I thought it
might compile.
 
S

srenusa

I have a problem with mismatching: cannot convert ifstream to char:
while(line=fgets(fp)){
for(i=0; i<signed(strlen(line)); i++){


void remove (int kraj, char *line){ //removes '//' and saves to file
I intended this function to write to a new file all characters
until //
characters are placed in char line and I thought that line[1]
represents the first character.


fpp.open("no commentary", ios:ut); //file to save non commentary
tipfeller :)


thx for your help :)
 
V

Victor Bazarov

I have a problem with mismatching: cannot convert ifstream to char:
while(line=fgets(fp)){

What is 'line=fgets(fp)' supposed to do? Perhaps you need to RTFM
about 'fgets' and 'ifstream'...
for(i=0; i<signed(strlen(line)); i++){
[..]

V
 
O

osmium

srenusa wrote:

#include <fstream>
#include <stdlib.h>
#include <iostream.h>
#include <stdio.h>
ifstream fp;
ofstream fpp;

void main(){
int i ,k, k2,k3;
char filename[12];
char *line;
cout<<"what is the name of the file";
cin>>filename;
fp.open (filename, ios :: in); //file to read from
if (!fp){
cout<<"\n error opening\n";
exit(0);
}
fpp.open("no commentary", ios:ut); //file to save non commentary
program to
if (!fpp){
cout << "Error opening file.\n";
}


while(line=fgets(fp)){

line is a char* pointing to God knows where. You are off to a bad start.
There are better ways of doing this. Look into

string line;
getline(fin, line): // where fiin is a file that is open for input
if(!cin)
// almost certainly EOF
else
// do something wise and Good with line.
 
O

osmium

osmium said:
srenusa wrote:

#include <fstream>
#include <stdlib.h>
#include <iostream.h>
#include <stdio.h>
ifstream fp;
ofstream fpp;

void main(){
int i ,k, k2,k3;
char filename[12];
char *line;
cout<<"what is the name of the file";
cin>>filename;
fp.open (filename, ios :: in); //file to read from
if (!fp){
cout<<"\n error opening\n";
exit(0);
}
fpp.open("no commentary", ios:ut); //file to save non commentary
program to
if (!fpp){
cout << "Error opening file.\n";
}


while(line=fgets(fp)){

line is a char* pointing to God knows where. You are off to a bad start.
There are better ways of doing this. Look into

string line;
getline(fin, line): // where fiin is a file that is open for input
if(!cin)

Should be:
if(!fin)
 
R

red floyd

hi, I am quite new to c++ programming and I would need some help with
my college assigment:
write a program which reads input c++ file and removes commentary. The
commentary can be oneline(//) and block commentary(/**/. The name of
the file is read from the command line. use functions and global
variables if neccesary.
here is my code. Thanks in advance


#include <fstream>
#include <stdlib.h>
#include <iostream.h>
Non-standard header. Use said:
#include <stdio.h>
ifstream fp;
ofstream fpp;

void remove (int kraj, char *line){ //removes '//' and saves to file
int i;
for (i = 0; i <= kraj; i++) {
fpp<<line;
}
}
void proceed (int kkraj, char *line,int lenght){
int i;
for (i = kkraj; i<=lenght; i++) {
fpp<<line;
}

}


void main(){
void main is not C++. main() always returns int.

int i ,k, k2,k3;
char filename[12];
char *line;
cout<<"what is the name of the file";
cin>>filename;
fp.open (filename, ios :: in); //file to read from
if (!fp){
cout<<"\n error opening\n";
exit(0);
}
fpp.open("no commentary", ios:ut); //file to save non commentary
program to
if (!fpp){
cout << "Error opening file.\n";
}


while(line=fgets(fp)){
for(i=0; i<strlen(line); i++){
if ((line=='/')&&(line[i+1]=='/')) {
k=i-1;
remove(k, line);

}
if ((line=='/')&&(!begin)&&(line[i+1]=='*')) {
k2=i-1;
remove(k2, line);
begin=1;

}
if ((line=='*')&&(begin)&&(line[i+1]=='/')){
k3=i-1;
begin=0;
proceed(k3, line, strlen(line)) ;
}

}
fp.close() ;
fpp.close() ;
return;
}

}
 
J

James Kanze

srenusa wrote:
string line;
getline(fin, line): // where fiin is a file that is open for input
if(!cin)
// almost certainly EOF
else
// do something wise and Good with line.

This is generally good advice, but I'm wondering. Given that
one of the forms of comments ("/*...*/") can span multiple
lines, I wonder if it wouldn't be better to read character by
character, and use a state machine of some sort. Or use simple
queue (e.g. std::deque) to keep a sliding window of two
characters in the file.
 
J

Jim Langston

Comments in line

hi, I am quite new to c++ programming and I would need some help with
my college assigment:
write a program which reads input c++ file and removes commentary. The
commentary can be oneline(//) and block commentary(/**/. The name of
the file is read from the command line. use functions and global
variables if neccesary.
here is my code. Thanks in advance


#include <fstream>
#include <stdlib.h>
#include <iostream.h>
#include <stdio.h>
ifstream fp;
ofstream fpp;

void remove (int kraj, char *line){ //removes '//' and saves to file

Comment, or function, is wrong. It should remove the // and everything
after it.
I.E. If it was processing this file, for your line above:
void remove (int kraj, char *line){ //removes '//' and saves to file
it should write:
void remove (int kraj, char *line){

So basically you want to write everying up to the //

forget about char* and use std::string, then you can use find, will make
your life a LOT easier.

In otherwords, rewrite this function using std::string, or just move it to
mainline (it's like 2 lines of code
int i;
for (i = 0; i <= kraj; i++) {
fpp<<line;
}
}
void proceed (int kkraj, char *line,int lenght){

No comment, but I take it this function is supposed to write everything
*after* kkraj to the file.
int i;
for (i = kkraj; i<=lenght; i++) {
fpp<<line;
}

}


void main(){
int i ,k, k2,k3;
char filename[12];

12 characters is no where near long enough. forget about char arrays and
use std::string

std::string filename;
char *line;

This is a pointer. But it's not initialized so is pointing to... anything.
Somewhere in memory where most likely you don't want to write. use
std::string and you wont' have a problem.

std::string line;
cout<<"what is the name of the file";
cin>>filename;
fp.open (filename, ios :: in); //file to read from

open takes a char*, and if you make filename a std::string you'd need to do:
fp.open( filename.c_str(), ios::in )
if (!fp){
cout<<"\n error opening\n";
exit(0);
}
fpp.open("no commentary", ios:ut); //file to save non commentary
program to
if (!fpp){
cout << "Error opening file.\n";
}


while(line=fgets(fp)){

How about:
while ( std::getline( line ) )
for(i=0; i<strlen(line); i++){
if ((line=='/')&&(line[i+1]=='/')) {


You can use find() here if you are using a std::string to get the position.
std::string::size_type k = line.find("//");

To see if it found it, compare it with std::string::npos.

if ( k != std::string::npos )
// ...

Now, what you really want at this point is just to keep everything up to the
//
I'd just use substr
line = substr( line, k );
Now the // and everything past it are gone.
k=i-1;
remove(k, line);

Ahh, did you really want to do this? What if you are in the middle of a
block comment? Then you don't want to write this line. You should check to
see about block comments before worrying about the line themselves. Move
this section down below the block comment part.
}
if ((line=='/')&&(!begin)&&(line[i+1]=='*')) {
k2=i-1;
remove(k2, line);
begin=1;


begin = 1
Why not use C++'s bool?
begin = true;
But, of course, you never declared begin anywhere, did you?
And begin isn't very descriptive of what this variable does either. So
before while do something like:
bool BlockComment = false;

here you would do
BlockComment = true;
}
if ((line=='*')&&(begin)&&(line[i+1]=='/')){


Again, with std::string this becomes
k3=i-1;
begin=0;
proceed(k3, line, strlen(line)) ;
}

}
fp.close() ;
fpp.close() ;
return;
}

}

Hmm.. I dont' see where you checked for ending a block comment, or where you
are not writing anything if you started a block comment.

If you read thourgh the comments people provided and look at your code you
should be able to figure it out. You have the logic about 50% right. Using
chae pointers is making it much more difficult then it needs to be,
std::strings will make it a whole lot easier, especially since then you can
use find, substr and other functions.
 
J

Jim Langston

Jim Langston said:
Comments in line

hi, I am quite new to c++ programming and I would need some help with
my college assigment:
write a program which reads input c++ file and removes commentary. The
commentary can be oneline(//) and block commentary(/**/. The name of
the file is read from the command line. use functions and global
variables if neccesary.
here is my code. Thanks in advance


#include <fstream>
#include <stdlib.h>
#include <iostream.h>
#include <stdio.h>
ifstream fp;
ofstream fpp;

void remove (int kraj, char *line){ //removes '//' and saves to file

Comment, or function, is wrong. It should remove the // and everything
after it.
I.E. If it was processing this file, for your line above:
void remove (int kraj, char *line){ //removes '//' and saves to file
it should write:
void remove (int kraj, char *line){

So basically you want to write everying up to the //

forget about char* and use std::string, then you can use find, will make
your life a LOT easier.

In otherwords, rewrite this function using std::string, or just move it to
mainline (it's like 2 lines of code
int i;
for (i = 0; i <= kraj; i++) {
fpp<<line;
}
}
void proceed (int kkraj, char *line,int lenght){

No comment, but I take it this function is supposed to write everything
*after* kkraj to the file.
int i;
for (i = kkraj; i<=lenght; i++) {
fpp<<line;
}

}


void main(){
int i ,k, k2,k3;
char filename[12];

12 characters is no where near long enough. forget about char arrays and
use std::string

std::string filename;
char *line;

This is a pointer. But it's not initialized so is pointing to...
anything. Somewhere in memory where most likely you don't want to write.
use std::string and you wont' have a problem.

std::string line;
cout<<"what is the name of the file";
cin>>filename;
fp.open (filename, ios :: in); //file to read from

open takes a char*, and if you make filename a std::string you'd need to
do:
fp.open( filename.c_str(), ios::in )
if (!fp){
cout<<"\n error opening\n";
exit(0);
}
fpp.open("no commentary", ios:ut); //file to save non commentary
program to
if (!fpp){
cout << "Error opening file.\n";
}


while(line=fgets(fp)){

How about:
while ( std::getline( line ) )

Sorry, that's
while ( std::getline( fp, line ))
for(i=0; i<strlen(line); i++){
if ((line=='/')&&(line[i+1]=='/')) {


You can use find() here if you are using a std::string to get the
position.
std::string::size_type k = line.find("//");

To see if it found it, compare it with std::string::npos.

if ( k != std::string::npos )
// ...

Now, what you really want at this point is just to keep everything up to
the //
I'd just use substr
line = substr( line, k );
Now the // and everything past it are gone.
k=i-1;
remove(k, line);

Ahh, did you really want to do this? What if you are in the middle of a
block comment? Then you don't want to write this line. You should check
to see about block comments before worrying about the line themselves.
Move this section down below the block comment part.
}
if ((line=='/')&&(!begin)&&(line[i+1]=='*')) {
k2=i-1;
remove(k2, line);
begin=1;


begin = 1
Why not use C++'s bool?
begin = true;
But, of course, you never declared begin anywhere, did you?
And begin isn't very descriptive of what this variable does either. So
before while do something like:
bool BlockComment = false;

here you would do
BlockComment = true;
}
if ((line=='*')&&(begin)&&(line[i+1]=='/')){


Again, with std::string this becomes
k3=i-1;
begin=0;
proceed(k3, line, strlen(line)) ;
}

}
fp.close() ;
fpp.close() ;
return;
}

}

Hmm.. I dont' see where you checked for ending a block comment, or where
you are not writing anything if you started a block comment.

If you read thourgh the comments people provided and look at your code you
should be able to figure it out. You have the logic about 50% right.
Using chae pointers is making it much more difficult then it needs to be,
std::strings will make it a whole lot easier, especially since then you
can use find, substr and other functions.
 
J

James Kanze


On the whole, your comments are on target, and correspond to
generally accepted good programming, but in thie particular
case...

[...]
forget about char* and use std::string, then you can use find, will make
your life a LOT easier.

Whatever you do, don't use char*, that's for sure. But in this
case, I don't think that std::string is really the answer
either.

[...]
How about:
while ( std::getline( line ) )

Generally (say about 99 times out of 100), I'd recommend the
same thing. If the grammar is line oriented, it makes
resynchronizing after an error child's play, and even if the
grammar isn't line oriented, it provides as good a "chunk" as
anything else, and makes it easy to indicate line numbers in the
error messages.

In his case, however, he isn't doing any real parsing, and
there's no error handling, so these considerations don't come
into play. And one of his constructs (a block comment) can
extend across line boundaries---I think you'll find handling it
correctly no easy job if you insist on reading line by line. In
this one particular case (again: it's an exception---your
suggestions are better 99% of the time), I'd use a sliding
window in the file, implemented using std::deque<char>. It took
me less than 5 minutes to come up the following general sketch:

class Window
{
public:
explicit Window( size_t size = 2 ) ;
size_t fill( std::istream& source ) ;
void pop( size_t n = 1 ) ;
char top() const ;
size_t size() const ;
bool matchPrefix( std::string const& target )
const ;

private:
size_t myMaxSize ;
std::deque< char > myWindow ;
} ;

Window::Window(
size_t size )
: myMaxSize( size )
{
}

size_t
Window::fill(
std::istream& source )
{
while ( source && myWindow.size() != myMaxSize ) {
char ch ;
if ( source.get( ch ) ) {
myWindow.push_back( ch ) ;
}
}
return myWindow.size() ;
}

void
Window::pop(
size_t n )
{
myWindow.erase(
myWindow.begin(),
myWindow.begin() + std::min( myWindow.size(), n ) ) ;
}

char
Window::top() const
{
assert( ! myWindow.empty() ) ;
return myWindow.front() ;
}

size_t
Window::size() const
{
return myWindow.size() ;
}

bool
Window::matchPrefix(
std::string const& target ) const
{
return myWindow.size() >= target.size()
&& std::equal( target.begin(), target.end(),
myWindow.begin() ) ;
}

int
main()
{
enum State
{
start,
inBlockComment,
inLineComment
} state = start ;
Window w ;
while ( w.fill( std::cin ) != 0 ) {
switch ( state ) {
case start :
if ( w.matchPrefix( "//" ) ) {
state = inLineComment ;
w.pop( 2 ) ;
} else if ( w.matchPrefix( "/*" ) ) {
state = inBlockComment ;
w.pop( 2 ) ;
} else {
std::cout << w.top() ;
w.pop( 1 ) ;
}
break ;

case inBlockComment :
if ( w.matchPrefix( "*/" ) ) {
state = start ;
w.pop( 2 ) ;
} else {
w.pop( 1 ) ;
}
break ;

case inLineComment :
if ( w.matchPrefix( "\n" ) ) {
state = start ;
} else {
w.pop( 1 ) ;
}
break ;
}
}
return 0 ;
}
Hmm.. I dont' see where you checked for ending a block comment, or where you
are not writing anything if you started a block comment.

Which will be non-trivial problems if he reads line by line.
 
J

Jim Langston

Comment at very bottom


On the whole, your comments are on target, and correspond to
generally accepted good programming, but in thie particular
case...

[...]
forget about char* and use std::string, then you can use find, will make
your life a LOT easier.

Whatever you do, don't use char*, that's for sure. But in this
case, I don't think that std::string is really the answer
either.

[...]
How about:
while ( std::getline( line ) )

Generally (say about 99 times out of 100), I'd recommend the
same thing. If the grammar is line oriented, it makes
resynchronizing after an error child's play, and even if the
grammar isn't line oriented, it provides as good a "chunk" as
anything else, and makes it easy to indicate line numbers in the
error messages.

In his case, however, he isn't doing any real parsing, and
there's no error handling, so these considerations don't come
into play. And one of his constructs (a block comment) can
extend across line boundaries---I think you'll find handling it
correctly no easy job if you insist on reading line by line. In
this one particular case (again: it's an exception---your
suggestions are better 99% of the time), I'd use a sliding
window in the file, implemented using std::deque<char>. It took
me less than 5 minutes to come up the following general sketch:

class Window
{
public:
explicit Window( size_t size = 2 ) ;
size_t fill( std::istream& source ) ;
void pop( size_t n = 1 ) ;
char top() const ;
size_t size() const ;
bool matchPrefix( std::string const& target )
const ;

private:
size_t myMaxSize ;
std::deque< char > myWindow ;
} ;

Window::Window(
size_t size )
: myMaxSize( size )
{
}

size_t
Window::fill(
std::istream& source )
{
while ( source && myWindow.size() != myMaxSize ) {
char ch ;
if ( source.get( ch ) ) {
myWindow.push_back( ch ) ;
}
}
return myWindow.size() ;
}

void
Window::pop(
size_t n )
{
myWindow.erase(
myWindow.begin(),
myWindow.begin() + std::min( myWindow.size(), n ) ) ;
}

char
Window::top() const
{
assert( ! myWindow.empty() ) ;
return myWindow.front() ;
}

size_t
Window::size() const
{
return myWindow.size() ;
}

bool
Window::matchPrefix(
std::string const& target ) const
{
return myWindow.size() >= target.size()
&& std::equal( target.begin(), target.end(),
myWindow.begin() ) ;
}

int
main()
{
enum State
{
start,
inBlockComment,
inLineComment
} state = start ;
Window w ;
while ( w.fill( std::cin ) != 0 ) {
switch ( state ) {
case start :
if ( w.matchPrefix( "//" ) ) {
state = inLineComment ;
w.pop( 2 ) ;
} else if ( w.matchPrefix( "/*" ) ) {
state = inBlockComment ;
w.pop( 2 ) ;
} else {
std::cout << w.top() ;
w.pop( 1 ) ;
}
break ;

case inBlockComment :
if ( w.matchPrefix( "*/" ) ) {
state = start ;
w.pop( 2 ) ;
} else {
w.pop( 1 ) ;
}
break ;

case inLineComment :
if ( w.matchPrefix( "\n" ) ) {
state = start ;
} else {
w.pop( 1 ) ;
}
break ;
}
}
return 0 ;
}
Hmm.. I dont' see where you checked for ending a block comment, or where
you
are not writing anything if you started a block comment.

Which will be non-trivial problems if he reads line by line.

==========

Actually, I could fix his program rather quickly to work using
std::getline( std::cin, line ); A comment start or end has to be in one
line. I.E.
keyword(); // comment
is legal but
keyword(); /
/ comment
isn't.
So for the end of line comment // it's easy.

Same with block comment, the start or stop has to be in one line.

I don't, at this point, want to show how I would do it because I"m quite
sure this is homework, and the OP needs to do it on their own to learn.
Basically, however, you just have to keep a flag stating if you are in the
middle of a block comment and act accordingly looking for the end of block
comment in any line.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top