I'm relatively new to C++ and programming in general, so I'm guessing that my mistake is a pretty simple one. Anyways, I've been working on scanning DNA sequences in from .txt files and I am trying to program it such that the user can specify the names of the data files from the command line. I included the entire function for reference, however the particular problem I'm getting is that I've been unable to get the file to actually open, the program always returns the "Unable to open file" message. The part with which I am having problems (I think) is the last for loop, but I included the entire function for reference.
int dataimport (int argc, char* argv[]){
vector<string> mutationfiles (argc -1); //mutationfiles: holds output file names
vector<string> filenames (argc - 1); //filenames: holds input file names
if (argc > 1){
for ( int i = 1; i < argc; ++i){
string inputstring = argv[i]; //filename input by user
filenames[i-1] = inputstring; //store input filename in vector
stringstream out;
out << inputstring << "_mutdata.txt"; //append _mutdata.txt to input file names
mutationfiles[i-1] = (out.str()); //store as output file name
inputstring.clear(); //clear temp string
}
}
else{
cout << "Error: Enter file names to be scanned" << endl;
system("PAUSE");
return EXIT_FAILURE;
}
for(int repeat = 0; repeat < argc; ++repeat){
ifstream myfile; //open input file
myfile.open (filenames[repeat].c_str());
ofstream myfile2; //open output file
myfile2.open (mutationfiles[repeat].c_str());
string all_lines;
if (myfile.is_open()){
while ( myfile.good() ){ //scan data
getline (myfile,all_lines,'\0');
}
myfile.close(); //close infile
}
else{ //error message
cout << "Unable to open file\n";
system("PAUSE");
return EXIT_FAILURE;
}
}
}
Please let me know if there is any additional information you need or anything I should research so that I can better help myself!
for(int repeat = 0; repeat < argc; ++repeat)
should be
for(int repeat = 0; repeat < argc - 1; ++repeat)
Aside from that I can't see anything that would cause the error you are getting.
If you fix that and still get errors, I would try printing the names to make sure the contents of your two vectors is correct.
for(int repeat = 0; repeat < argc - 1; ++repeat)
{
cout << filenames[repeat] << endl;
cout << mutationfiles[repeat] << endl;
}
Change for ( int i = 1; i < argc; ++i) to for ( int i = 0; i < argc; i++)
and
change filenames[i-1] = inputstring; to filenames[i] = inputstring;
and
change mutationfiles[i-1] to mutationfiles[i].
Related
im a Student and new to this site. I want to split my txt file with my highscore data back to my Highscore List.
The txt file stores my Highscore like name:score
My parsing is not working and i dont know why?
I just want to split it to name and score again and then put it in my HighscoreList.
If you have any question about the code just ask :)
#include "highscore.h"
highscore::highscore(){
}
struct highscore::Player{
string spielerName;
int score;
};
void highscore::writeHighscore(string name, int score ,int playerNumberx){
Player HighscoreListe[100];
for(int i=0;i<=99;i++){
HighscoreListe[i].score = {0};
}
for(int i=0;i<=99;i++){
HighscoreListe[i].spielerName = "leer";
}
HighscoreListe[playerNumberx].spielerName = name;
HighscoreListe[playerNumberx].score = score;
int i, j,temp;
string temp1;
ifstream myfile("scores.txt");
string line;
//heres the point where i need help!!
if (myfile.is_open()){
int z=0;
while(getline(myfile, line)){
string name1;
string score1;
int d = 20;
while(line[z] != ':'){
name1 += line[z];
z++;
}
z = z+2;
while(line[z] != '\0'){
score1 += line[z];
z++;
}
HighscoreListe[d].spielerName = name;
HighscoreListe[d].score = score;
d++;
}
myfile.close();
}else cout << "Unable to open file" << endl;
for(i = 0; i<100; i++) {
for(j = i+1; j<100; j++)
{
if(HighscoreListe[j].score < HighscoreListe[i].score) {
temp = HighscoreListe[i].score;
temp1 = HighscoreListe[i].spielerName;
HighscoreListe[i].score = HighscoreListe[j].score;
HighscoreListe[i].spielerName = HighscoreListe[j].spielerName;
HighscoreListe[j].score = temp;
HighscoreListe[j].spielerName = temp1;
}
}
}
ofstream myfilex("scores.txt");
if (myfilex.is_open()){
for(int i = 99;i>89;i--){
myfilex << HighscoreListe[i].spielerName << ":" << HighscoreListe[i].score<<endl;
}
myfilex.close();
}
else cout << "Unable to open file" << endl;
}
void highscore::readHighscore(){
string line;
ifstream myfile("scores.txt");
if (myfile.is_open()){
while(getline(myfile, line)){
cout << line << endl;
}
}
else cout << "Unable to open file" << endl;
}
Make a >> overload for highscore::Player.
In the >> overload
Use std::getline to read a line from the input stream.
Create a std::istringstream out of the line.
Use std::getline to read up to the : from the istringstream into a local string name;.
Use another std::getline to read the rest of the line into a string.
Convert the string into an int with std::stoi and store into a local int score;. Make sure you provide a pos argument.
Ensure that the entire string was converted by comparting the pos argument with the string's length.
If nothing went wrong, store name and score into the highscore::Player passed by the caller. Otherwise, set the failbit on the input stream with setstate
return the input stream.
Now the reading code should be something simple like
int scorecount = 0;
while (myfile >> HighscoreListe[scorecount])
{
scorecount++;
}
I'm fairly new to C++ and I'm working on point of sale program from a class in which I will need to read in the menu option along with the price. I'm attempting to read in a .txt file into a 2D Char* but I keep on getting the error message
Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
from line containing
inFile >> array[i][j];
I'm assuming this error is arising due to the way that I'm trying to assign values to each element in the array. I'm sure how to accomplish it.
// Main function
int main (){
char *array[4][3];
string fileName;
vector<string>order;
fileName = fileLoc();
getMenu(fileName, array);
return 0;
}
string fileLoc(){
string file;
cout << "Enter file name or location: ";
cin >> file;
return file;
}
void getMenu(string fileName, char *array[][3]){
ifstream inFile(fileName.c_str());
if (!inFile){
cout << "File failed to open\n";
}
for (int i = 0; i < 4; ++i){
for (int j = 0; j < 3; ++j){
inFile >> array[i][j];
cout << array[i][j] << endl;
}
}
inFile.close();
}
The .txt file I am reading from looks like such
B Burger 3
S Soda 1
F Fries 2
C Chips 1.5
just want to ask if anyone knows why I cant convert an entire picture into decimal.
Problem: after about 180 couts it turns 0 for the rest of the pixels.
Code:
#include <fstream>
#include <iostream>
int main() {
char unsigned charTemp = 0;
int unsigned intTemp = 0;
std::fstream file;
file.open("PIC.pbm", std::ios::in);
//Ignore header
for (int i = 0; i < 13; i++) {
file.ignore();
}
//read and print
//img res is 40x40 = 1600
for (int i = 0; i < 1600; i++) {
file >> charTemp;
intTemp = charTemp;
std::cout << intTemp << " ";
charTemp = 0;
intTemp = 0;
}
std::cout << "\n\n\n";
system("pause");
return 0;
}
Pic: any 40x40 pbm
A better method with picture and image files is to read them as binary files:
std::ifstream file("PIC.pbm", ios::binary);
std::vector<unsigned char> bitmap(1600);
// Skip over the header
file.seekg(13, ios::beg); // Skip over 13 bytes.
// Read in the data at once
file.read((char *) &bitmap[0], 1600);
// Now process the bitmap from memory
for (int i = 0; i < 1600; ++i)
{
cout << static_cast<unsigned int>(bitmap[i]) << " ";
if ((i % 40) == 39)
{
cout << "\n";
}
}
cout << "\n";
The idea here is to read in the bitmap in one transaction into memory. Streams like to flow (don't interrupt the flow). Memory is faster to access than files, so the bitmap values are processed from memory.
The cast is used so that the formatted insertion doesn't treat the byte as a character, but a number.
First, open your PIC.pbm file in another hex editor because it's quite possible that those bytes really are zeroes. If not, then you've got problems reading the file.
The fstream constructor does not default to reading in binary mode, so it reads files as "text" - and I've learned the hard way that you can't trust the standard-library with knowing anything about text anymore (what with mishandling Unicode, line-endings, etc - I feel it's best to always use binary and a dedicated Unicode library).
You should check the fstream::good() function after each read operation to see if it failed, and if so, then check iostate:
using namespace std;
// ...
fstream file;
file.open( "PIC.pbm", ios::in | ios::binary );
file.ignore( 13 );
for (int i = 0; i < 1600; i++) {
file >> charTemp;
if( !file.good() ) {
cout << endl;
cout << "Error reading file: iostate == " << file.iostate << endl;
break;
}
else {
intTemp = charTemp;
std::cout << intTemp << " ";
charTemp = 0;
intTemp = 0;
}
}
I cannot find the problem in my code. readFile function works well, but writeFile function does not make any changes in the file:
#include <iostream>
#include <fstream>
using namespace std;
const int BUF_SIZE = 1024;
void readFile(fstream &file, char buffer[BUF_SIZE]);
void writeFile(fstream &file);
void readFile(fstream &file, char buffer[BUF_SIZE])
{
int position;
cout << "Please enter a position to read from the file some info" << endl;
cin >> position;
file.seekg(position, ios::beg);
file.read((char*) buffer, BUF_SIZE); // <<<<<
for(int i = 0; i < file.gcount(); i++){
cout << buffer[i];
}
}
void writeFile(fstream &file)
{
char temp[100] = "HHHH";
//cout << "Please enter some info to add to the file" << endl;
file.write((char*) &temp, 100);
for(int i = 0; i < file.gcount(); i++){
cout << temp[i];
}
}
int main(int argc, char const *argv[])
{
char buffer[BUF_SIZE];
if (argc != 2){
cout << "Program usage: prog_name file_name";
return 1;
}
fstream file(argv[1], ios::in | ios::out | ios::binary | ios::app);
if (!file){
cout << "File can not open or doesn't exist";
return 1;
}
//Try to read & write some info from/to file in particular position
readFile(file, buffer);
writeFile(file);
file.close();
return 0;
}
When I create a new ostream it works well, but I want to understand why fstream in/out mode works in my code only for reading.
I see several problems:
The reason behind the writing problem is probably because you reach the end of the file (is the file smaller than BUF_SIZE bytes?). This sets the EOF bit, which makes any write operations to fail. You have to clear that bit before (use the std::fstream::clear method):
void readFile(fstream &file, char buffer[BUF_SIZE])
{
int position;
cout << "Please enter a position to read from the file some info" << endl;
cin >> position;
file.seekg(position, ios::beg);
file.read(buffer, BUF_SIZE);
for(int i = 0; i < file.gcount(); i++){
cout << buffer[i];
}
file.clear(); // clears EOF
}
The line file.write((char*) &temp, 100); is wrong since you are actually passing a point to the temp variable, which is also a pointer, but it is camouflaged by the cast. These ones are OK: file.write(temp, 100); or file.write(&temp[0], 100);
When printing the written characters, you are using std::fstream::gcount, which literally means get count (amount of characters read in the last get operation). You are writing (put) not reading (get). Indeed, you are actually indicating how many bytes you are willing to write, so use it:
file.write(temp, 100);
for(int i = 0; i < 100; i++){
cout << temp[i];
}
Finally, you are always writing 100 characters, probably including some garbage from the buffer. As I see that you want to let the user choose what to write (the commented line), you can instead:
const size_t size = strlen(temp);
file.write(temp, size);
for(size_t i = 0; i < size; i++){
cout << temp[i];
}
In addition, some suggestions:
Use a std::string to read the user input, in this way you avoid a possible buffer overflow (if the user enters more than 100 characters).
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // read the link bel
string temp;
getline(cin, temp); // need #include <string>
file.write(temp.c_str(), temp.size());
You will probably want to read this answer to learn more about the first line (basically it avoids the getline to be skipped after using cin >> position).
Avoid the for loop to print the user input. For both the buffer and the std::string options you can just cout << temp << endl;.
The problem I am facing is the following:
if we define something like
ofstream myFile;
myFile.open("Directory//debug.txt");
for (int i = 0; i < 10; i++)
{
myFile << i << endl;
myFile.close();
}
the output in the debug file will be 9.
I want to make it so that it outputs all the numbers from 0 to 9. Aside from closing the file after the for statement is it possible to define an ofstream that would do that?
No. You have two options:
Close the file outside the loop:
myFile.open("Directory//debug.txt");
for (int i = 0; i < 10; i++)
{
myFile << i << endl;
}
myFile.close();
or open the file in append mode and close inside the loop:
for (int i = 0; i < 10; i++)
{
myFile.open("Directory//debug.txt", ios_base::app);
myFile << i << endl;
myFile.close();
}
myFile.close();
should be put after the for-loop. Also introduce some error checking to see if the open was indeed a success.
I am calling a function foo repeatedly in a function goo I create the
file in foo and I want to output a new value each time foo is called
in goo.
In order to achieve your objective you could use a static variable inside foo
void foo()
{
static int count=0;
ofstream myfile;
myfile.open("Directory//debug.txt",std::fstream::app)
if (myfile.is_open()) // Checking is file is successfully opened.
{
count++;
myfile<<count<<"\n";
}
myfile.close; // Close the file
}