How to read the whole lines from a file (with spaces)? - c++

I am using STL. I need to read lines from a text file. How to read lines till the first \n but not till the first ' ' (space)?
For example, my text file contains:
Hello world
Hey there
If I write like this:
ifstream file("FileWithGreetings.txt");
string str("");
file >> str;
then str will contain only "Hello" but I need "Hello world" (till the first \n).
I thought I could use the method getline() but it demands to specify the number of symbols to be read. In my case, I do not know how many symbols I should read.

You can use getline:
#include <string>
#include <iostream>
int main() {
std::string line;
if (getline(std::cin,line)) {
// line is the whole line
}
}

using getline function is one option.
or
getc to read each char with a do-while loop
if the file consists of numbers, this would be a better way to read.
do {
int item=0, pos=0;
c = getc(in);
while((c >= '0') && (c <= '9')) {
item *=10;
item += int(c)-int('0');
c = getc(in);
pos++;
}
if(pos) list.push_back(item);
}while(c != '\n' && !feof(in));
try by modifying this method if your file consists of strings..

Thanks to all of the people who answered me. I made new code for my program, which works:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char** argv)
{
ifstream ifile(argv[1]);
// ...
while (!ifile.eof())
{
string line("");
if (getline(ifile, line))
{
// the line is a whole line
}
// ...
}
ifile.close();
return 0;
}

