Reading text file per line in C++, with unknown line length - c++

I have a text file, that is formatted somewhat like this:
1 3 4 5 6
6 7 8
4 12 16 17 18 19 20
20
0
A line can contain 1 to 10000 integers. What I need to do, is read all of them line by line.
Pseudocode like this:
line=0;
i=0;
while(!file.eof()){
while(!endLine){
array[0][i++]=file.readChar();
}
line++;i=0;
}
So, I have an array , into which I would like to read every line, and each line would consist of each of these integers.
The problem I'm having, is how to check if the end of a line has come.
Note, I can't use strings.
Yes, This is for a homework, but the main task for the assignment is to build a tree and then transform it. I can do that, but I've no idea how to read the integers from the file.

Probably something like this:
after reading an int, I manually skip spaces, tabs, carriage return and end of line (for this one you'll have to implement your logic).
To read an int I read it directly using the C++ functions of ifstream. I don't read it character by character and then recompose it as a string :-)
Note that I skip \r as "spaces. The end of line for me is \n.
#include <iostream>
#include <fstream>
#include <vector>
int main()
{
std::ifstream file("example.txt");
std::vector<std::vector<int>> ints;
bool insertNewLine = true;
int oneInt;
//The good() here is used to check the status of
//the opening of file and for the failures of
//peek() and read() (used later to skip characters).
while (file.good() && file >> oneInt)
{
if (insertNewLine)
{
std::vector<int> vc;
ints.push_back(vc);
//With C++11 you can do this instead of the push_back
//ints.emplace_back(std::vector<int>());
insertNewLine = false;
}
ints.back().push_back(oneInt);
std::cout << oneInt << " ";
int ch;
while ((ch = file.peek()) != std::char_traits<char>::eof())
{
if (ch == ' '|| ch == '\t' || ch == '\r' || ch == '\n')
{
char ch2;
if (!file.read(&ch2, 1))
{
break;
}
if (ch == '\n' && !insertNewLine)
{
std::cout << std::endl;
insertNewLine = true;
}
}
else
{
break;
}
}
}
//Here we should probably check if we exited for eof (good)
//or for other file errors (bad! bad! bad!)
return 0;
}

There is a function called getline() which will read a whole line. Link

You need a function to read a value from a file or indicates an end of line or end of file condition, something like:
result_type GetNextValue (input_file, &value)
{
if next thing in file is a number, set value and return number_type
if next thing in file is an end of line, return end_of_line_type
if end of file found, return end_of_file_type
}
and then your array building loop becomes:
line = 0
item = 0
eof = false
while (!eof)
{
switch (GetNextValue (input_file, value))
{
case value_type:
array [line][item++] = value
case end_of_line_type:
line++;
item = 0;
case end_of_file_type:
eof = true
}
}
I'll leave the details to you as it's homework.

You could read the numbers in a char and check against carriage return. A snippet that I had just tried is given below:
ifstream ifile;
ifile.open("a.txt");
char ch;
while((ch = ifile.get()) != EOF)
{
std::cout<<ch<<"\n";
if (ch == '\n')
std::cout<<"Got New Line";
}
ifile.close();

Related

Reading in Floats from Text File and Counting the Columns [duplicate]

How can i read data untill end of line?I have a text file "file.txt" with this
1 5 9 2 59 4 6
2 1 2
3 2 30 1 55
I have this code:
ifstream file("file.txt",ios::in);
while(!file.eof())
{
....//my functions(1)
while(?????)//Here i want to write :while (!end of file)
{
...//my functions(2)
}
}
in my functions(2) i use the data from the lines and it need to be Int ,not char
Don't use while(!file.eof()) as eof() will only be set after reading the end of the file. It does not indicate, that the next read will be the end of the file. You can use while(getline(...)) instead and combine with istringstream to read numbers.
#include <fstream>
#include <sstream>
using namespace std;
// ... ...
ifstream file("file.txt",ios::in);
if (file.good())
{
string str;
while(getline(file, str))
{
istringstream ss(str);
int num;
while(ss >> num)
{
// ... you now get a number ...
}
}
}
You need to read Why is iostream::eof inside a loop condition considered wrong?.
As for reading until the end of the line. there's std::getline.
You have another problem though, and that is that you loop while (!file.eof()) which will most likely not work as you expect. The reason is that the eofbit flag is not set until after you try to read from beyond the end of the file. Instead you should do e.g. while (std::getline(...)).
char eoln(fstream &stream) // C++ code Return End of Line
{
if (stream.eof()) return 1; // True end of file
long curpos; char ch;
curpos = stream.tellp(); // Get current position
stream.get(ch); // Get next char
stream.clear(); // Fix bug in VC 6.0
stream.seekp(curpos); // Return to prev position
if ((int)ch != 10) // if (ch) eq 10
return 0; // False not end of row (line)
else // (if have spaces?)
stream.get(ch); // Go to next row
return 1; // True end of row (line)
} // End function
If you want to write it as function in order to call some where, you can use a vector. This is a function which I use to read such file and return integers element wise.
vector<unsigned long long> Hash_file_read(){
int frames_sec = 25;
vector<unsigned long long> numbers;
ifstream my_file("E:\\Sanduni_projects\\testing\\Hash_file.txt", std::ifstream::binary);
if (my_file) {
//ifstream file;
string line;
for (int i = 0; i < frames_sec; i++){
getline(my_file, line);
numbers.push_back(stoull(line));
}
}
else{
cout << "File can not be opened" << endl;
}
return numbers;
}

Matching word c++ program using getline() running infinitely?

I am learning c++ so bear with me and apologize for any idiocy beforehand.
I am trying to write some code that matches the first word on each line in a file called "command.txt" to either "num_lines", "num_words", or "num_chars".
If the first word of the first line does not match the previously mentioned words, it reads the next line.
Once it hits a matching word (first words only!) it prints out the matching word.
Here is all of my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
ifstream comm_in("commands.txt"); // opens file
string command_name = "hi"; // stores command from file
bool is_command() {
if (command_name == "num_words" || command_name == "num_chars" || command_name == "num_lines") {
return true;
} else {
return false;
}
}
// FIND a first word of a line in file THAT MATCHES "num_words", "num_chars" or "num_lines"
void get_command() {
string line;
char c;
while (!is_command()) { // if command_name does not match a command
// GET NEXT LINE OF FILE TO STRING
getline(comm_in, line);
// SUPPOSED TO GET THE FIRST WORD OF A STRING (CANT USE SSTREAM)
for (int i = 0; i < line.size(); i++) { // increment through line
c = line[i]; // assign c as index value of line
if (c == ' ' || c == '\t') { // if c is a space/tab
break; // end for loop
} else {
command_name += c; // concatenate c to command_name
} // if
} // for
} // while
return;
}
int main() {
get_command();
cout << command_name; // supposed to print "num_lines"
}
The contents of the command.txt file:
my bear is happy
and that it
great ha
num_lines sigh
It compiles properly, but when I run it in my terminal, nothing shows up; it doesn't seem to ever stop loading.
How can I fix this?
Unless you really want to hate yourself in the morning (so to speak) you want to get out of the habit of using global variables. You'll also almost certainly find life easier if you break get_command into (at least) two functions, one specifically to get the first word from the string containing the line.
I'd write the code more like this:
bool is_cmd(std::string const &s) {
return s == "num_words" || s == "num_chars" || s == "num_lines";
}
std::string first_word(std::istream &is) {
std::string line, ret;
if (std::getline(is, line)) {
auto start = line.find_first_not_of(" \t");
auto end = line.find_first_of(" \t", start);
ret = line.substr(start, end - start);
}
return ret;
}
void get_command(std::istream &is) {
std::string cmd;
while (!(cmd = first_word(is)).empty())
if (is_cmd(cmd)) {
std::cout << cmd;
break;
}
}
This still isn't perfect (e.g., badly formed input could still cause it to fail) but at least it's a move in what I'd say is a better direction.
If something goes wrong and you reach the end of file the loop will never stop. You should change getline(comm_in, line) to if(!getline(comm_in, line)) break;, or better yet, use that as the condition for the loop.
You also have to reset command_name for each pass:
while(getline(comm_in, line))
{
command_name = "";
for(int i = 0; i < line.size(); i++)
{
c = line[i];
if(c == ' ' || c == '\t')
break;
else
command_name += c;
}
if(is_command())
break;
}
// FIND a first word of a line in file THAT MATCHES "num_words", "num_chars" or "num_lines"
void get_command()
{
string line;
char c;
while (!is_command()) { // if command_name does not match a command
// GET NEXT LINE OF FILE TO STRING
if(getline(comm_in, line),comm_in.fail()){
// end reading
break;
}
//clear
command_name = "";
// SUPPOSED TO GET THE FIRST WORD OF A STRING (CANT USE SSTREAM)
for (int i = 0; i < line.size(); i++) { // increment through line
c = line[i]; // assign c as index value of line
if (c == ' ' || c == '\t') { // if c is a space/tab
break; // end for loop
} else {
command_name += c; // concatenate c to command_name
} // if
} // for
} // while
return;
}
The key of this problem is that you didn't clear the command_name.
What's more, you have to add a judge about whether reaching the end of the file.
ps: if(getline(comm_in, line),comm_in.fail()) is equal to if(getline(comm_in, line)),

How to know it's the end of the line in c++ reading file

I need to know how to stop if it's the end of the line
I need the int value for the last element which is 15
and also for the other lines, I need to know if this value is the last element in the line
i try getline(file ,line)
but it just gives me a string!
and also line.length(); gives me the length of the file.
You should either use std::getline and parse the string you get, or go char-by-char and treat CR/LF as end of line. Then just move back from it until you get a space.
You should continue to use your getline function, from that you will have your std::string then to pull your last digit use:
string str = <getline() result>
size_t last_index = str.find_last_not_of("0123456789");
string result = str.substr(last_index + 1);
int num = std::stoi(result);
This will give you your int representation of your last number.
This will extract the last number on each line:
ifstream f ("./numbers");
vector<int> v;
int i;
while (f >> i) {
char c = f.get();
if (f.eof() || c == '\r' || c == '\n') {
v.push_back(i);
}
}
f.eof() may be true if the file is not terminated by a new line, in which case the f.get() call may fail and set the eofbit.
std::ifstream file{"your-file"};
std::string line;
while (getline(file, line)) {
std::istringstream iss{line};
std::vector<int> vec{std::istream_iterator<int>{iss},
std::istream_iterator<int>{}};
if (vec.size() == 1) {
// only one element
}
vec.back() // last value of the line (/!\ check not empty first)
}

Checking stringstream line char by char C++

I will keep it short and simple. After making sure that user is able to open a file succesfully, I have written the following piece of code to take a line from the inputFile.
string line;
int counter = 0;
DynIntStack stack;
while (!inputFile.eof())
{
getline(inputFile, line);
stringstream inputLine(line);
counter++;
//I NEED TO DO IT HERE
}
This will be used to write program to check balanced paranthesis in an input cpp file and I have to use stacks. Classic CS homework as I understand from the topics I have checked :)
counter is updated after every line and the line number(counter) is to be pushed to the stack if it has a opening bracket and it must be popped from the stack if it is a closing bracket. after these, the output should look something like this:
block: 3 - 3
block: 12 - 14
block: 10 - 14
block: 5 - 16
Syntax error in line 21.
But I do not know how to check the line I got char by char. I need a loop to check the chars and apply the previously mentioned things if an opening or closing bracket is found. How can I check the line char by char.
using any data container other than stacks is forbidden.
thank you very much :)
But I do not know how to check the line I got char by char
Is this what you want?
string line;
int counter = 0;
DynIntStack stack;
while (getline(inputFile, line))
{
counter++;
for(size_t i = 0; i < line.length(); i++) {
// line[i] is i'th character
if(line[i] == '(') {
// do stuff
}
else if(line[i] == ')') {
// do stuff
}
}
}
In addition to the correct answer by Kaidul Islam, a std::string support range based for loops.
string line;
int counter = 0;
DynIntStack stack;
while (getline(inputFile, line))
{
++counter;
for (char const c : line)
{
if (c == '(')
{
// do stuff
}
else if (c == ')')
{
// do stuff
}
}
}

