help dat file

closed account (4wpL6Up4)
Hi,
this program should obtain upper and lower characters from a dat file and once extracted, move each category into a new txt file.
This code seems to run smoothly, but not sure why, the newly created files always come out empty.
What exactly is wrong with it?


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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  #include "pch.h"
#include <iostream>
#include<fstream>

using namespace std;
int main()
{
	int uppercase = 0;
	int lowercase = 0;

	ifstream input("abcfile.dat");
	char data;
	while (!input.eof())
	{
		input.get(data);
		cout << data << endl;
	
	

		input.get(data);

		if ((data >= 'A') && (data <= 'Z'))

		{

			uppercase++;

		}

		else if ((data >= 'a') && (data <= 'z'))

		{

			lowercase++;

		}
	}

	cout << "Number of uppercase letters " << uppercase;

	cout << "Number of lowercase letters " << lowercase;
	input.close();

	ofstream outfile;
	outfile.open("upper.txt");
	while (!input.eof())
	{
		input.get(data);
		if ((data >= 'A') && (data <= 'Z'))

		{

			cout << data;

		}
	}
	outfile.close();


	outfile.open("lower.txt");
	while (!input.eof())
	{
		input.get(data);
		if ((data >= 'a') && (data <= 'z'))

		{

			cout << data;

		}
	}
	outfile.close();
}
Last edited on
Hello nypran,

It would help if you post your "abcfile.dat" file so everyone can see what you are using.

On line the while condition based on "eof" will not work the way you are thinking. By the time the condition sees that you are at end of file you will have processed your last read twice. It would be better to use while (input.get(data)) and remove line 15. This way when there is nothing left to read the condition fails and so the while loop.

The while loops on your output makes no sense. Since you are always appending to the file as you write how do you know you are at the end?

I would open the output files after you open for the input file and write to the output file after "uppercase++;" and "lowercase++;" since this is where you will a value for data and something to write to the output files.

By the time you reach lines 48 and 63 the input file is at "eof" and the "eof" bit has been set, so the stream is no longer usable. And if it was you would be reading the next character not the one you need.

In your last two while loops you open a file for output, but never write to it. This is why your files are empty.

I will rework your program to give you an idea of what you can do. Be patient this will take a little time.

Hope that helps,

Andy
closed account (4wpL6Up4)
Thank you Andy,

but how should I post here such a file?
If you want you are free to use the content of it since my code reads it and displays it in the command prompt but I am not sure how to post such a file here.
Hello nypran,

Either just copy and paste it or put it in inside output tags. Most people just copy and paste it.

Andy
Beware of helping this OP.
http://www.cplusplus.com/forum/beginner/250735/
They will delete after getting help.
@salem c,

Thank you for the warning. Fo me its just something to do yo fill time.

Andy
closed account (4wpL6Up4)
I was getting no answer and wanted to start fresh, that's why I erased.
I did not know it was forbidden.
The code I erased was almost the same as the one I posted above anyway,
so trying to convince other users to act on what you feel instead of telling me first
what I should and should not do is quite unfair.
closed account (4wpL6Up4)
I have written many times on this forum and erased nothing.
The reason why I erased those comments are explained above.
Now I got the warning.
closed account (4wpL6Up4)
@Andy,
the file is a dat file, it does not open.
That is why is impossible to copy paste.
@nypran, It's needed to check after each openings and reading-ins if a stream is at a 'good' state. It's not sufficient to check for eof(). E.g. it could be that the file could not exist or red/write is not permissible for a user.

Here I have fixed your code for what I think it should do for 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
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <iostream>
#include<fstream>

using namespace std;
int main()
{
	int uppercase = 0;
	int lowercase = 0;

	ifstream input("abcfile.dat");
	if (!input)
	{
	    cerr << "File 'abcfile.dat' couldn't opened!\n";
	    exit(1);
	}
	
	char data;
	while (input)
	{
		if (!input.get(data)) break;
		cout << data;

		if ((data >= 'A') && (data <= 'Z'))
		{
			uppercase++;
		}

		else if ((data >= 'a') && (data <= 'z'))
		{
			lowercase++;
		}
	}

	cout << "Number of uppercase letters " << uppercase << '\n';

	cout << "Number of lowercase letters " << lowercase << '\n';
	

	ofstream outfile;
	outfile.open("upper.txt");
	if (!outfile)
	{
	    cerr << "File 'upper.txt' couldn't opened!\n";
	    exit(1);
	}
	
	input.clear(); // Makes the stream 'good()'
	input.seekg(0); // Sets the position to begin of the file
	while (input)
	{
		if (!input.get(data)) break;
		if ((data >= 'A') && (data <= 'Z'))
		{
			outfile << data;
		}
	}
	outfile.close();


	outfile.open("lower.txt");
	if (!outfile)
	{
	    cerr << "File 'lower.txt' couldn't opened!\n";
	    exit(1);
	}
	
	input.clear();
	input.seekg(0);
	while (input)
	{
		if (!input.get(data)) break;
		if ((data >= 'a') && (data <= 'z'))
		{
			outfile << data;
		}
	}
	outfile.close();
}

closed account (4wpL6Up4)
Thank you nuderobomonkey.

basically all you did was keeping my code the way it is and adding

