I want to make text file, filling him string by string, until empty string. But, somehow I have infinite input, what conidition need I make to escape infinite loop?
Here is my code:
fstream f;
f.open("text1.txt", ios::out);
bool flag = false;
while (!flag) {
char buf[50];
cin >> buf;
if (strlen(buf)!=0 )
f<<buf<<endl;
else {
f.close();
flag = true;
}
}
With cin >> buf you are reading one word at a time. It's easier to use std::getline instead:
fstream f;
f.open("text1.txt", ios::out);
bool flag = false;
while (!flag) {
string str;
getline(cin, str);
if (cin && !str.empty())
f<<str<<endl;
else {
f.close();
flag = true;
}
}
If you are forced to use fixed buffer, you need to search for \n\n occurrence in a data. \n is a new line symbol in C++.
You need to iterate while loop until end of file.
fstream f;
f.open("text1.txt", ios::out);
char buf[50];
while (cin >> buf) // it becomes false when end of file reach. You can test it from keyboard by Ctrl+Z and then Enter
{
f<<buf<<endl;
}
f.close();
Related
I tried to take every character in a file and use with toupper() and tolower() functions. But I can't put the result instead of the character.
I used a vector to solve it.
Is there an easy way to solve this?
void UpperCase(){
fstream file;
char name[81] , ch;
vector<char> container;
cout << "Enter the file name : ";
cin >> name;
file.open(name,ios::in);
while(!file.eof() && !file.fail()){
file.get(ch);
container.push_back(toupper(ch));
}
file.close();
file.open(name,ios::out);
for(int i=0 ; i<container.size()-1 ; ++i){
file.put(container[i]);
}
file.close();
return;
}
Here is an efficient method:
char buffer[4096];
std::string name;
std::cout << "Enter filename: ";
std::cin >> name;
std::ifstream input(name.c_str(), ios::binary);
const std::string out_filename = name + ".upper_case";
std::ofstream output(out_filename.c_str(), ios::binary);
while (input.read(buffer, sizeof(buffer))
{
const unsigned int chars_read = input.gcount();
std::transform(&buffer[0], &buffer[chars_read],
&buffer[0], toupper);
output.write(buffer, chars_read);
}
The above code reads in a block of characters, then transforms them to uppercase, then writes the block to another file.
Writing to another file is a safe practice, and you don't need to read the entire file into memory.
You can change the size of the buffer to make the program more efficient. Recommend sizes are multiples of 512, since that is a standardized size for a hard drive sector.
Edit 1:
If you are allergic to std::transform, replace the call with a loop to convert the characters.
I want to programmatically convert a string of characters stored in a file to a string of character codes (encode) by following a code table. The string of binary codes should then go to a file, from which I can revert it back to the string of characters later (decode). The codes in the code table were generated using Huffman algorithm and the code table is stored in a file.
For example, by following a code table where characters and its corresponding codes are single spaced like this:
E 110
H 001
L 11
O 111
encoding "HELLO" should output as "0011101111111"
My C++ code cannot seem to complete the encoded string. Here is my code:
int main
{
string English;
ifstream infile("English.txt");
if (!infile.is_open())
{
cout << "Cannot open file.\n";
exit(1);
}
while (!infile.eof())
{
getline (infile,English);
}
infile.close();
cout<<endl;
cout<<"This is the text in the file:"<<endl<<endl;
cout<<English<<endl<<endl;
ofstream codefile("codefile.txt");
ofstream outfile ("compressed.txt");
ifstream codefile_input("codefile.txt");
char ch;
string st;
for (int i=0; i<English.length();)
{
while(!codefile_input.eof())
{
codefile_input >> ch >> st;
if (English[i] == ch)
{
outfile<<st;
cout<<st;
i++;
}
}
}
return 0;
}
For an input string of "The_Quick_brown_fox_jumps_over_the_lazy_dog", the output string is 011100110, but it should be longer than that!
output image
Please help! Is there anything I have missed?
(n.b. my C++ code has no syntax errors)
Let's take a look at the main loop, you are doing your work in:
for (int i=0; i<English.length();)
{
while(!codefile_input.eof())
{
codefile_input >> ch >> st;
if (English[i] == ch)
{
outfile<<st;
cout<<st;
i++;
}
}
}
Your code, will read through the codefile_input once, and then will get stuck in codefile_input.eof () == true condition, and then, for (int i=0; i<English.length();) will become an infinite loop, due to the fact, that there won't be a code path, in which i is increased, and it will never reach the value equal to English.length ().
As a side note, take a read on Why is iostream::eof inside a loop condition considered wrong?.
To avoid the issue, explained above, consider reading the dictionary file, to a data container (e.g. std::map), and then, use that, while iterating through the string, that you want to encode.
For example:
std::ifstream codefile_input("codefile.txt");
char ch;
std::string str;
std::map<char, std::string> codes;
while (codefile_input >> ch >> str)
{
codes[ch] = str;
}
codefile_input.close ();
for (int i=0; i<English.length(); ++i)
{
auto it = codes.find (English[i]);
if (codes.end () != it)
{
outfile << codes->second;
cout << codes->second;
}
}
Note, you will need to #include <map> to use std::map.
In addition to solving the issue, about which, your question, was actually, about, your loop:
while (!infile.eof())
{
getline (infile,English);
}
only reads the last line of the file, while discarding all other lines, that came prior to it. If you want to process all the lines in a file, consider changing that loop to:
while (std::getline (infile, English))
{
/* Line processing goes here */
}
And, since, your dictionary is unlikely to be different for different lines, you can move that logic, to the front of this loop:
std::ifstream codefile_input("codefile.txt");
char ch;
std::string str;
std::map<char, std::string> codes;
while (codefile_input >> ch >> str)
{
codes[ch] = str;
}
codefile_input.close ();
ifstream infile("English.txt");
if (!infile.is_open())
{
cout << "Cannot open file.\n";
exit(1);
}
ofstream outfile ("compressed.txt");
string English;
while (std::getline (infile, English))
{
for (int i=0; i<English.length(); ++i)
{
auto it = codes.find (English[i]);
if (codes.end () != it)
{
outfile << codes->second;
cout << codes->second;
}
}
}
In addition, consider adding error checking for all of the files that you open. You check if you can open file English.txt, and exit if you can't, but you don't check if you could open any other file.
On unrelated note #2, considering reading Why is “using namespace std” considered bad practice? (that's why you see me using std:: explicitly in the code, that I added).
I've a problem with writing to file. If I write something with spaces, it write each word as a single line. Why?
void backstart()
{
thread t1(backing);
thread t2(thr2);
t1.join();
t2.join();
}
void thr2()
{
string tmp;
tmp = "";
while (tmp != "/exit")
{
cin >> tmp;
if (tmp != "/exit")
{
writefile(tmp);
}
}
runing = false;
}
void writefile(string msg)
{
ofstream myfile("file.txt", ios::out | ios::app);
myfile << userna + ": " + msg + ",\n";
myfile.close();
}
Thanks
Damon
Consider writing it like this:
void thr2()
{
std::string line;
while(std::getline(cin, line)) // this check the read succeeded as well
{
if (line=="/exit") break; // stop on "/exit" command
writefile(line); // write out the line
}
running = false; // stop the thread, I guess
}
The most important line is
while(std::getline(std::cin, line))
which reads a whole line at a time into the std::string called line, and then checks the state of the stream to make sure the read succeeded. Read about std::getline here.
Edit:
Be very careful (and in fact I suggest just avoiding it) mixing reading with >> and getline. If you read, for example an int, with >> it will leave the '\n' character at the end of the line, so when you next read with getline, you get the rest of the line (which is basically nothing), rather than what you probably wanted, which is the next line.
If you have just read with >> and want to use getline, read into the whitespace eater first, like this std::cin >> std::ws.
Good day, everyone
I would like to insert a dot (or any other char), after specified amount chars read (in my case it's 2)
So here is my code:
#include <fstream>
#include <string>
using namespace std;
string dot = "."; //Char to insert
char ch;
unsigned i=0; //Symbol counter
int counter = 2; //How much letters to skip before insertion
int main(){
fstream fin("file.txt", fstream::in);
while (fin >> noskipws >> ch) {
ofstream file;
file.open ("file2.txt");
file << ch;
file.close();
i++;
if(i == counter){
file.open ("file2.txt");
file << dot;
file.close();
i = 0;
}
}
return 0;
}
What i have written in my new file2.txt is "0".
P.S. I'm quite new in C++ so please explain in depth as for newbie (if you have time)
Thank you in advance.
EDIT: After applying few fixes output is now "."
EDIT2: It doesn't allow me to answer to my self post (because I'm newbie in this forum and have to wait 7h before answering), I'm going to post my fixed code here
Fixed version:
#include <fstream>
#include <string>
using namespace std;
string dot = "."; //Char to insert
char ch;
unsigned i = 0; //Symbol counter
int counter = 2; //How much letters to skip before insertion
int main(){
ofstream file;
file.open ("file2.txt");
fstream fin("file.txt", fstream::in);
while (fin >> noskipws >> ch) {
file << ch;
i++;
if(i == counter){
file << dot;
i = 0;
}
}
file.close();
fin.close();
return 0;
}
Thank you everyone for replies.
For a simple application like this, open the output file before you start reading, and don't close it until you're done. As written, the output file gets opened every time a character is read and then overwrites whatever was in the file before. You could open the file in append mode to stick new data on the end, but it's much simpler (and faster) to just keep it open.
Each time you write something to your output file, you open it, write your output, then close it. Because of the way you are opening your file, each of your writes start at the beginning of the file.
If instead, you leave your output file open until you are finished writing all your data, then next write will continue at the point the previous write ended, producing the sequence of output you are expecting.
ofstream file;
file.open("file2.txt");
while (fin >> noskipws >> ch) {
file << ch;
i++;
if (i == counter) {
file << dot;
i = 0;
}
}
Just open file in beginning , updated it and finally close all files.
ofstream file; <------------+
file.open ("file2.txt"); |
|
while (fin >> noskipws >> ch) { |
|
//ofstream file; ---+ |
+----->------+
//file.open ("file2.txt"); ---+
file << ch;
//file.close();
i++;
if(i == counter){
//file.open ("file2.txt");
file << dot;
//file.close();
i=0;
}
}
//Close files
file.close();
fin.close() ;
When you write to a file in a loop, you most likely want to to open the file outside of the loop. Normally when you open a file for writing, the old content will be overwritten.
So do this:
ofstream file ("file2.txt")
while (...)
{
...
file << ....
...
}
I am trying to read a list of words from a file in C++. However, the last word is read twice. I cannot understand why it is so. Can someone help me out?
int main () {
ifstream fin, finn;
vector<string> vin;
vector<string> typo;
string word;
fin.open("F:\\coursework\\pz\\gattaca\\breathanalyzer\\file.in");
if (!fin.is_open())
cout<<"Not open\n";
while (fin) {
fin >> word;
cout<<word<<endl;
vin.push_back(word);
}
fin.close();
}
Your loop condition is off by one:
while (fin >> word) {
cout<<word<<endl;
vin.push_back(word);
}
You need to do:
while((fin >> word).good()) {
vin.push_back(word);
}
Because fin >> word fails and you don't check it.
It's not read twice. It's simply the old value, since fin >> word fails.
Use
while(fin >> word)
{
...
}
instead.
It tries to read and stops loop if it fails.
Check these..
How do you read a word in from a file in C++?
http://www.bgsu.edu/departments/compsci/docs/read.html
http://answers.yahoo.com/question/index?qid=20081216024044AAKidaX