I'm trying to read in a file into an array so that I could process the array into selection sort. But when I try to read in the file, I get a segmentation fault(core dumped) error. Here is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string array[40707];
int loop = 0;
int loop2;
string line;
ifstream inFile("beowulf.txt");
if (inFile.is_open())
{
while(!inFile.eof())
{
getline(inFile, line);
array[loop] = line;
loop++;
}
inFile.close();
}
else cout << "Unable to open file" << endl;
for (loop2 =0; loop2 <= loop; loop2++)
cout << array[loop2] << endl;
return 0;
}
Change your string array to:
std::vector<std::string> array;
Then you can read the file and copy into the vector simply as:
std::copy(std::istream_iterator<std::string>(inFile),
std::istream_iterator<std::string>(),
std::back_inserter(array));
EDIT: To read the file line-by-line, either define your own insert_iterator or do it like this:
std::string line;
while (getline(inFile, line))
array.push_back(line);
Your code will then change to something like this
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<string> array;
string line;
ifstream inFile("beowulf.txt");
if (!inFile.is_open()) {
cerr << "Unable to open file" << endl;
return 1;
}
while (getline(inFile, line))
array.push_back(line);
inFile.close();
for (int i = 0; i < array.size(); ++i)
cout << array[i] << endl;
return 0;
}
Two potential error cases I can see right away.
Overrunning the end of the end of array. It can happen while reading because there is no guard on loop. If the array read was exactly 40707 lines it will happen while printing out when loop2 == loop. Either of these is probably the cause of the segfault. The recommended solution is to use C++'s std::vector because it will dynamically size itself to the input and automate iterating through the items stored.
The second error is less severe, but allows an infinite loop on an IO error. The end of file may never be reached if an error prevents reading a line and places the stream in an error condition. Unlikely to happen with getline, but a common occurrence with formatted reads.
Using most of the OP's solution:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<string> array; // vector eliminates buffer overflow problem of string array.
//int loop = 0; vector also eliminates the need for this counter
//int loop2; and this one
string line;
ifstream inFile("beowulf.txt");
if (inFile.is_open())
{
while(getline(inFile, line)) //exits if anything goes wrong with the file IO
{
array.push_back(line); // stores line in vector
}
inFile.close();
}
else cout << "Unable to open file" << endl;
// C++11 way
for (string const & str: array)
{ // iterates through the string automatically
cout << str << endl;
}
/* Old C++ way
for (vector<string>::iterator str = array.begin();
token != array.end();
++token)
{ // iterates through the string manually
cout << *str << endl;
}
*/
return 0;
}
Related
I am trying to get the amount of lines in a file in order to make an array to store the characters of each line. I think the problem is with the two while loops iterating at the same time.
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using std::string;
int main(int argc, char *argv[]){
cout << "input file" << endl;
string file;
cin >> file;
ifstream inFile;
inFile.open(file, ios::in);
cout << "success1";
if (inFile.is_open()) {
vector<double> inputs;
string line;
string s;
int current;
int sTotal;
while(!inFile.eof()) {
getline(inFile, s);
sTotal++;
}
while (!inFile.eof()) {
getline(inFile, line);
cout << "success2";
char *lineArr = new char[line.length()][sTotal];
for(int j = 0;j < sTotal;j++){
for (int i = 0; i < sizeof(lineArr); i++) {
lineArr[i] = line[i];
}
}
}
}else cout << "fail";
}
Any help would be appreciated. Im probably looking at this all wrong.
A main issue with your code is that you consume the stream in the first while loop and then try to do it again. They are not "iterating at the same time", they are two successive loops with the same exit condition. In virtually every case that results in the second one not executing at all.
Also, if you are allowing yourself to use str::string and std::vector, avoid using char*, it only adds confusion.
Try a single loop, using a vector<string> to push each line you get and print in the end the length of the loop. Have a look at these links: std::vector, getline
A rough sketch of what I mean:
vector<string> lines;
string line;
while(getLine(inFile, line)){
lines.push(line);
}
cout << lines.size() << endl;
Then if you want to count the words per line, iterate again through the vector, and split each element; there are several ways to do that as well.
hi I am trying to read a specific line from a text file update that and put it back to the same line without affecting the other lines in c++
here I am trying to execute the code and values get added when I re-execute it
#include <iostream>
#include <stream>
#include <stdio.h>
#include <string>
#include <stream>
using namespace std;
void stringGen(char num){
ifstream ifile;
ifile.open("example1.txt");
if(ifile) {
int LINE = 5;
string line;
ifstream myfile1 ("example1.txt");
for (int i = 1; i <= LINE; i++)
getline(myfile1, line);
cout << line<<endl;
stringstream geek(line);
int num=0;
geek>>num;
if(num<61004){
num=num+1;
ofstream MyFile("example1.txt");//
MyFile.close();
}
else{
num=61001;
ofstream MyFile("example1.txt");//
MyFile << num;
MyFile.close();
}
}
else{
int num=61001;
cout<<num<<endl;
ofstream MyFile("example1.txt");//
MyFile << num+1;
MyFile.close();
}
}
int main (){
char num;
stringGen(num);
return 0;
}
At first, you need to understand, how files, with lines are stored. Simplified, it is a sequence of bytes, one byte after the other. There maybe some special characters in this byte sequence, which people can interprete as the end of a line, e.g. '\n'. But also other characters or even more than one character is possible:
If you look at the following text.
Hello1
World1
Hello2
World2
it maybe stored in a file like this:
Hello1\nWorld1\nHello2\nWorld2\n
And just because we interprete a '\n' as the end of the line, we can "see" lines in there.
So, if you want to modify a line, then you would need to find the start position of the thing that we interprete as a line in the file, and then modify some bytes.
That can of course only be done, if the length of the "line" will not change. Then you could use "seek" functions and overwrite the needed bytes.
In reality, nobody would do that. Normally, you would read "lines" of the file into some kind of memory buffer, then do the modification there and then write back all lines.
For example, you would define a std::vector and then read all lines, by using std::getline and push_back the lines in the std::vector.
The modifications will be done in the std::vector, and the all data will be written back to the file, overwriting all "old" data.
There are more answers to this question. If you have any more specific question, I will answer again
Some simple example code
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
int main() {
// Here we will store all lines of the text file
std::vector<std::string> lines{};
// Open the text file for reading and check, if it could be opened
if (std::ifstream textfileStream{ "test.txt" }; textfileStream) {
// Read all lines into our vector
std::string oneLine{};
while (std::getline(textfileStream, oneLine)) {
// Add the just read line to our vector
lines.push_back(oneLine);
}
// For test purposes, modify the first line
if (not lines.empty()) lines[0] = "MODIFIED";
}
else std::cerr << "\nError: Could not open input text file\n";
// Write back data
// Open the text file for writing and check, if it could be opened
if (std::ofstream textfileStream{ "r:\\test.txt" }; textfileStream) {
// Iterate over all lines and wriite to file
for (const std::string& oneLine : lines)
textfileStream << oneLine << '\n';
}
else std::cerr << "\nError: Could not open output text file\n";
return 0;
}
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string>
#include <sstream>
using namespace std;
void stringGen(char num){
int count=0;
int a;
string line,check,linex;
string msg="Message_Handler:";
fstream ifile;
ifile.open("sample.txt",ios::in|ios::out);
if(ifile){
while(getline (ifile,line)) {
if (line.find("Message_Handler:") == 0){
check=line.substr(16,5);
count++;
a=ifile.tellp();
}
}
ifile.close();
if(count==0){
int num=61001;
cout<<num<<endl;
num=num+1;
ofstream examplefile ("sample.txt",ios::app);
examplefile<<"Message_Handler:"<<num;
examplefile.close();
}
if(count==1){
cout<<check<<endl;
stringstream geek(check);
int num=0;
geek>>num;
if(num<61004){
num=num+1;
stringstream ss;
ss << num;
string nums = ss.str();
fstream MyFile("sample.txt",ios::in|ios::out);
MyFile.seekp(a-5);
MyFile<<nums;
}
else{
int num=61001;
stringstream ss;
ss << num;
string nums = ss.str();
fstream MyFile("sample.txt",ios::in|ios::out);
MyFile.seekp(a-5);
MyFile<<nums;
}
}
}
else{
int num=61001;
cout<<num<<endl;
ofstream MyFile("sample.txt",ios::app);
MyFile <<"Message_Handler:"<< num+1;
MyFile.close();
}
}
int main (){
char num;
stringGen(num);
return 0;
}
I have double numbers in a file (one on each line) that I am trying to read into a c++ array. I am using the below code, but get the below error while running:
segmentation fault: 11
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main () {
string line;
ifstream myfile ("temp2.csv");
std::vector<double> myArray;
int index = 0;
if (myfile.is_open())
{
while (! myfile.eof() )
{
getline (myfile,line);
cout << line << endl;
// myArray[index++] << line;
myArray[index++] = atoi( line.c_str() );
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
You can't do
myArray[index++] = atoi( line.c_str() );
It is an empty vector. You either need to push_back elements into it. Or initialize it with sufficient memory.
This should work:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <stdlib.h>
using namespace std;
int main () {
string line;
ifstream myfile ("temp2.csv");
std::vector<double> myArray;
int index = 0;
if (myfile.is_open())
{
while (! myfile.eof() )
{
getline (myfile,line);
cout << line << endl;
// myArray[index++] << line;
myArray.push_back(atoi( line.c_str() ));
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
On this line:
std::vector<double> myArray;
You create a vector using the default constructor. As you can see from the documentation, the default constructor creates an empty vector.
On this line:
myArray[index++] = atoi( line.c_str() );
You access elements from the vector with successively increasing indices. But those elements do not exist and the indices are out of bounds because the vector is empty. Accessing outside the bounds of the vector has undefined behaviour.
TL;DR you forgot to add any elements into the vector.
The code is far more complex than it needs to be. It's much simpler to just read one value at a time:
std::vector<double> myArray;
double value;
std::ifstream myfile(temp2.csv);
if (!myfile) {
std::cout << "Unable to open file\n");
return EXIT_FAILURE;
}
while (myfile >> value)
myArray.push_back(value);
Hey guys I stuck working on an assignment in which I asked to write a program that lists the contents of a file.
#include<iostream>
#include<fstream>
using namespace std;
int main() {
string array[5];
ifstream infile("file_names.txt");
int x=0;
while(infile>>array[x++]){
for(int i=0;i<=x;i++){
infile >> array[i];
cout << array[i] << endl;}}
}
basically I have a file named "file_names.txt" that contains three strings and I want my program to list them.
you don't need two loops.
int main() {
int array_size=5;
string array[array_size];
ifstream infile("file_names.txt");
int x=0;int i=0;
while(i<array_size && infile>>array[i]){ //order is important here
cout << array[i] << endl;
i++;
}
}
Your assignment was
an assignment in which I asked to write a program that lists the contents of a file.
One way of printing the contents of a file could be
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ifstream fin("my_file.txt", ios::in); // open input stream
if(!fin){ // check state, that file could be successfully opened
printf("Error opening file.");
return 1;
}
while(fin.peek() != EOF){
cout << (char)fin.get();
}
fin.close(); // close input stream
return 0;
}
This code demonstrates some basic C++ functionality like
opening an input stream, checking the state of the input stream and reading the contents character by character. Try to understand each step.
I know I can get to the same result like this
string array[50];
ifstream infile("file_names.txt");
for(int i=0; **i<3**; i++){
infile >> array[i];
cout << array[i] <<endl;}
But the whole point is to use a while loop because there might be more or less than 3 items
I have a problem trying to count words inside of a vector. A vector holds every line from a file as an object. v[0] is the first line, v[1] is the second line, so on.
For my countWords() function, it only works for counting v[0]. Any object past that is ignored or missed some how. Any ideas? Thanks in advance.
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
int countWords(vector<string> v)
{
stringstream ss;
string word;
int count = 0;
for(int i = 0; i < v.size(); i++) {
ss.str(v[i]);
while (ss >> word)
count++;
}
return count;
}
void readFile(string filename,vector<string> &v)
{
fstream file;
string line;
file.open(filename,ios::in);
while(getline(file,line)) { //Reads the file line by line ...
if(line == "") //... ignoring any empty lines ...
continue;
v.push_back(line); //... and puts them into our vector.
}
file.close();
}
int main(int argc,char* argv[])
{
if (argc != 2) { //Terminate unless the user enters -ONE- entry.
cout << "Usage: " << argv[0] << " <filename>" << endl;
exit(1);
}
string filename = argv[1];
vector<string> fileContents;
readFile(filename,fileContents);
cout << countWords(fileContents) << endl;
}
As an alternative to RichieHindle's answer, this works too. Just have the stringstream scope local to the for loop and it will reset properly.
int countWords(vector<string> v)
{
string word;
int count = 0;
for(int i = 0; i < v.size(); i++) {
stringstream ss(v[i]);
while (ss >> word)
count++;
}
return count;
}
Before you reuse stringstream you must do
ss.clear();
after your while loop.
You could also declare it inside the for() loop, but then it would be reinitialized again. For readabillity, this might be better. Performancewise it could make a difference.
I bet ss goes into an error state when you've exhausted it for the first time and doesn't reset just because you call str.
Declare ss inside the for loop and pass the string directly to the constructor. This avoids such problems.
In general, you have the bad habit of declaring your variables in a bunch instead of closest to where you need them, and not using constructors. For example, you could pass the filename to fstream's constructor instead of calling open. And you could use ifstream so you don't need the second argument.