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

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]);
}
}

Related

how to properly use fstream and passing data in a char array?

In this function what I have to do is pass the strings from txt file in char and do some operations. My only problem is on pass file from txt to char. how i should fix it?
char* foo(string& input){
stringstream ss;
ss<<input;
char *elements=new char[32];
elements[32]='\0';
ss>>elements; //next part code not written because useless
This is how you can store data in a char array from a file:
Source File
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream inFile;
inFile.open("Input File.txt");
char Array[50] = { ' ' };
inFile.get(Array, 50);
cout << "Output : " << Array << endl;
inFile.close();
}
Text File
Enter Text Here
If you want i can make a dynamic array for you which will have the exact size as the string (Data you input) from file or use vectors because they can easily be expanded and shortened in late binding(means: during program execution).

I/O ascii codes to foreign characters

Using cout << "\n\u00f3\n << endl, I can print ó with newlines at the Unix command line. Once I start attempting to read files and print strings containing the characters, I see the literal output instead \n\u00f3\n.
I am not sure if this is because the file read techniques use character arrays or if there is some other nuance I do not know.
Any ideas?
Thanks!
const char *filename ="spanish_project_sample1.txt";
FILE *file = fopen(filename, "r");
int c;
char *data;
data = " ";
while ((c=fgetc(file)) != EOF) {
data = appendCharToCharArray(data, c);
}
printf("%s", data);
I looked at the JavaScript solutions to a similar problem (e.g. FromCharCode) and found this code online:
https://ideone.com/Udo3hN
#include <cstdarg>
#include <iostream>
using namespace std;
string FromCharCode ( int num, ... )
{
va_list arguments;
char ch;
string s;
va_start ( arguments, num );
for ( int x = 0; x < num; x++ )
{
ch = va_arg ( arguments, int );
s = s + ch;
}
va_end ( arguments );
return s;
}
int main()
{
cout<<FromCharCode (10,73,78,68,69,83,73,71,78,33,33) ;//<<endl;
return 0;
}
Specifically, it looks like reading in the characters is the issue because at runtime instead of reading '\n' as value 10 for example, the character array would actually record two ints [92,110].
Using a hardcoded string, the compiler parses the escaped characters as the desired values.
Any suggestions or solutions still welcome.
The C++ idiom for reading a file line by line is:
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
string line;
ifstream ifs;
ifs.open(argv[1]);
while(getline(ifs, line))
cout << line << endl;
}
Try that.
Your problem is probably one of interpretation though. If you have "\n\u00f3\n" in a file, that is what it reads and prints. If you have "ó" in the file, which is stored as \u00f3 in UTF-16, you will get what you want. The i/o routines don't do any conversion.
You also need to know if your file is in UTF-8 or UTF-16 so that you can read it properly.

String manipulation and File IO in 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!

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;
}
}
...

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();
}