How to get rid of commas and replace them with spaces

closed account (EAk1vCM9)
Hi guys, so I need to read in a original file that has mutual funds data. Then I have to create a second file and put the data from the original file in there. However the second file should have the headings removed and the hyphens removed, and the commas should be replaced by spaces. I managed to remove the headings and hyphens but I got stuck at removing the commas and replacing them with white spaces. Ive tried multiple things but nothing as worked for me so far, any ideas on how to get rid of the commas and replace them with spaces?
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
  #include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;



int main() {

	ifstream infile;
	ofstream modifiedFile;
	string trash;
	char ch, comma;

	infile.open("vtsmx.csv");
	modifiedFile.open("vtsmxModified.csv");

	if(!infile)
	{
		cout << "Error opening the file" << endl;
		return 1;
	}
	else
	{
	 getline(infile,trash);

	 while(!infile.eof())
	 {
	 	ch= infile.get();
	 	if(ch !='-') modifiedFile <<ch;
	 	comma= infile.get();
	    if(comma!=',') modifiedFile <<comma;
	 }
	/* while(!infile.eof())
	 	 {
	 	 	comma= infile.get();
	 	 	if(comma!=',') modifiedFile <<comma;
	 	 }


*/

	 cout <<"done";

	}





	return 0;
}

Ex of original file
Date,Open,High,Low,Close,Adj Close,Volume
2015-10-16,50.860001,50.860001,50.860001,50.860001,49.009617,0
2015-10-19,50.880001,50.880001,50.880001,50.880001,49.028889,0
2015-10-20,50.810001,50.810001,50.810001,50.810001,48.961437,0

Ex of what I need
20151016 50.860001 50.860001 50.860001 50.860001 49.009617 0
20151019 50.880001 50.880001 50.880001 50.880001 49.028889 0
20151020 50.810001 50.810001 50.810001 50.810001 48.961437 0
Why are you reading two characters in that loop? You should only be reading one character at time and take different actions if the character is a comma or a dash or if it is not either of those characters.

