I know this is a widely asked question and there are answers even on this website, unfortunately, none of the answers helped me with my problem which is the following: i open a file and loop over its characters to see how many rows i will need to initialize my dynamic array, then i have another loop to reread the file found out how many columns i have (i know this inst so efficient), then i will input these chars to my 2d dynamic array. We can see here i reread the file several times. I have tried commands like seekg(),rewind(), closing the file and re-opening it none have worked, here is my code : (we have been giving a hint that each row ends with value 0, that should not be counted.)Any help is much appreciated.
//------------- include section -------------
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <new>
#include <fstream>
#include <cstring>
#include <cctype>
//------------- using section -------------
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using std::ifstream;
using std::ofstream;
using std::setw;
//------------- const section -------------
const int END_OF_LINE=-1;
const int LEN=100;
//------------- prototypes section -------------
void open_files(ifstream& if1, ifstream& if2);
void convert_to_matrix (ifstream &inp,int*matrix[],int num_of_rows);
void add_2_matrixes (int*matrix[],int* matrix2[],int num_of_rows,int
num_of_rows2);
int get_length(ifstream & inp,int &length);
int get_rows(ifstream &inp, int &counter);
//------------- main -------------
int main(int argc, char *argv[])
{
ifstream inp;
ifstream inp2;
open_files(inp,inp2);
int num_of_rows=0,counter=0;
num_of_rows=get_rows(inp,counter);
int* matrix[num_of_rows];
//fill rows and cols dynamically
convert_to_matrix(inp,matrix,num_of_rows);
int num_of_rows2=0;
counter=0;
num_of_rows2=get_rows(inp2,counter);
//another matrix
int* matrix1[num_of_rows2];
//fill rows and cols dynamically
convert_to_matrix(inp2,matrix1,num_of_rows2);
add_2_matrixes(matrix,matrix1,num_of_rows,num_of_rows2);
return EXIT_SUCCESS;
}
//-----------------------------
void open_files(ifstream& inp, ifstream& inp2){
char* st_file;
char* nd_file;
st_file=new(std::nothrow) char [LEN];
nd_file=new(std::nothrow) char [LEN];
//gets the first file name
cin >> setw(LEN) >> st_file;
inp.open(st_file);
//gets the second file name
cin >> setw(LEN) >> nd_file;
inp2.open(nd_file);
// if the opening command failed
if ((!(inp.is_open())) || (!(inp2.is_open()))) {
exit(EXIT_FAILURE);
}
}
//------------------------------------------------
int get_rows(ifstream &inp, int &counter){
int columns=0;
while(!inp.eof())
{
counter++;
inp>>columns;
while (columns!=0)
{
inp>>columns;
}
}
//!!!! (problem)
inp.seekg(0,std::ios::beg);
return counter;
}
//---------------------------------------------
void convert_to_matrix (ifstream &inp,int* matrix[],int num_of_rows){
//numbers is how many cols
int length=0;
//value of each col
int number;
for (int row=0;row<num_of_rows;row++){
//open an array
get_length(inp,length);
matrix[row]=new(std::nothrow) int [length+1];
//if null we failed
if (matrix[row]==NULL)
{
cerr<<"Cannot allocate memory /n";
exit(EXIT_FAILURE);
}
//else start filling in values
for (number=0;matrix[row][number]!=0;number++)
{
inp>>matrix[row][number];
}
//at end of filling values last number is -1
//to help us know when to stop
matrix[row][number]=END_OF_LINE;
}
}
//------------------------------------------------------
int get_length(ifstream &inp,int &length){
int columns=0;
inp>>columns;
length++;
while(columns!=0)
{
inp>>columns;
length++;
}
//!!!!!(problem)
inp.seekg(0,std::ios::beg);
return length;
}
Related
So I am not sure how to get the output to like a .txt file, the code keeps giving me a .txt file but it is always empty. I know I am supposed to include a line where it outputs the information but I am uncertain of what to put in the line since its a void function and it doesn't return anything, would changing it to a different type of function solve the problem?
Code:
#include <iostream>
#include <string>
#include <fstream>
#include "ArgumentManager.h"
using namespace std;
void permute(string a, int l, int r)
{
if (l == r)
cout<<a<<endl;
else
{
for (int i = l; i <= r; i++)
{
swap(a[l], a[i]);
permute(a, l+1, r);
swap(a[l], a[i]);
}
}
}
int main(int argc, char* argv[])
{
ArgumentManager am(argc, argv);
ifstream input;
ofstream output;
string infileName = am.get("input");
string outfileName = am.get("output");
input.open(infileName);
output.open(outfileName);
string str;
int n = str.size();
permute(str, 0, n-1);
return 0;
}
I havent worked with ArgumentManager before in C++.
But can you use something like:
// basic file operations
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ofstream myfile;
myfile.open ("example.txt");
myfile << "Writing this to a file.\n";
myfile.close();
return 0;
}
I think instead of passing the output to cout, you should pass it to myfile object.
I am still a newbie in programming. I am writing a program of 2D Snell's Law. I know the problem may due to wrong localisations in Xcode, but I am writing in C++ only and g++ even gives me segmentation fault error after compiling successfully.
Here are my code for main function:
#include <string>
#include "Snell.hpp"
int main(int argc, const char * argv[]){//thread 1 exc_bad_access (code=2 address=0x7fff5f238304)
string filename;
double time;
Snell S[3600];
for (int i=1; i<=1; i++) {
while (S[i].angle_tr>0) {
filename="VPVSMOD"+to_string(i)+".txt";
S[i].Open(filename);
time=S[i].Locate(i);
cout<<"The "<<i<<"th event takes "<<time<<" seconds to reach the destination"<<endl;
S[i].angle_tr-=0.01;
}
}
return 0;
}
Here is the code for Snell.hpp
#ifndef Snell_hpp
#define Snell_hpp
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
class Snell{
private:
double GetV(double lat,double dep);
int ny,nz,time;
double la[30],h[20],v[10][30];
double lat,alt,step;
public:
Snell();
void Open(string filename);
double Locate(int i);
double angle_tr;
};
#endif /* Snell_hpp */
and Snell.cpp:
#include "Snell.hpp"
Snell::Snell(){
ny=1,nz=3,time=0;
lat=0,alt=0,step=1;
angle_tr=M_PI/2;
}
void Snell::Open(string filename){
ifstream fin(filename);
stringstream ss;
string str,tok;
for (int i=0; i<nz; i++) {
(getline(fin, str));
ss.str(str);
for (int j=0; j<ny; j++) {
getline(ss, tok, ',');
v[i][j]=stod(tok);
cout<<v[i][j]<<",i="<<i<<",j="<<j<<endl;
}
ss.clear();
}
fin.close();
angle_tr=v[1][0]/v[0][0];
}
double Snell::GetV(double lat, double dep){
int index_la = 0,index_dep = 0;
index_dep=round(dep);
return (v[index_dep][index_la]+v[index_dep+1][index_la])/2;
}
double Snell::Locate(int i){
string filename;
double count_t=0;
double latt=lat,altt=alt,step_altt_all=0,angle=0,angle_p=0;
double vsy,vsz;
double vs,vs_n;
ofstream fout;
angle=M_PI/2-atan(angle_tr);
vs=GetV(lat, alt);
filename="Test"+to_string(i)+"_"+to_string(time)+".txt";
fout.open(filename,ios::out);
fout<<lat<<","<<alt<<endl;
while (altt!=2) {
//cout<<"Compute Velocity in each dimension"<<endl;
angle_p=angle;
vsy=vs*cos(angle);
vsz=vs*sin(angle);
//cout<<"Check Velocity"<<endl;
if (vsy==0||vsz==0) {
break;
}
//cout<<"Compute reflection point"<<endl;
step_altt_all=step/vsz;
count_t=count_t+step/vsz;//time plus one
latt=latt+vsy*(step_altt_all);
step_altt_all=0;
altt=altt+step;
//cout<<"Compute New Velocity"<<endl;
vs_n=GetV(latt,altt);
if ((vs_n*cos(angle)/vs)>1) {
break;
}
else{
angle=M_PI/2-asin(vs_n*cos(angle)/vs);
vs=vs_n;
if (angle!=angle_p)
fout<</*"position:"<<*/latt<<","<<altt<<endl;
}
}
fout.close();
filename="Result"+to_string(i)+"_"+to_string(time)+".txt";
fout.open(filename);
fout<<0<<" "<<latt<<" "<<altt<<" "<<step<<endl;
fout.close();
return count_t;
}
My immediate guess is: You must have blown your stack. Please see why is stack memory size so limited?
....And yes, On my platform, my guess was correct...
Reproducing your program, but modifying your main.cpp ...
int main(int argc, const char * argv[]){//thread 1 exc_bad_access (code=2 address=0x7fff5f238304)
string filename;
double time;
//Snell S[3600];
std::cout << sizeof(Snell) << " bytes" << std::endl;
return 0;
}
It gives an output of
2848 bytes
....And You are trying to allocate 3600 of them... ~10MB!!
The solution to that is to allocate it on the heap using a std::unique_ptr or better still, your good friend, std::vector.
Modify your main to this
#include <string>
#include <memory>
//or #include <vector>
#include "Snell.hpp"
int main(int argc, const char * argv[]){//thread 1 exc_bad_access (code=2 address=0x7fff5f238304)
string filename;
double time;
std::unique_ptr<S[]> p(new Snell[3600]);
//or std::vector<Snell> S(3600);
for (int i=1; i<=1; i++) {
while (S[i].angle_tr>0) {
filename="VPVSMOD"+to_string(i)+".txt";
S[i].Open(filename);
time=S[i].Locate(i);
cout<<"The "<<i<<"th event takes "<<time<<" seconds to reach the destination"<<endl;
S[i].angle_tr-=0.01;
}
}
return 0;
}
I have an input file that looks like this
1 0 3
2 11 5
3 15 1
4 16 11
and a structure that looks like this
struct numb {
int numb1;
int numb2;
int numb3;
}
and I need to create an array of the struct so that each element of the array holds all three numbers. So
numbArray[0].numb1 == 1
numbArray[0].numb2 == 0
numbArray[0].numb3 == 3
numbArray[1].numb1 == 2
numbArray[1].numb2 == 11
and so on. I've gotten the hang of opening and closing files, finding how many lines there are in a file, and reading a single line from a file, but I do not know how to store individual elements from a line.
My program looks like this so far:
#include <iostream>
#include <fstream>
#include <string>
int main(int argc, char* argv[])
{
ifstream inFile(argv[1]);
int fileLength = 0;
std::string line;
while(std::getline(inFile, line))
{
++fileLength;
}
struct numb {
int numb1;
int numb2;
int numb3;
}
if(inFile.is_open())
{
for(unsigned i = 0; i <= fileLength; i++)
{
//What to do here?
}
}
}
Use getline when you don't have regular structure to the input and need to handle variation between lines. When your input file has regular structure (in this case, there are always three values per line), then simply use the stream extraction operators directly:
#include <iostream>
#include <vector>
struct group
{
int n1;
int n2;
int n3;
};
int main()
{
std::vector<group> groups;
while (std::cin)
{
group line;
line.n1 << std::cin;
line.n2 << std::cin;
line.n3 << std::cin;
groups.push_back(group);
}
}
Express your ideas directly in code as much as possible.
Note I've written the code assuming that the file is in the proper form. If there are too many or too few values per line, then the above code will be confused. However, it is best to code the simplest thing that could possibly work and worry about complexity when you need it. In your example you stated that the input file was well-formed, so there's no need to overcomplicate things.
I recommend using a std::stringstream for this:
#include <iostream>
#include <sstream>
#include <string>
#include <stdio.h>
#include <vector>
struct numb {
int numb1;
int numb2;
int numb3;
};
void populate(std::vector<numb>& my_numbs, std::string line) {
std::stringstream ss(line);
numb my_numb;
ss >> my_numb.numb1 >> my_numb.numb2 >> my_numb.numb3;
my_numbs.push_back(my_numb);
}
void output(const numb my_numbs) {
printf("%d %d %d\n", my_numbs.numb1, my_numbs.numb2, my_numbs.numb3);
}
int main(int argc, char* argv[]) {
ifstream inFile(argv[1]);
std::string line;
std::vector<numb> my_vect;
while(std::getline(inFile, line)) {
populate(my_vect, line);
}
for(size_t i = 0; i < my_vect.size(); ++i) {
std::cout << "my_vect[" << i << "]:";
output(my_vect[i]);
}
return 0;
}
std::stringstreams allow you to parse out data types from std::strings, you you just need to parse out 3 ints, which you can use with your struct. You then push the struct into your vector.
Here's the working ideone taking input from stdin.
You should probably be able to do something like this:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
ifstream inFile(argv[1]);
int fileLength = 0;
std::string line;
struct numb {
int numb1;
int numb2;
int numb3;
};
vector<vector<int>> sets;
int n1, n2, n3;
while (std::cin >> n1)
{
cin >> n2;
cin >> n3;
vector<int> vec;
vec.push_back(n1);
vec.push_back(n2);
vec.push_back(n3);
sets.push_back(vec);
}
numb * numbSet = new numb[sets.size()];
//Since the vectors data is continuous in memory just as the array of structs are
//you can just copy the data directly
for (int i = 0; i < sets.size(); i++)
{
std::memcpy(&numbSet[i], &sets[i][0], sizeof(numb));
}
}
make a function which receive the file name but it not working properly because it receives "Doctor.txtG" but I am giving "Doctor.txt" how can i resolve it?My code is Given below......
#include <iostream>
#include <conio.h>
#include <fstream>
using namespace std;
int number_of_lines = 0;
int numberoflines(string A);
int main()
{
cout<<numberoflines("Doctor.txt");
getch();
return 0;
}
int numberoflines(string A)
{
int Len;
char Chr[Len];
Len=A.length();
A.copy(Chr, Len);
//cout<<Len;
cout<<Chr;
string line;
ifstream myfile(Chr);
if(myfile.is_open())
{
while(!myfile.eof())
{
getline(myfile,line);
number_of_lines++;
}
myfile.close();
}
return number_of_lines;
}
It needs to copy a null-terminated byte into Chr.
Use
strcpy(Chr, A.c_str());
instead of A.copy(Chr, Len);
And you should properly init Chr like
char Chr[1024]
or
char* Chr = new char[Len + 1].
Your problem is happening because you are trying to create a char array with the size Len. But you have not initialized Len before using it. This is why it is resulting in undefined behavior and creating this problem. Always try to initialize variables when you declare them. Otherwise, this problem will happen quite often.
However, You don't need to create another char array. Just use std::string::c_str(); in your parameter for the constructor of the ifstream. I am giving a sample code below. This should solve your problem.
#include <iostream>
#include <conio.h>
#include <fstream>
using namespace std;
int number_of_lines = 0;
int numberoflines(string A);
int main()
{
cout<<numberoflines("Doctor.txt");
getch();
return 0;
}
int numberoflines(string A)
{
string line;
ifstream myfile(A.c_str());
if(myfile.is_open())
{
while(!myfile.eof())
{
getline(myfile,line);
number_of_lines++;
}
myfile.close();
}
return number_of_lines;
}
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <fstream>
using namespace std;
int main()
{
srand(time(0));
const int array_size=10,n=10;
int i,j,k;
fstream io("io.dat", ios_base::binary);
float a[array_size];
for (i=0;i<n;i++) {
cout<<"Inputting "<<i+1<<" array:\n";
for (j=0;j<array_size;j++) {
a[j]=(float)rand()/(RAND_MAX+1)*200-100;
cout<<i+1<<"["<<j<<"]="<<a[j]<<endl;
}
io.write((char *)&a,sizeof(a));
}
io.close();
io.open("io.dat", ios_base::binary);
j=1;
while (!io.eof()) {
cout<<"Reading "<<j<<" array:"<<endl;
io.read((char *)&a,sizeof(a));
for (i=0,k=0;i<array_size;i++) {
cout<<j<<"["<<i<<"]="<<a[i]<<endl;
if (a[i]<0) k++;
}
cout<<"Number of negative elements in "<<j++<<" array="<<k<<endl;
}
return 0;
}
I am stuck in reading arrays from binary file. The problem is that condition of breaking reading cycle doesn't even works. Program reads the same array again and again.
This sort of a problem is caused because you are using !in.eof(). One of the easiest way to solve this is to read inside the while loop like in this code
io.open("io.dat", ios_base::binary);
j=1;
while ( io.read( (char *) &a, sizeof(a) ) ) // changed the !in.eof
{
cout<<"Reading "<<j<<" array:"<<endl;
// Removed the read form here
for (i=0,k=0;i<array_size;i++)
{
cout<<j<<"["<<i<<"]="<<a[i]<<endl;
if (a[i]<0) k++;
}
cout<<"Number of negative elements in "<<j++<<" array="<<k<<endl;
}
Well, that should solve the problem with your output.