Read from file in c++ till end of line?

How can i read data untill end of line?I have a text file "file.txt" with this
1 5 9 2 59 4 6
2 1 2
3 2 30 1 55
I have this code:
ifstream file("file.txt",ios::in);
while(!file.eof())
{
....//my functions(1)
while(?????)//Here i want to write :while (!end of file)
{
...//my functions(2)
}
}
in my functions(2) i use the data from the lines and it need to be Int ,not char
Don't use while(!file.eof()) as eof() will only be set after reading the end of the file. It does not indicate, that the next read will be the end of the file. You can use while(getline(...)) instead and combine with istringstream to read numbers.
#include <fstream>
#include <sstream>
using namespace std;
// ... ...
ifstream file("file.txt",ios::in);
if (file.good())
{
string str;
while(getline(file, str))
{
istringstream ss(str);
int num;
while(ss >> num)
{
// ... you now get a number ...
}
}
}
You need to read Why is iostream::eof inside a loop condition considered wrong?.
As for reading until the end of the line. there's std::getline.
You have another problem though, and that is that you loop while (!file.eof()) which will most likely not work as you expect. The reason is that the eofbit flag is not set until after you try to read from beyond the end of the file. Instead you should do e.g. while (std::getline(...)).
char eoln(fstream &stream) // C++ code Return End of Line
{
if (stream.eof()) return 1; // True end of file
long curpos; char ch;
curpos = stream.tellp(); // Get current position
stream.get(ch); // Get next char
stream.clear(); // Fix bug in VC 6.0
stream.seekp(curpos); // Return to prev position
if ((int)ch != 10) // if (ch) eq 10
return 0; // False not end of row (line)
else // (if have spaces?)
stream.get(ch); // Go to next row
return 1; // True end of row (line)
} // End function
If you want to write it as function in order to call some where, you can use a vector. This is a function which I use to read such file and return integers element wise.
vector<unsigned long long> Hash_file_read(){
int frames_sec = 25;
vector<unsigned long long> numbers;
ifstream my_file("E:\\Sanduni_projects\\testing\\Hash_file.txt", std::ifstream::binary);
if (my_file) {
//ifstream file;
string line;
for (int i = 0; i < frames_sec; i++){
getline(my_file, line);
numbers.push_back(stoull(line));
}
}
else{
cout << "File can not be opened" << endl;
}
return numbers;
}