So something more like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
while(infile.get(ch))
{
    if(ch == '-')
    {
         // Do whatever.
     }
     else if(ch == ',')
     {
         // Do whatever.
     }
     else
     {
         // Do what ever when the character is not one of the above.
     }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <fstream>
#include <string>

int main() {

    std::ifstream infile( "vtsmx.csv" );
    if( !infile.is_open() ) { /* ... */ return 1 ; }

    std::ofstream modifiedFile( "vtsmxModified.txt" ); // not csv once commas are gone

    std::string line ;
    std::getline( infile, line ) ; // discard the first line

    while( std::getline( infile, line ) ) { // for each subsequent line

        for( char& c : line ) // for each char in the line,
            if( c == ',' ) c = ' ' ; // if it is a comma, replace it with a space

        modifiedFile << line << '\n' ;
    }
}
Last edited on
(Suggestions requested - see lower part)

To remove the header line and change commas to spaces you can use just:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>
using namespace std;

using it = istream_iterator<char>;
using ot = ostream_iterator<char>;

int main()
{
   ifstream in ( "vtsmx.csv" );
   ofstream out( "vtsmx.txt" );
   string dummy;   getline( in, dummy );         // dump first line
   in >> noskipws;                               // needed to get the linefeeds
   replace_copy( it{in}, {}, ot{out}, ',', ' ' );
}


vtsmx.csv
Date,Open,High,Low,Close,Adj Close,Volume
2015-10-16,50.860001,50.860001,50.860001,50.860001,49.009617,0
2015-10-19,50.880001,50.880001,50.880001,50.880001,49.028889,0
2015-10-20,50.810001,50.810001,50.810001,50.810001,48.961437,0


vtsmx.txt
2015-10-16 50.860001 50.860001 50.860001 50.860001 49.009617 0
2015-10-19 50.880001 50.880001 50.880001 50.880001 49.028889 0
2015-10-20 50.810001 50.810001 50.810001 50.810001 48.961437 0



HOWEVER, THIS DOESN'T SIMULTANEOUSLY REMOVE THE HYPHENS


Can anyone see a way of doing this with just a minor modification, still retaining the stream iterators and copy-type algorithm?

The only thing I could come up with was to use an intermediate stringstream; it works, but it's really clunky and has been irritating me for too long.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>
using namespace std;

using it = istream_iterator<char>;
using ot = ostream_iterator<char>;

int main()
{
   ifstream in ( "vtsmx.csv" );
   ofstream out( "vtsmx.txt" );
   stringstream ss;
   string dummy;   getline( in, dummy );         // dump first line
   in >> noskipws;    ss >> noskipws;            // needed to get the linefeeds
   replace_copy( it{in}, {}, ot{ss}, ',', ' ' );
   remove_copy( it{ss}, {}, ot{out}, '-' );
}


vtsmx.txt
20151016 50.860001 50.860001 50.860001 50.860001 49.009617 0
20151019 50.880001 50.880001 50.880001 50.880001 49.028889 0
20151020 50.810001 50.810001 50.810001 50.810001 48.961437 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>

int main()
{
   std::ifstream in ( "vtsmx.csv" );

   std::string dummy;
   std::getline( in, dummy );

   std::replace_copy_if( std::istreambuf_iterator<char>{in}, {},
                         std::ostreambuf_iterator<char>{ std::ofstream( "vtsmx.txt" ).rdbuf() },
                         []( char c ) { return c == ',' || c == '-' ; }, ' ' );
}


Note: using std::istreambuf_iterator<char> and std::ostreambuf_iterator<char> eliminates the overhead of construction and destruction of a pair of sentry objects for each character read from the file.
Thank-you @JLBorges. Is it possible to replace ',' by a space, but simultaneously remove '-' (rather than also replacing it by a space)? I can't quite find a general-enough copy algorithm for that.
There is no standard algorithm for that; we can write one if it can be used in many places.

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 <fstream>
#include <string>
#include <algorithm>
#include <iterator>

template < typename INPUT_ITERATOR, typename OUTPUT_ITERATOR, typename T >
OUTPUT_ITERATOR replace_and_remove_copy( INPUT_ITERATOR begin, INPUT_ITERATOR end,
                                         OUTPUT_ITERATOR dest,
                                         const T& old_v, const T& new_v, const T& remove_v )
{
    for( ; begin != end ; ++begin )
    {
        const auto& value = *begin ;
        if( !(value==remove_v) ) *dest++ = (value==old_v) ? new_v : value ;
    }
    return dest ;
}

int main()
{
   std::ifstream in ( "vtsmx.csv" );

   std::string dummy;
   std::getline( in, dummy );

   replace_and_remove_copy( std::istreambuf_iterator<char>{in}, {},
                                 std::ostreambuf_iterator<char>{ std::ofstream( "vtsmx.txt" ).rdbuf() },
                                ',', ' ', '-' );
}
Thank-you for the reply.

(Sorry @MOMO1, that slightly hijacked your thread.)
closed account (EAk1vCM9)
Thanks for the help guys but I cant really use the solutions because for one I dont understand what anything you guys did means and the other reason is for two solution you guys gave me it ended up giving me errors. I was asking some people IRL and they all said I could use and if else statement(which was also recommended here) but I tried it and I realized that it skips the else if statement all the time and I dont know why. so why is it skipping the else if statement and how can I fix this. Also real quick just to tell you guys it does successfully the first if statement so if (ch !='-' ) is first then it removes the - lines from the file but keeps the commas and if its if(ch==',') first then it successfully takes out the spaces and replaces them with spaces ..... ps. im required to name the modified file "vtsmxModified.csv" so I cant change it to txt.
my updated 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
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;



int main() {

	ifstream infile;
	ofstream modifiedFile;
	string dummy, lines;
	char ch ;

	infile.open("vtsmx.csv");
	modifiedFile.open("vtsmxModified.csv");

	if(!infile)
	{
		cout << "Error opening the file" << endl;
		return 1;
	}
	else
	{
	 getline(infile,dummy);

	 while(!infile.eof())
	 	{
	 		ch = infile.get();

	 		if(ch != '-')
	 			{
	 			modifiedFile <<ch;
	 			}
	 		else if(ch==',')
	 		{
	 			cout <<" did it enter";
	 			ch =' ';
	 			modifiedFile <<ch;
	 		}


	 	}

	 cout <<"done";

	}





	return 0;
}


I also tried this but no didnt really solve my issue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
while(infile.get(ch))
	 {
		
		 if(ch ==',')
		 {
			 ch =' ';
			// modifiedFile << ch; this just ends make my file blank
		 }
			modifiedFile << ch; // takes out commas
			if( ch !='-') // with this if it just makes my file garbage
			{

			}
			modifiedFile << ch;
	 }
Last edited on
Also real quick just to tell you guys it does successfully the first if statement so if (ch !='-' ) is first then it removes the - lines from the file but keeps the commas and if its if(ch==',') first then it successfully takes out the spaces and replaces them with spaces

No.

You are looking one char at a time. If it is not a dash, then it is written out.

That condition fails only if the character is a dash. Then you would test whether it is a comma. A dash is never a comma. => will always fail.


IF character is a dash THEN do nothing
ELSE IF character is a comma THEN write space
ELSE write the character
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
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;

int main()
{
   ifstream infile;
   ofstream modifiedFile;
   string dummy;                         // lines isn't used
   char ch;

   infile.open( "vtsmx.csv" );
   modifiedFile.open( "vtsmxModified.csv" );
   if ( !infile )
   {
      cout << "Error opening the file" << endl;
           return 1;
   }
   else
   {
      getline( infile, dummy );

//    while (!infile.eof())             // Better not to use .eof() as loop condition
      while ( infile.get( ch ) )        // Use the ability to read the stream instead
      {
         if (ch != '-' )                // If it's not a hyphen then you will write something ...
         {
            if ( ch == ',' ) ch = ' ';  // ... but you may need to change it first

            modifiedFile.put( ch );
         }
      }
   }
   return 0;                            // Not needed (automatic for main())
}
Last edited on
closed account (EAk1vCM9)
oh ok thanks for explaining the logic @keskiverto when I was show an example IRL the person that showed it didnt really explain why that worked and I was left confused wondering how his example worked.Also Thank you @lastchance that worked, you sir just made my day! (also no worries about the hijack its cool :) )
Topic archived. No new replies allowed.