For this project, we are supposed to use an input and output file to better organize our data. Howvever, for whatever reason, every time I rube the program it says
"File couldn't open. Terminating.
Process finished with exit code 1"
I have tried several different methods to try and get the program to open the file (using different commands, changing filename, etc), however each time it gives me the above statement.
Here is the code for my program (please note there is much more code than this. However, this is the only area that uses the input file, so I am confident that the error is residing somewhere withing here):
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <iomanip>
#include <limits>
#ifdef _MSC_VER // Memory leak check
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define VS_MEM_CHECK _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#else
#define VS_MEM_CHECK
#endif
using namespace std;
const int NUM_GRADES = 5;
int main(int argc, char* argv[]) {
VS_MEM_CHECK // Enable memory leak check
ifstream inputFile; // Reading Input file
inputFile.open(argv[1]);
if (inputFile.is_open()) { // Checks if file opened succesfully
cout << "Input File opened successfully.\n";
} else {
cout << "File couldn't open. Terminating.\n";
return 1;
}
int numStudents;
int numExams;
inputFile >> numStudents >> numExams;
inputFile.ignore(std::numeric_limits<int>::max(), '\n');
string *arrayNames = new string[numStudents]; // Intializes Students Array
double *arrayTotalGrade = new double[numStudents]; // Initializes Total Score Array
double *arrayAverages = new double[numExams]; // Initializes Average Score Array
int **arrayScores = new int *[numStudents]; // Initializes Scores Array
for (int i = 0; i < numStudents; ++i) {
arrayScores[i] = new int[numExams];
}
int **arrayGradeCount = new int *[numExams]; // Initializes Grade Count Array
for (int i = 0; i < numExams; ++i) {
arrayGradeCount[i] = new int[NUM_GRADES];
for (int j = 0; j < NUM_GRADES; ++j) {
arrayGradeCount[i][j] = 0;
}
}
for (int i = 0; i < numStudents; ++i) {
string line;
string name;
getline(inputFile, line);
size_t p = 0;
while (!isdigit(line[p])) ++p; // line[p] is the location of the first digit on the line
name = line.substr(0, p - 1); // Gets name from file, p-1 removes an extra whitespace.
arrayNames[i] = name;
line = line.substr(p); // Isolates scores on line
istringstream iss(line); // Puts line (now with only scores' values) into an istringstream
for (int j = 0; j < numExams; ++j) // Puts scores from istringstream into arrayScores onto row 'i'
{
int scores;
iss >> scores;
arrayScores[i][j] = scores;
}
}
inputFile.close();
}
Related
For a project I am currently working on, I have to read from a file and depending on the certain character in the file, output either a 1 or 0 to an array.
So here is an example of file input:
* * *
* * *
** ** **
*** *
And here is the function I have written to handle this:
void input (int cellGrid[][MAX]) //takes info from a .txt and puts it into an array
{
ifstream infile; //declare a file variable
int row;
int column;
int number;
infile.open("life.txt"); //open a file
while(infile>>row>>column) { //inserts bacteria places into array
cout << row << " " << column << endl;
cellGrid[row][column]=1; //makes it equal one if bacteria is present
}
infile.close(); //closes file
}
My thinking was that the function needs to see if there is a character that exists and if so, place a 1 in its respective position ([row][column]) in the array. However with this current code, nothing is input into my array.
Generally in C++ use std::vector wherever possible.
Array example:
You have to go through the file and record position of each *. Then set it to 1 for that position. Something like the following (we use getline and i as counter for rows, then we loop through the line using j as counter for columns):
#include <fstream>
#include <string>
using namespace std;
void input(int cellGrid[][100]) {
ifstream infile;
infile.open("life.txt");
int i = 0;
for (string line; getline(infile, line); ++i)
{
for (size_t j = 0; j < line.size(); ++j) {
if (line[j] == '*') {
cellGrid[i][j] = 1;
}
}
}
infile.close();
}
Vector example #1:
Here you can find a solution using std::vector. It will be always in a size rows x columns. One thing it requires is to pass default constructed vector and not constructed with vector(size_type count); c-tor. You can write your own version that doesn't have this problem:
#include <fstream>
#include <string>
#include <vector>
using namespace std;
void input(vector<vector<int>> &cellGrid) {
ifstream infile;
infile.open("life.txt");
int i = 0;
for (string line; getline(infile, line); ++i)
{
cellGrid.push_back(vector<int>(line.size()));
for (size_t j = 0; j < line.size(); ++j) {
if (line[j] == '*') {
cellGrid[i][j] = 1;
}
}
}
infile.close();
}
int main() {
vector<vector<int>> cellGrid;
vector<vector<int>> cellGrid2(100);
input(cellGrid);
//input(cellGrid2); - THIS WILL THROW AN EXCEPTION
return 0;
}
Vector example #2:
It would be even better for you function to return a newly created and populated vector:
#include <fstream>
#include <string>
#include <vector>
using namespace std;
vector<vector<int>> input() {
ifstream infile;
infile.open("life.txt");
vector<vector<int>> cell_grid;
int i = 0;
for (string line; getline(infile, line); ++i)
{
cell_grid.push_back(vector<int>(line.size()));
for (size_t j = 0; j < line.size(); ++j) {
if (line[j] == '*') {
cell_grid[i][j] = 1;
}
}
}
infile.close();
return cell_grid;
}
int main() {
auto vec = input();
return 0;
}
My thinking goes like this:
set row to 0
while can read a line from file
set column to 0
for each character on line
if character is '*'
set cellGrid(row,column) to 1
else
set cellGrid(row,column) to 0
increment column
increment row
You may want additional logic to trap row or column trying to go out of bounds or characters that aren't ' ' or '*'.
I have been working with a program that will read through multiple text files, record the number of words in them, and write to a file all of the words and the frequency of them. However, I have encounter a segmentation fault somewhere in my code. I have tried using tools such as Valgrind to help me debug it, however it only points to where I say int i = 0 in the main loop. I apologize for posting a large portion of my code but I have spent hours trying to find where the bug is and cannot seem to find it for the life of me. The issues began when I started passing a structure in pthread_exit().
#include <iostream>
#include <fstream>
#include <string>
#include <pthread.h>
#include <vector>
#include <algorithm>
#include <sstream>
#include <iterator>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <cstdio>
using namespace std;
// Create a structure that we can store information in
typedef struct info{
int words;
string dictionary[500000];
} info;
// Counts the number of words in the text file so we know how big to make our array
int countWord(char *arg){
char words[25000];
int count = 0;
ifstream check;
check.open(arg);
while(!check.eof()){
check>>words;
count++;
}
cout<<"Word Count: "<< count << '\n';
check.close();
return count;
}
// Checks to see if the word exists in our dictionary or not
int findWord(string array[], string target, int wordCount){
for(int i = 0; i < wordCount; ++i){
if(array[i] == target){
return 1;
}
}
return 0;
}
// Checks to see how many times a word is repeated
int checkWord(string array[], string target, int wordCount){
int number = 0;
for(int i = 0; i < wordCount; i++){
if(array[i] == target){
number++;
}
}
return number;
}
void *threads(void *arg){
info information;
char *fileName = (char *)arg;
ifstream myfile (fileName);
string line;
string fullText[15000];
string dictionary[500000];
int wordCount = countWord(fileName);
int i = 0;
int find;
int check;
int x = 0;
int checkingStart = 0;
// Opens and reads the file word by word removing any symbols that we dislike
if (myfile.is_open()){
while(myfile >> line){
transform(line.begin(), line.end(), line.begin(), ::tolower);
line.erase(remove(line.begin(), line.end(), ','), line.end());
fullText[i] = line;
i++;
}
}
else cout << "Unable to Open the File";
myfile.close();
// Goes through and adds all the words to our dictionary
for(i = 0; i < wordCount; ++i){
find = findWord(dictionary, fullText[i], wordCount);
if(find == 0){
dictionary[x] = {fullText[i]};
++x;
checkingStart = 1;
}
}
// Sets each section of dictionary equal to the one in the structure
for(i = 0; i < wordCount; ++i){
information.dictionary[i] = dictionary[i];
}
// Sets words equal to word count and then passes the structure information out of the thread
information.words = wordCount;
pthread_exit(&information);
return NULL;
}
int main(){
int i = 0;
int x = 0;
int y = 0;
int z = 0;
int a = 0;
int b = 0;
int add = 0;
int currentSize = 0;
int checkingStart = 0;
int wordCount;
int find;
string fullDictionary[500000];
string dict[500000];
ofstream writeFile;
info information;
char *fileName;
char *fileList[2];
pthread_t threadCount[2];
int frequency[500000];
int check;
fileList[0] = "text1";
fileList[1] = "text2";
// Creates a loop that creates and joins threads for each text file
for(a = 0; a < 1; ++a){
fileName = fileList[a];
pthread_create(&threadCount[a], NULL, threads, &fileName);
pthread_join(threadCount[a], (void **)&information);
wordCount = information.words;
// Sets each part of dict equal to the same slot on info.dict
for(b = 0; b < wordCount; ++b){
dict[b] = information.dictionary[b];
}
// Adds to a complete list of all the text files added together
for(y = 0, z = currentSize; z < wordCount; ++z, ++y){
fullDictionary[z] = dict[y];
}
currentSize = (currentSize + wordCount);
}
// Goes through and adds all the words to our dictionary
for(i = 0; i < wordCount; ++i){
find = findWord(dict, fullDictionary[i], currentSize);
if(find == 0){
dict[x] = {fullDictionary[i]};
cout << "Added the Word: " << fullDictionary[i] << "\n";
add = 1;
checkingStart = 1;
}
// Checks the number of times each word appears in the text file
if(checkingStart == 1){
check = checkWord(fullDictionary, dict[x], wordCount);
frequency[x] = {check};
}
// Checks to see if it needs to move to the next open dictionary spot
if(add == 1){
++x;
add = 0;
}
}
return 0;
}
These were the changes that were needed to get the program working.
1) One issue seems to be that the size of the variables in the function threads. Looks like every thread that is spawned has some default limit . You could read up on pthread_attr_setstacksize. but the simplest solution was to reduce the size of the strings in thread.So the size of the variables are why it's gives a segmentation fault as soon as the threads function is called.
As already mention in the comments above usage of vector/maps classes will help reduce the need for large local variables.
2) The return variable needs to be a non-local variable else the return value does not make it back successfully.
3) just noticed the main loop ( variable a ) is running only once . Also once the thread is launched(pthread_create) the loop is waiting for the join . This will result in serialization of the threads. The create can be done first and then the join can be in called in a separate loop after that.
Changes are given below ..
In function - threads
info *information;
//changed to pointer
// info information;
char *fileName = (char *)arg;
ifstream myfile (fileName);
string line;
string fullText[1500];
string dictionary[5000];
// reduced size
//string fullText[15000];
//string dictionary[500000];
.....
information = new info; // create an instance
........
// change to pointer
information->dictionary[i] = dictionary[i];
}
// Sets words equal to word count and then passes the structure information out of the thread
information->words = wordCount;
pthread_exit(information); // return pointer
in function - main
info *information; // change to pointer
....
for(a = 0; a < 2; ++a){ // loop to 2
.....
pthread_create(&threadCount[a], NULL, threads, (void *)fileName); // changed file name
// pthread_create(&threadCount[a], NULL, threads, &fileName);
wordCount = information->words; // changed for pointer
...
dict[b] = information->dictionary[b] // changed for pointer
After the edits you should be able to run to debug the rest of the functionality.
I am trying to write a c++ program to read a txt file containing data (122X300 matrix - tab delimited matrix) into my code and get it to display. The following is the code I wrote after referring extensively to google and many similar questions on this site. On running the code, I do not get any errors, however it does give me huge list of numbers which I cant seem to make any sense of. The following is the code: Any help would be great. I do not know where I am going wrong. Thanks.
DID some changes after considering the comment below by #ZekeMarsh, the problem now is that my text data is like:
Data Matrix Snapshot
The output I am getting is this:
Output of Code
The row counter does not move over to the next row,instead continues in the same row after incrementation....No idea why. The code modified is as follows:
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <conio.h>
using namespace std;
int main(){
int HEIGHT = 3;
int WIDTH = 2;
int array_req[HEIGHT][WIDTH];
string userinputprompt, filename;
userinputprompt = "Data Filename: ";
cout<<userinputprompt<<endl;
getline(cin,filename);
ifstream inputfile;
inputfile.open(filename.c_str());
for(int i=0; i<HEIGHT; i++)
{
for(int j=0; j<WIDTH; j++)
{
/*if(!(inputfile>>array_req[i][j]))
{
cerr<<"Error";
break;
}
else if(!inputfile) // its error.. , can use a cerr here...
{
cerr<<"Error";
break;
}
else*/
inputfile>>array_req[i][j];
cout<<i<<","<<j<<"-->"<<array_req[i][j]<<endl;
}
/* This is not needed, read above comment
else
{
inputfile >> array_req[i][j];
}*/
}
for(int p=0; p<HEIGHT; p++)
{
for(int q=0; q<WIDTH; q++)
{
cout<<array_req[p][q]<<" ";
}
cout<<"\n";
}
inputfile.close();
getchar();
return 0;
}
.
EDITED CODE - The output array is a null matrix. Please help. What is wrong in the code ..compiles correctly. Trying to read line by line using getline and stringstream based on a lot of examples I read here..still not working.
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <conio.h>
#include <sstream>
#include <stdlib.h>
const int HEIGHT = 3;
const int WIDTH = 4;
const int BUFFSIZE = 10000;
using namespace std;
int main(){
int array_req [HEIGHT][WIDTH];
char buff[BUFFSIZE];
string userinputprompt, filename;
userinputprompt = "COLORDATA FILENAME: ";
cout<<userinputprompt<<endl;
getline(cin,filename);
ifstream inputfile;
stringstream ss;
inputfile.open(filename.c_str());
for (int i=0; i<HEIGHT; i++)
{
inputfile.getline(buff,BUFFSIZE,'\n');
ss<<buff;
for(int j=0;j<WIDTH; j++)
{
ss.getline(buff,1000,'\n');
array_req[i][j]=atoi(buff);
}
ss<<"";
ss.clear();
}
for(int p=0; p<HEIGHT; p++)
{
for(int q=0; q<WIDTH; q++)
{
cout<<array_req[p][q]<<" ";
}
cout<<"\n";
}
inputfile.close();
getchar();
return 0;
}
First of all during the printing of your array, you are not delimiting your data with anything which will result in a line of numbers. You should add delimiter and line breaks.
Second and most importantly: you try printing the full value of the array while it has not been filled up yet. I believe you meant to put the printing outside of the loop that works with your variable i . Now you are printing garbage in the places where the array was not filled yet.
Edit: Here is only the reading part as I believe that is only what you are looking for:
for (int i = 0; i < HEIGHT; ++i)
{
std::string tmpString;
std::getline(inputfile, tmpString);
std::stringstream ss(tmpString);
for(int j=0;j < WIDTH; ++j)
{
ss >> array_req[i][j];
}
}
I need to traverse a file in a vertical manner. If suppose the file contents are:
adg
beh
cfi
It should print the file as:
abc
def
ghi
The length for each line will be same(i.e. all lines will be of length 3 for above example). I have written a code but it doesn't traverse the file as required.
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main()
{
fstream fs;
fs.open("asd.txt",ios::in);
string str;
char *ch = new char();
int lineLen = 0, k = 0;
if(getline(fs,str))
{
lineLen = str.length();
}
fs.seekg(0);
if(lineLen > 0)
{
for(int i = 0;i<lineLen;i++)
{
fs.seekg(i+k*lineLen);
while(fs.read(ch,1))
{
k++;
fs.seekg(i+k*lineLen);
cout<<*ch;
}
k = 0;
}
}
fs.close();
cin.ignore();
}
I am a bit new to file handling and couldn't find the mistake. Also, is there a better approach for this to be followed?
Pretty much your way with some little tweaks
//lines = no. of lines in file
fs.seekg(0, fs.beg);
fs.clear();
if(lineLen > 0)
{
for(int k = 0; k < lineLen; k++) {
for(int i = 0;i<lines;i++){
fs.seekg(k+i * (lineLen + 2), fs.beg); //use lines + 2
if(fs.read (ch,1));
cout << *ch;
}
cout << endl;
}
Untested pseudo-code that may give you some ideas. Basically, load the whole file into a 2d vector of characters for easy access. It will use more memory than reading directly from the file but this won't matter unless the file is very big.
vector<vector<char>> filemap;
string line;
while (getline(filestream, line))
{
filemap.push_back(vector<char>(line.begin(), line.end()));
}
for (int x = 0; x < XSIZE; x++)
{
for (int y = 0; y < YSIZE; y++)
{
filestream << filemap[y][x]; // note x/y are opposite way round in 2d vectors
}
filestream << '\n';
}
You might find this task much simpler if you were to use mmap(2). There may be a C++ equivalent or wrapper, but I'm afraid I'm not much of an expert on that front. Hopefully someone will come along with a better answer if that's the case.
Here's a quick C (not ++) example. I'll see if I can google around and C++ify it some more:
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
int main(void)
{
int fd = open("input", O_RDONLY);
struct stat s;
fstat(fd, &s);
// map the file as one big string
char *c = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
// calculate sizes
int columns = strchr(c, '\n') - c; // first newline delimits a row
int stride = columns + 1; // count the newline!
int rows = s.st_size / stride; // all rows are the same length
for (int x = 0; x < columns; x++)
{
for (int y = 0; y < rows; y++)
{
putchar(c[y*stride + x]);
}
putchar('\n');
}
munmap(c, s.st_size);
close(fd);
return 0;
}
Edit: A quick search around didn't turn up a much better way to handle this in C++ as far as I could tell. I mean, I can add a typecast on the mmap line and change the putchar calls to std::cout, but that doesn't really seem like it makes any difference.
Instead of trying to seek() repeatedly in the source file it is much easier and faster to simply read in the whole source file then generate output from the in-memory contents.
This sounds an awful like like a class assignment, so I won't simply write the answer for you. However this should point you in the right way -- Some PseodoCode is included
To avoid pain, it should presumably be safe to assume some upper bound on line length and max lines, i.e.,
const int MaxLines = 100;
const int MaxLength = 80;
int lineno, linelength;
// array of char pointers for each line
char *lines[] = (*lines[])malloc(Maxlines * sizeof(char*));
// ReadLoop
lineno = 0;
while (not eof)
{
getline(buffer);
if (++lineno++ == 1)
{
linelength = strlen(buffer);
}
else
{
if (linelength != strlen(buffer))
{
cout "Line # " << lineno << " does not match the expected length";
exit();
}
}
lines[lineno] = malloc(strlen(buffer)+1));
strcpy(lines[lineno], buffer);
}
int cc, linecnt = lineno;
// now all data in memory, output "vertical data"
for (cc = 0; cc < linelength; ++cc)
{
for (lineno=0; lineno<<linelength; ++lineno)
{
cout << lines[xx][yy]; // xx && yy left you to figure out
}
cout "\n";
}
Provided that your file is not enormous, there's no reason not to just slurp the whole thing into memory. There may be a more idiomatic way to do this in C++, but the following works:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
int main(int argc, char *argv[])
{
std::fstream infile("foo.txt");
std::vector<std::string> lines;
std::string line;
while(std::getline(infile,line)) {
lines.push_back(line);
}
int m=lines.size();
int n=lines[0].length();
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
std::cout << lines[j].at(i);
}
std::cout << std::endl;
}
return 0;
}
Problems arise when all the lines in the file are not the same length, of course.
And now, a version that “doesn't use any extra memory” (of course, it does, but not much):
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>
int main(int argc, char *argv[])
{
std::fstream infile("foo.txt");
std::vector<std::string> lines;
std::string line;
std::getline(infile, line);
int n = line.length();
int m = 1+std::count(std::istreambuf_iterator<char>(infile),
std::istreambuf_iterator<char>(), '\n');
infile.clear();
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
infile.seekg(j*m+i);
std::cout << char(infile.peek());
}
std::cout << std::endl;
}
return 0;
}
I am a high school student programming as a hobby. I make free stuff and I am working on a game using opengl. I need to save and load data but when met with difficulty I made the following to test my methods.
The save file 'shiptest' is correct but when I open the second file 'shipout' which is created with the save data from 'shiptest' only the first line is there. At first I thought that my array wasn't loading any new data and the clear function wasn't getting rid of the first elements. I corrected this assumption by overwriting those lines after saving the data and observing that the saved lines were loaded after all. My new assumption is that the getline func is only getting the first line each time it's called; but i do not know how to fix this.
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
unsigned short int shipPart;
float editShip[256][3];//part ID, x relative, y relative, r,g,b
float activeShip[256][3];
void CLEAR(bool edit)
{
for (int n = 0; n < 256; n++)
{
if (edit)
editShip[n][0] = -1;
else
activeShip[n][0] = -1;
}
}
void saveEdit(std::string name)
{
std::ofstream out;
out.open ("ship" + name + ".txt", std::ofstream::out);
for (int n = 0; n < 256; n++)
{
for (int i = 0; i < 3; i++)
{
if (editShip[n][0] == -1)
break;
out << editShip[n][i] << " ";
}
out << "\n";
}
out.close();
}
void load(std::string name, bool edit)
{
CLEAR(edit);
std::ifstream in;
in.open ("ship" + name + ".txt", std::ifstream::in);
std::string line, buf;
std::stringstream ss;
int i;
for (int n = 0; n < 3; n++)
{
getline(in, line);
ss << line;
i=0;
while (ss >> buf)
{
if (edit)
editShip[n][i] = atof(buf.c_str());
else
activeShip[n][i] = atof(buf.c_str());
i++;
}
}
in.close();
}
int main()
{
for (int n = 0; n < 256; n++)
{
editShip[n][0] = -1;
activeShip[n][0] = -1;
}
editShip[0][0] = 5;
editShip[0][1] = .11;
editShip[0][2] = .22;
editShip[1][0] = 4;
editShip[1][1] = .33;
editShip[1][2] = .44;
editShip[2][0] = 3;
editShip[2][1] = .55;
editShip[2][2] = .66;
saveEdit("test");
editShip[0][0] = 5000;
editShip[0][1] = 8978;
editShip[0][2] = 8888;
load("test",1);
saveEdit("out");
std::cout << "Hello world!" << std::endl;
return 0;
}
In load(), you keep appending more lines to your stringstream ss but its eof flag is probably remaining set from the previous time through the loop, so even though there's more to read from it, eof is already set so it won't continue providing data via operator>>(). If you simply call ss.clear() at the top of the for() loop, you'll start with an empty stringstream on each loop, and I think you'll get what you want.
In your load() function:
for (int n = 0; n < 3; n++)
{
ss.clear(); //< Clear ss here before you use it!
getline(in, line);
ss << line;
i=0;
while (ss >> buf)
{
if (edit)
editShip[n][i] = atof(buf.c_str());
else
activeShip[n][i] = atof(buf.c_str());
i++;
}
}
Getline() was working just fine. Just clear the stringstream before you use it and you're good to go. Ran this code on my computer and it works as desired.
EDIT: Ack! Just saw that phonetagger said the same thing while I was making my answer. He deserves the +1's not me.