if (!input)
{
cerr << "File 'abcfile.dat' couldn't opened!\n";
exit(1);
}

to the beginning and to the new files.
Now it works.

Thanks again.
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 <iterator>
#include <cctype>
#include <algorithm>
using namespace std;

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

void filter( string infile, string oufile, bool test( char c ) )
{
   ifstream in ( infile );
   ofstream out( oufile );
   copy_if( it{ in }, it{}, ot{ out }, test );
}

int main()
{
   filter( "input.txt", "lower", []( char c ){ return (bool)islower( c ); } );
   filter( "input.txt", "upper", []( char c ){ return (bool)isupper( c ); } );
}
Checking for good file opening is mandatory. But the salient point is, that you always need to check if a read-in was successful. At this example: if (!input.get(data))) break;

At your example we could have this check also at the loop header:
while (input.get(data)) ...
Hello nypran,

I was getting no answer and wanted to start fresh, that's why I erased.
I did not know it was forbidden.

In that case reply to your own post with "bump". This will put the post at the top of the list.

Your ".dat" file can be opened in "Notepad". It can also be opened in VS.

I am not sure if it is actually forbidden to delete the beginning of a post, but it is bad form. It makes the replies hard to understand especially for someone who comes in late.

nuderobmonkey has one approach. Here is a different approach:
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <iostream>
#include <string>
#include<fstream>
#include <chrono>
#include <thread>

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

int main()
{
	int uppercase = 0;
	int lowercase = 0;
	char data;

	const std::string inFileName{ "abcfile.dat" };
	const std::string outFileNameLow{ "LowerCase.txt" };
	const std::string outFileNameUp{ "UpperCase.txt" };

	std::ifstream inFile(inFileName);

	if (!inFile)
	{
		std::cout << "\n File \"" << inFileName << "\" did not open" << std::endl;
		std::this_thread::sleep_for(std::chrono::seconds(3));  // <--- Needs header files chrono" and "thread".
		return 1;  //exit(1);  // If not in "main".
	}


	std::ofstream outFileLow(outFileNameLow);

	if (!outFileLow)
	{
		std::cout << "\n File \"" << outFileNameLow << "\" did not open" << std::endl;
		std::this_thread::sleep_for(std::chrono::seconds(3));  // <--- Needs header files chrono" and "thread".
		return 2;  //exit(1);  // If not in "main".
	}


	std::ofstream outFileUp(outFileNameUp);

	if (!outFileUp)
	{
		std::cout << "\n File " << outFileNameUp << " did not open" << std::endl;
		std::this_thread::sleep_for(std::chrono::seconds(3));  // <--- Needs header files chrono" and "thread".
		return 3;  //exit(1);  // If not in "main".
	}


	while (inFile.get(data))
	{
		if ((data >= 'A') && (data <= 'Z'))
		{
			uppercase++;

			std::cout << data << std::endl;
			outFileUp << data << ' ';
		}
		else if ((data >= 'a') && (data <= 'z'))
		{
			lowercase++;

			std::cout << data << std::endl;
			outFileLow << data << ' ';
		}
	}

	std::cout << "\nNumber of uppercase letters " << uppercase << std::endl;

	std::cout << "Number of lowercase letters " << lowercase << std::endl;

	inFile.close();
	outFileLow.close();
	outFileUp.close();

	// <--- Used mostly for testing in Debug mode. Removed if compiled for release.
	// <--- Used to keep the console window open in Visual Studio Debug mode.
	// The next line may not be needed. If you have to press enter to see the prompt it is not needed.
	//std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
	std::cout << "\n\n Press Enter to continue";
	std::cin.get();

	return 0;
}

You will need to include the header file "string". The header files "chrono" and "thread" are optional, will explain shortly.

I like using the strings for the file names because I can use them to open the files and use them in the if statements.

When opening a file for input it is not only a good idea to check if it opened it is a must. If the file did not open and the program continues nothing will be read.

In contrast if an output file name does not exist it will be created. It is not impossible for an output file to fail to open, but it could happen. Checking that an output file is open is just a good practice.

In the if statements lines 24, 34 and 44 are optional. I use this in my VS to keep the console window open long enough to read the message before the window closes. You may not need or want this.

Since this is all contained inside "main" the return statement is best to use. "return 0;" is a normal exit of the program. Any number greater than zero is considered a problem exit. By using different numbers, (1, 2, 3) you can use this to help find where the problem is. As the comment says if you use this if statement outside "main" you will need to use the "exit()". The different numbers greater than zero apply the same.

One single while loop can accomplish everything that you need with the least amount of work and coding.

The lines above the "return" are something I use and may not be needed by you. Keep them if you want or delete them. The use is similar to line 24.

Although it is not necessary to end the program with return 0; it is good form and also a good place for a break point when debugging the program.

Hope that helps,

Andy
Hello nypran,

I was thinking about your "abcfile.dat" file. The ".dat" is generally used tor binary files and this would be better as a ".txt" file for what you are using.

Andy
closed account (4wpL6Up4)
Thanks for your code andy,
however the code written above much more similar to mine
so it makes it more understandable, but thanks anyway.
Yes, the .dat is binary, and that's the whole point.
Topic archived. No new replies allowed.