String manipulation and File IO in C++? - c++

What I am trying to do is open a file containing a string, replace every character in that file with [character + 37], and output it on a different file "output.txt". What I'm guessing is a problem with the at function...
#include "stdafx.h"
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
void encrypt(string text, int size) {
int i;
for (i = 0; i < size; i++) {
text.at(i) = text.at(i) + 37;
}
}
int main()
{
string string;
int length = string.length();
ifstream infile;
infile.open("input.txt");
if (infile.fail()) {
cerr << "Error Opening File. " << endl;
exit(1);
}
infile >> string;
infile.close();
encrypt(string, length);
ofstream outfile;
outfile.open("output.txt");
if (infile.fail()) {
cerr << "Error Opening File. " << endl;
exit(1);
}
outfile << string;
outfile.close();
return 0;
}

First thing, you should change your encrypt function string parameter to reference type:
void encrypt(string& text, int size) {
otherwise string text is a local variable in this function, and any changes will be lost after it ends.
Another thing is that you dont need int size, use text.size() instead. Also I see you are passing as size, result of this code:
string string;
int length = string.length();
here length will always be zero, also - as you can see your variable name is the same as the type std::string, why you use such name? This is one of the reason you should not use using namespace std;
Third thing, after :
ofstream outfile;
outfile.open("output.txt");
you check if it is in fail state by using infile instead of outfile
if (infile.fail()) {
better change this check to if (!infile) {

As said by #marcinj, your encrypt routine only modifies a copy of original string, and the copy is lost when function exists.
But anyway, what you do is rather dangerous: your encrypt function can take printable characters and transform then into non printable ones while you use the text interface of streams. Even if it works, the file might not contain a correct string when done.
For example the character ù (which is common in french) will become a space which is the string delimiter, and even worse, the õ (common in portuguese) will become a \n not speaking of the Û that will give a null character!

Related

How to read a .txt file using c-strings?

I'm working on a project for school and I need to read in text from a file.
Sounds easy peasy, except my professor put a restriction on the project: NO STRINGS
("No string data types or the string library are allowed.")
I've been getting around this problem by using char arrays; however, I'm not sure how to use char arrays to read in from a file.
This is an example from another website on how to read in a file with strings.
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
The important line here is while ( getline (myfile,line) );
getline accepts an ifstream and a string (not char array).
Any help is appreciated!
Use cin.getline. Refer to this site for the format: cin.getline.
You can write something like this:
ifstream x("example.txt");
char arr[105];
while (x.getline(arr,100,'\n')){
cout << arr << '\n';
}
ifstream has a method named get() that reads the contents of the file into a char array. get() takes, as parameters, a pointer to the array, and the size of the array; then fills the array up to the given size, if possible.
After get() returns, use the gcount() method to determine how many characters have been read.
You can use then, and a simple logical loop, to repeatedly read the contents of the file, in size-chunks, into an array, and collect all the chunks read into a single array, or a std::vector.
You can use the int i = 0; while (scanf("%c", &str[i ++]) != EOF) to judge the end of text input. str is the char array include newline which you wanted, and i is the input size.
You can also use while(cin.getline()) to read per line every loop in C++ style:
istream& getline (char* s, streamsize n, char delim ); just like below:
const int SIZE = 100;
const int MSIZE = 100;
int main() {
freopen("in.txt", "r", stdin);
char str[SIZE][MSIZE];
int i = -1;
while (cin.getline(str[++ i], MSIZE)) {
printf("input string is [%s]\n", str[i]);
}
}

Fixing syntax of number of line reading function

I tried making a program earlier that tells the user then number of char, words, and lines in a text file. I made functions to determine the numbers of each, yet I was passing them by value. This resulted in an error since after reading the number of char it would be at the end of the file and then output zero for the other two. Now I cant seem to rewrite my functions so that the file is open and closed each time its checked for char, words, and lines. Any one see where my errors are?? Thanks! (just copied and pasted one of my functions for now).
int num_of_lines(ifstream file)
{
string myfile;
myfile = argv[1];
ifstream l;
l.open(myfile);
int cnt3 = 0;
string str;
while(getline(file, str))cnt3++;
l.close();
return(cnt3);
}
int main(int argc, char **argv)
{
int num_of_char(ifstream file);
string file;
file = argv[1];
if(argc == 1)die("usage: mywc your_file");
ifstream ifs;
ifs.open(file);
if(ifs.is_open())
{
int a, b, c;
a = num_of_lines(ifs);
cout <<"Lines: " << a << endl;
}
else
{
cerr <<"Could not open: " << file << endl;
exit(1);
}
ifs.close();
return(0);
}
There is no way to "reopen" a file other than knowing the name and creating a new ifstream, but you can use the seekg member function to set your read position in the file, and setting it to 0 will have the next read operation start from the beginning of the file.
A stream is not possible to copy, so you can't pass it "by value", but must pass it by reference.
int num_of_lines(ifstream &file)
{
int count = 0;
string str;
while (getline(file, str)) {
count++;
}
file.seekg(0);
return count;
}
For the full problem, I agree with Mats Petersson, though. Counting both characters, lines and words in one pass will be much more efficient than reading through the file three times.

Trying to return size of input file of c++ but recieve an error when I convert the char variable to string

I am trying to count the characters in my program. Initially my variable "words" was a char and the file read just fine. When trying to determine the length of the variable, it wouldn't work with .length(). Can you explain how I can make my "words" variable as a string so that the words.length() executes correctly?
error on line words = readFile.get(); is:
no match for ‘operator!=’ in ‘words != -0x00000000000000001’
#include <iostream>
#include <cmath>
#include <fstream>
#include <cstdlib>
#include <string>
#include <stdio.h>
#include <math.h>
using namespace std;
int main() {
//buff array to hold char words in the input text file
string words;
//char words;
//read file
ifstream readFile("TextFile1.txt");
//notify user if the file didn't transfer into the system
if (!readFile)
cout <<"I am sorry but we could not process your file."<<endl;
//read and output the file
while (readFile)
{
words = readFile.get();
if(words!= EOF)
cout <<words;
}
cout << "The size of the file is: " << words.length() << " bytes. \n";
return 0;
}
char c;
while (readFile.get(c))
{
words.insert(c);
}
Of course, if you were solely doing this to count the number of characters (and were intent on using std::istream::get) you'd probably be better off just doing this:
int NumChars = 0;
while (readFile.get())
{
NumChars++;
}
Oh, and by the way, you might want to close the file after you're done with it.
You should read some reference.. try cppreference.com and look for std::instream::get
I'm not sure what do you want, but if you wanna just count words, you can do something like this:
std::ifstream InFile(/*filename*/);
if(!InFile)
// file not found
std::string s;
int numWords = 0;
while(InFile >> s)
numWords++;
std::cout << numWords;
Or if you want to get to know how many characters are in file, change std::string s to char s and use std::ifstream::get instead:
std::ifstream InFile(/*filename*/);
if(!InFile)
// file not found
char s;
int numCharacters = 0;
while(InFile.get(s)) //this will read one character after another until EOF
numCharacters++;
std::cout << numCharacters;
The second approach is easier:
If file uses ASCII, numCharacters == fileSize;
Otherwise if it uses UNICODE, numCharacters == fileSize / 2;
get() returns an int, to do what you're doing, you must check that int before appending to "words" instead of checking words against EOF, e.g.:
...
//read and output the file
while (readFile)
{
const int w = readFile.get();
if (w!= EOF) {
words += w;
cout <<words;
}
}
...

How to read a file line by line or a whole text file at once?

I'm in a tutorial which introduces files (how to read from file and write to file)
First of all, this is not a homework, this is just general help I'm seeking.
I know how to read one word at a time, but I don't know how to read one line at a time, or how to read the whole text file.
What if my file contains 1000 words? It is not practical to read entire file word after word.
My text file named "Read" contains the following:
I love to play games
I love reading
I have 2 books
This is what I have accomplished so far:
#include <iostream>
#include <fstream>
using namespace std;
int main (){
ifstream inFile;
inFile.open("Read.txt");
inFile >>
Is there any possible way to read the whole file at once, instead of reading each line or each word separately?
You can use std::getline :
#include <fstream>
#include <string>
int main()
{
std::ifstream file("Read.txt");
std::string str;
while (std::getline(file, str))
{
// Process str
}
}
Also note that it's better you just construct the file stream with the file names in it's constructor rather than explicitly opening (same goes for closing, just let the destructor do the work).
Further documentation about std::string::getline() can be read at CPP Reference.
Probably the easiest way to read a whole text file is just to concatenate those retrieved lines.
std::ifstream file("Read.txt");
std::string str;
std::string file_contents;
while (std::getline(file, str))
{
file_contents += str;
file_contents.push_back('\n');
}
I know this is a really really old thread but I'd like to also point out another way which is actually really simple... This is some sample code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
ifstream file("filename.txt");
string content;
while(file >> content) {
cout << content << ' ';
}
return 0;
}
I think you could use istream .read() function. You can just loop with reasonable chunk size and read directly to memory buffer, then append it to some sort of arbitrary memory container (such as std::vector). I could write an example, but I doubt you want a complete solution; please let me know if you shall need any additional information.
Well, to do this one can also use the freopen function provided in C++ - http://www.cplusplus.com/reference/cstdio/freopen/ and read the file line by line as follows -:
#include<cstdio>
#include<iostream>
using namespace std;
int main(){
freopen("path to file", "rb", stdin);
string line;
while(getline(cin, line))
cout << line << endl;
return 0;
}
The above solutions are great, but there is a better solution to "read a file at once":
fstream f(filename);
stringstream iss;
iss << f.rdbuf();
string entireFile = iss.str();
you can also use this to read all the lines in the file one by one then print i
#include <iostream>
#include <fstream>
using namespace std;
bool check_file_is_empty ( ifstream& file){
return file.peek() == EOF ;
}
int main (){
string text[256];
int lineno ;
ifstream file("text.txt");
int num = 0;
while (!check_file_is_empty(file))
{
getline(file , text[num]);
num++;
}
for (int i = 0; i < num ; i++)
{
cout << "\nthis is the text in " << "line " << i+1 << " :: " << text[i] << endl ;
}
system("pause");
return 0;
}
hope this could help you :)
hello bro this is a way to read the string in the exact line using this code
hope this could help you !
#include <iostream>
#include <fstream>
using namespace std;
int main (){
string text[1];
int lineno ;
ifstream file("text.txt");
cout << "tell me which line of the file you want : " ;
cin >> lineno ;
for (int i = 0; i < lineno ; i++)
{
getline(file , text[0]);
}
cout << "\nthis is the text in which line you want befor :: " << text[0] << endl ;
system("pause");
return 0;
}
Good luck !
Another method that has not been mentioned yet is std::vector.
std::vector<std::string> line;
while(file >> mystr)
{
line.push_back(mystr);
}
Then you can simply iterate over the vector and modify/extract what you need/
The below snippet will help you to read files which consists of unicode characters
CString plainText="";
errno_t errCode = _tfopen_s(&fStream, FileLoc, _T("r, ccs=UNICODE"));
if (0 == errCode)
{
CStdioFile File(fStream);
CString Line;
while (File.ReadString(Line))
{
plainText += Line;
}
}
fflush(fStream);
fclose(fStream);
you should always close the file pointer after you read, otherwise it will leads to error

C++ Fstream Only Prints One Word

This is a very strange issue. I'm trying to print a large text file, it's a Wikipedia entry. It happens to be the page on Velocity. So, when I tell it to print the file, it prints "In", when it should print "In physics, velocity is etc, etc etc".
Here's the code I'm using to print out:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream wiki;
wiki.open("./wiki/velocity.txt");
char* wikiRead;
wiki >> wikiRead;
cout << wikiRead << endl;
wiki.close();
}
Please help.
wiki >> wikiRead;
The default delimiter for stream is space, so when the stream encounters a space, it simply stops reading, that is why it reads only one word.
If you want the stream to read all words, the you've to use a loop as:
char* wikiRead = new char[1024]; //must allocate some memory!
while(wiki >> wikiRead)
{
cout << wikiRead << endl;
}
wiki.close();
delete []wikiRead; //must deallocate the memory
This will print all the words in the file, each on a new line. Note if any of the word in the file is more than 1024 character long, then this program would invoke undefined behavior, and the program might crash. In that case, you've to allocate a bigger chunk of memory.
But why use char* in the first place? In C++, you've better choice: Use std::string.
#include<string>
std::string word;
while(wiki >> word)
{
cout << word << endl;
}
wiki.close();
Its better now.
If you want to read line-by-line, instead of word-by-word, then use std::getline as:
std::string line;
while(std::getline(wiki, line))
{
cout << line << endl;
}
wiki.close();
This will read a complete line, even if the line contains spaces between the words, and will print each line a newline.
You ask the stream to read the (binary) value of a pointer (probably 4 bytes, depending on your machine architecture), then you ask it to print the text pointed to by those 4 bytes!
I wonder why you ignored the compiler warning (most of the modern compiler warns you about using uninitialized variables). How about this?
ifstream wiki;
wiki.open("./wiki/velocity.txt");
char wikiRead[255];
wiki >> wikiRead;
cout << wikiRead << endl;
wiki.close();
Alternatively I'd suggest you to use string object with getline to get a single line of text.
string str;
getline(wiki, str);
The >> operator applied to a char * reads only one word. Moreover, you're reading into an uninitialized pointer, which is not valid. Usually std::string, not char *, is used for string processing in C++.
If you only want to print the file's contents, you can hook the file's buffer directly to std::cout:
int main() {
std::ifstream wiki("./wiki/velocity.txt");
std::cout << wiki.rdbuf() << '\n';
}
If you want to put the contents into an automatically-allocated string, use std::getline with the delimiter disabled.
int main() {
std::ifstream wiki("./wiki/velocity.txt");
std::string wiki_contents;
getline( wiki, wiki_contents, '\0' /* do not stop at newline */ );
std::cout << wiki_contents << '\n'; // do something with the string
}
Since you want to read a large file, reading it block by block is a better way.
ifstream wiki;
wiki.open("./wiki/velocity.txt");
const int buf_size = 1024;
char* wikiRead = 0;
int cnt = 1;
do
{
wikiRead = realloc( wikiRead, bufsize*cnt );
wiki.Read( wikiRead + (bufSize*(cnt-1)), buf_size ); //appends to reallocated memory
cnt++;
}while( !wiki.eof())
wikiRead[(bufSize*(cnt-2)) + wiki.gcount() + 1] = '\0'; // null termination.
wiki.Close();
cout << wikiRead;
delete[] wikiRead;
The operator>> is designed to only read one word at a time. If you want to read lines, use getline.
#include <iostream>
#include <fstream>
#include<string>
using namespace std;
int main()
{
ifstream wiki;
wiki.open("./wiki/velocity.txt");
string wikiRead;
while (getline(wiki, wikiRead))
{
cout << wikiRead << endl;
}
wiki.close();
}