I suggest:
#include<fstream>
ifstream reader([filename], [ifstream::in or std::ios_base::in);
if(ifstream){ // confirm stream is in a good state
while(!reader.eof()){
reader.read(std::string, size_t how_long?);
// Then process the std::string as described below
}
}
For the std::string, any variable name will do, and for how long, whatever you feel appropriate or use std::getline as above.
To process the line, just use an iterator on the std::string:
std::string::iterator begin() & std::string::iterator end()
and process the iterator pointer character by character until you have the \n and ' ' you are looking for.

Related

How can I read from a file and sort them by category

I'm trying to read a bunch of words from a file and sort them into what kind of words they are (Nouns, Adjective, Verbs ..etc). For example :
-Nouns;
zyrian
zymurgy
zymosis
zymometer
zymolysis
-Verbs_participle;
zoom in
zoom along
zoom
zonk out
zone
I'm using getline to read until the delimiter ';' but how can I know when it read in a type and when it read in a word?
The function below stop right after "-Nouns;"
int main()
{
map<string,string> data_base;
ifstream source ;
source.open("partitioned_data.txt");
char type [MAX];
char word [MAX];
if(source) //check to make sure we have opened the file
{
source.getline(type,MAX,';');
while( source && !source.eof())//make sure we're not at the end of file
{
source.getline(word,MAX);
cout<<type<<endl;
cout<<word<<endl;
source.getline(type,MAX,';');//read the next line
}
}
source.close();
source.clear();
return 0;
}
I am not fully sure about the format of your input file. But you seem to have a file with lines, and in that, items separated by a semicolon.
Reading this should be done differently.
Please see the following example:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
std::istringstream source{R"(noun;tree
noun;house
verb;build
verb;plant
)"};
int main()
{
std::string type{};
std::string word{};
//ifstream source{"partitioned_data.txt"};
if(source) //check to make sure we have opened the file
{
std::string line{};
while(getline(source,line))//make sure we're not at the end of file
{
size_t pos = line.find(';');
if (pos != std::string::npos) {
type = line.substr(0,pos);
word = line.substr(pos+1);
}
std::cout << type << " --> " << word << '\n';
}
}
return 0;
}
There is no need for open and close statements. The constructor and
destructor of the std::ifstream will do that for us.
Do not check eof in while statement
Do not, and never ever use C-Style arrays like char type [MAX];
Read a line in the while statement and check validity of operation in the while. Then work on the read line later.
Search the ';' in the string, and if found, take out the substrings.
If I would knwo the format of the input file, then I will write an even better example for you.
Since I do not have files on SO, I uses a std::istringstream instead. But there is NO difference compared to a file. Simply delete the std::istringstream and uncomment teh ifstream definition in the source code.

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.

Trouble with parsing text file based on commas (C++)

I am working on creating a program that is supposed to read a text file (ex. dog, buddy,,125,,,cat,,,etc...) line by line and parse it based on commas. This is what I have so far but when I run it, nothing happens. I am not entirely sure what i'm doing wrong and I am fairly new to the higher level concepts.
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <cstdlib>
#include <sstream>
#include <vector>
using namespace std;
int main()
{
std::ifstream file_("file.txt"); //open file
std::string line_; //declare line_ as a string
std::stringstream ss(line_); //using line as stringstream
vector<string> result; //declaring vector result
while (file_.is_open() && ss.good())
{ //while the file is open and stringstream is good
std::string substr; //declares substr as a string
getline( ss, substr, ',' ); //getting the stringstream line_ and substr and parsing
result.push_back(substr);
}
return 0;
}
Did you forget to add a line like std::getline(file_, line_);? file_ was not read from at all and line_ was put into ss right after it was declared when it was empty.
I'm not sure why you checked if file_ is open in your loop condition since it will always be open unless you close it.
As far as I know, using good() as a loop condition is not a good idea. The flags will only be set the first time an attempt is made to read past the end of the file (it won't be set if you read to exactly the end of the file when hitting the delimiter), so if there was a comma at the end of the file the loop will run one extra time. Instead, you should somehow put the flag check after the extraction and before you use the result of the extraction. A simple way is to just use the getline() call as your loop condition since the function returns the stream itself, which when cast into a bool is equivalent to !ss.fail(). That way, the loop will not execute if the end of the file is reached without extracting any characters.
By the way, comments like //declaring vector result is pretty much useless since it gives no useful information that you can't easily see from the code.
My code:
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
int main()
{
std::ifstream file("input.txt");
std::string line, word;
std::vector<std::vector<string>> result; //result[i][j] = the jth word in the input of the ith line
while(std::getline(file, line))
{
std::stringstream ss(line);
result.emplace_back();
while(std::getline(ss, word, ','))
{
result.back().push_back(word);
}
}
//printing results
for(auto &i : result)
{
for(auto &j : i)
{
std::cout << j << ' ';
}
std::cout << '\n';
}
}

Read text file char by char instead of word by word?

I tried to make a code that reads from text file called aisha
This is a new file I did it for as a trial for university
but it worked =)
Its about Removing stopwords from the file
and apply casefolding to it
It tried doing that many times
and finally now I could do now
and then the code stores the read text on an array and then removes the stopwords from it
but now I nead to make the case folding step
the problem that this code reads the text file word by word
I want to read it char by char so I can apply casefolding to each char
is there ant way to make the code read the aisha file char by char ?
#include <iostream>
#include <string>
#include <fstream>
int main()
{
using namespace std;
ifstream file("aisha.txt");
if(file.is_open())
{
string myArray[200];
for(int i = 0; i < 200; ++i)
{
file >> myArray[i];
if (myArray[i] !="is" && myArray[i]!="the" && myArray[i]!="that"&& myArray[i]!="it"&& myArray[i]!="to"){
cout<< myArray[i]<<" ";
}
}
}
system("PAUSE");
return 0;
}
If you declare your array as an array of char instead of array of strings, the extraction operator shall automatically read char.
Also you will have to be careful because the >> operator by default skips the whitespace characters. If you want to read the whitespaces also, then you should add noskipws before reading the characters.
file >> std::noskipws;
The C++ way to do this is explained at this link: http://www.cplusplus.com/reference/istream/istream/get/
#include <iostream> // std::cin, std::cout
#include <vector> // store the characters in the dynamic vector
#include <fstream> // std::ifstream
int main () {
std::ifstream is("aisha.txt"); // open file and create stream
std::vector <char> stuff;
while (is.good()) // loop while extraction from file is possible
{
char c = is.get(); // get character from file
if (is.good())
std::cout << c; // print the character
stuff.push_back(c); // store the character in the vector
}
is.close(); // close file
return 0;
}
Now you basically have every character of the file stored in the vector known as stuff. You can now do your modification to this vector, for it is a far easier internal representation of data. Also, you have access to all the handy STL methods.
Use Whole string instead of reading char by char
using readline function.

Read a file backwards?

Is there a way to read a file backwards, line by line, without having to go through the file from the beginning to start reading backwards?
Use a memory-mapped file and walk backwards. The OS will page in the needed parts of the file in reverse order.
As per comment, a possible (quite simple) alternative would be read the lines into a vector. For example:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
int main()
{
std::ifstream in("main.cpp");
if (in.is_open())
{
std::vector<std::string> lines_in_reverse;
std::string line;
while (std::getline(in, line))
{
// Store the lines in reverse order.
lines_in_reverse.insert(lines_in_reverse.begin(), line);
}
}
}
EDIT:
As per jrok's and Loki Astari's comments, push_back() would be more efficient but the lines would be in file order, so reverse iteration (reverse_iterator) or std::reverse() would be necessary:
std::vector<std::string> lines_in_order;
std::string line;
while (std::getline(in, line))
{
lines_in_order.push_back(line);
}
Slightly improved version will be this:-
1)Seek to the last-1 position
2)Get the last-1 position
3)Read a char and print it;
4)seek 2 pos back;
5)repeat 3 &4 for last-1 times;
ifstream in;
in.open("file.txt");
char ch;
int pos;
in.seekg(-1,ios::end);
pos=in.tellg();
for(int i=0;i<pos;i++)
{
ch=in.get();
cout<<ch;
in.seekg(-2,ios::cur);
}
in.close();
Open the file for read, call fseek() to seek to the end of the file, then call ftell() to get the length of the file. Alternatively you can get the file length by calling stat() or fstat()
Allocate a buffer pointer to the file size obtained in #1, above.
Read the entire file into that buffer -- you can probably use fread() to read the file all in one shot (assuming the file is small enough).
Use another char pointer to transverse the file from end to beginning of the buffer.
The short answer would be no. However, you can use the seek() function to move your pointer to where you want to go. Then read() some data from that point. If you know well how to manage buffers, then it should be pretty quick because you can read and cache the data and then search for the previous newline character(s). Have fun with \r\n which will be inverted...
-- Update: some elaboration on the possible algorithm --
This is not valid code, but it should give you an idea of what I'm trying to say here
File reads:
int fpos = in.size() - BUFSIZ;
char buf[BUFSIZ];
in.seek(fpos);
in.read(buf, BUFSIZ);
fpos -= BUFSIZ; // repeat until fpos < 0, although think of size % BUFSIZ != 0
// now buf has characters... reset buffer position
int bpos = BUFSIZ - 1;
Getting string:
// first time you need to call the read
if(bpos == -1) do_a_read();
// getting string
std::string s;
while(bpos >= 0 && buf[bpos] != '\n') {
s.insert(0, 1, buf[bpos]);
--bpos;
}
// if bpos == -1 and buf[0] != '\n' then you need to read another BUFSIZ chars
// and repeat the previous loop...
// before leaving, skip all '\n'
while(bpos >= 0 && buf[bpos] == '\n') {
--bpos;
}
return s;
To ease with '\r', you could have a first pass that transforms all '\r' to '\n'. Otherwise, all the tests of '\n' need to also test for '\r'.
My answer is similar to ones that use a vector to store the lines of the file, but I would instead use a list.
Imagine you have the following text in a file called input.txt:
hello
there
friend
I would read the file line-by-line, pushing each line not to the back of my list but to its front. Using this rather than push_back has the same effect as reading the contents of the file line-by-line into a vector and then reversing it or iterating through it backwards.
#include <iostream>
#include <fstream>
#include <list>
#include <string>
#include <iterator>
#include <algorithm>
int main(void) {
std::ifstream file;
file.open("input.txt");
// Make sure the file opened properly
std::list<std::string> list;
std::string buffer;
while (std::getline(file, buffer)) {
list.push_front(buffer);
}
file.close();
std::copy(
list.begin(),
list.end(),
std::ostream_iterator<std::string>(std::cout, "\n")
);
return 0;
}
(Note that the bit at the bottom with std::copy is just to print the contents of the list with a newline character as a delimiter between elements.)
This then prints:
friend
there
hello
this might help.
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
ifstream myFile("my.txt");
int count;
cout << "Enter the number of lines u want to print ";
cin >> count;
char c;
string str = "";
for (int i = 1; i <= 10000; i++)
{
myFile.seekg(-i, std::ios::end);
myFile.get(c);
str += c;
if (c == '\n')
{
reverse(str.begin(), str.end());
count--;
cout << str;
str.clear();
}
if (count == 0)
{
break;
}
}
cout << endl;
return 0;
}