reading data file for root cern graphing - c++

I created a script to take data from a text file and graph it in Root (CERN) but haven't used root in about a year, updated to the current version of Root and now it gets the error "Error: Function readprn() is not defined in current scope :0:
* Interpreter error recovered *" when i try to use it with Root.
It runs an excel data file that I saved as a txt file. The first column is the x value corresponding to each y value in the subsequent 768 columns. At the end it graphs and fits and loops over a couple graphs.
I'm mostly wondering if there is anything in the new versions that would cause this to not be able to be read by root.
#include <TGraph.h>
#include <TCanvas.h>
#include <TF1.h>
#include <TMath.h>
#include <TStyle.h>
#include <iostream>
#include <fstream>
#include <string>
using std::cout; using std::endl;
int threshold1(Int_t channel=0)
{
const char* ifname = "thresholdScanRun110FPGA4.txt";
cout<< "processing file " << ifname <<endl;
std::ifstream ifile(ifname);
if (!ifile) {
cout<< "Could not find file " << ifname <<endl;
return 0;
}
//std::string line;
// discard the first two lines
//std::getline(ifile, line);
//cout<< line <<endl;
//std::getline(ifile, line);
//cout<< line <<endl;
std::string str;
double number;
// read the first row (in sense of Exel's row)
ifile >> str;
//cout<< str <<endl;
for (int i=0; i<768; ++i) {
ifile >> number;
//cout<< number << " ";
}
//cout<<endl;
// read the second "row"
ifile >> str;
//cout<< str <<endl;
for (int i=0; i<768; ++i) {
ifile >> number;
//cout<< number << " ";
}
//cout<<endl;
double thres[60];
double prob[60][768];
int nthres_max = 60;
for (int ithres=0; ithres<nthres_max; ++ithres) {
ifile >> thres[ithres];
for (int iprob=0; iprob<768; ++iprob) ifile >> prob[ithres][iprob];
}
cout<< "The channel " << channel <<endl;
for (int ithres=0; ithres<60; ++ithres) {
cout<< thres[ithres] << " " << prob[ithres][channel] <<endl;
}
Double_t probability[60];
for (int ithres=0; ithres<60; ++ithres) probability[ithres] = prob[ithres][channel];
TGraph* gr = new TGraph(60, thres, probability);
gr->SetMarkerStyle(29);
gr->SetMarkerColor(4);
gr->SetTitle("Threshold Scan ChipX, ChanY");
TF1* ferfc = new TF1("ferfc", "0.5*TMath::Erfc((x-[0])/[1])", 0, 767);
ferfc->SetParameters(100,10);
new TCanvas;
gStyle->SetOptFit(1);
gr->Draw("apl");
gr->Fit("ferfc");
return 0;
}
int threshold_all()
{
for (Int_t channel=0; channel<2; ++channel) {
threshold1(channel);
}
}

when loading your macro in root 6.07/04, with .L macro.C I receive the following warning:
/tmp/tmp.rQTNVdlydv/macro.C:88:1: error: control reaches end of non-void function [-Werror,-Wreturn-type]
which is because you don't have a return statement in int threshold_all(). Fixing this the macro seems fine to me. (runs, opens a canvas, some fit output. Since I don't have your input values, I just created a text file with a few invented numbers and reduced the number of thresholds and values to 5x6. Which is why I'm not concerned about the abnormal fit termination which I receive.).
Also loading the macro with compilation .L macro.C+ looks fine to me once adding the return statement.

Related

Reading coordinate file with ifstream while ignoring headers and writing to array

There's a series of coordinates I'm trying to write to an array so I can perform calculations on, but I haven't been able to read the file correctly since I can't ignore the headers, and when I do remove the headers it also doesn't seem to correctly write the values to the array.
The coordinate file is a txt as below.
Coordinates of 4 points
x y z
-0.06325 0.0359793 0.0420873
-0.06275 0.0360343 0.0425949
-0.0645 0.0365101 0.0404362
-0.064 0.0366195 0.0414512
Any help with the code is much appreciated. I've tried using .ignore to skip the two header lines but they don't seem to work as expected.
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;
int main() {
int i = 1;
int count = 1;
char separator;
const int MAX = 10000;
int x[MAX];
int y[MAX];
int z[MAX];
int dist[MAX];
char in_file[16]; // File name string of 16 characters long
char out_file[16];
ifstream in_stream;
ofstream out_stream;
out_stream << setiosflags(ios::left); // Use IO Manipulators to set output to align left
cout << "This program reads a series of values from a given file, saves them into an array and performs calculations." << endl << endl;
// User data input
cout << "Enter the input in_file name: \n";
cin >> in_file;
cout << endl;
in_stream.open(in_file, ios::_Nocreate);
cout << "Enter the output file name: \n";
cin >> out_file;
cout << endl;
out_stream.open(out_file);
// While loop in case in_file does not exist / cannot be opened
while (in_stream.fail()) {
cout << "Error opening '" << in_file << "'\n";
cout << "Enter the input in_file name: ";
cin >> in_file;
in_stream.clear();
in_stream.open(in_file, ios::_Nocreate);
}
while (in_stream.good) {
in_stream.ignore(256, '\n');
in_stream.ignore(256, '\n');
in_stream >> x[i] >> separator >>y[i] >> separator >> z[i];
i++;
count = count + 1;
}
cout << x[1] << y[1] << z[1];
in_stream.close();
out_stream.close();
return 0;
}
Within your reading of the file, you are using in_stream.ignore(256, '\n'); correctly, but you want to use it outside the while loop. When you have it inside the while loop, every time it runs, you will ignore the first two lines, then read the third. Your output would actually read in only a third of what you expect. To fix this, just move those 2 lines outside the while loop.
in_stream.ignore(256, '\n');
in_stream.ignore(256, '\n');
while (in_stream.good)
{
in_stream >> x[i] >> separator >>y[i] >> separator >> z[i];
i++;
count = count + 1;
}
This should fix your problem, but you should generally use a vector instead of an array. Vectors automatically manage memory and check for bounds instead of you having to do that.
Also, good practice is to read values out of the stream as the while condition instead of in_stream.good:
while(stream >> var)
{
//Your code here
}
Here is a good resource on why that is.

printing weird symbols to output file, c++

I am writing a code that reads an input file of numbers, sorts them in ascending order, and prints them to output. The only thing printed to output is some really freaky symbols.
Here is my code
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
int i, y, temp, num[20];
char file_nameI[21], file_nameO[21];
ofstream outfile;
ifstream infile;
cout << "Please enter name of input file: ";
cin >> file_nameI;
infile.open(file_nameI);
if (!infile)
{
cout << "Could not open input file \n";
return 0;
}
cout << "Please enter name of output file: ";
cin >> file_nameO;
outfile.open(file_nameO);
if (!outfile)
{
cout << "Could not open output file \n";
return 0;
}
for (i = 0; i < 20; i++)
{
y = i + 1;
while (y < 5)
{
if (num[i] > num[y]) //Correction3
{
infile >> temp;
temp = num[i];
num[i] = num[y];
num[y] = temp;
//y++; //Correction4
}
y++;
}
}
for (i = 0; i < 5; i++)
outfile << "num[i]:" << num[i] << "\n";
return 0;
}
Here is my input
6 7 9 0 40
Here is the output
 „Ô,üþ 54
H|À°ÀzY „Ô,üþ 0
Problems with your code are already mentioned in the comments but again:
First problem is uninitialized elements of num[20] - elements of num have indeterminate values so accessing any of them triggers undefined behavior. You should first read them from the file or at least initialize them to some default value.
The part of code that should most likely do the sorting is just completely wrong. If you'd like to implement your own function for sorting, you can pick up some well-known algorithm like e.g. quicksort - but C++ Standard Library already provides sorting function - std::sort.
Besides obvious mistakes:
You are using char[] - in C++ it's almost always better to use std::string.
Your static array can only store 20 values and you are reading those from a file. You can use std::vector which can grow when you add more elements than its current capacity. It also automatically fixes the problem with uninitialized elements of num[20].
As mentioned in the comments you can organize your code and improve readability by splitting it into functions.
Here you've got it quickly rewritten. This code uses std::string instead of char[], std::vector to store the numbers and std::sort. If there is something you don't understand here, read SO documentation:
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> read_file(ifstream& in_file)
{
vector<int> vec;
int value;
while (in_file >> value)
{
vec.push_back(value);
}
return vec;
}
void write_file(ofstream& out_file, const vector<int>& values)
{
for (size_t i = 0; i < values.size(); ++i)
out_file << "value #" << i << ": " << values[i] << '\n';
}
int main()
{
string input_filename, output_filename;
ofstream out_file;
ifstream in_file;
cout << "Please enter name of input file: ";
cin >> input_filename;
in_file.open(input_filename);
if (!in_file)
{
cout << "Could not open input file\n";
return 0;
}
cout << "Please enter name of output file: ";
cin >> output_filename;
out_file.open(output_filename);
if (!out_file)
{
cout << "Could not open output file\n";
return 0;
}
auto numbers = read_file(in_file);
sort(begin(numbers), end(numbers));
write_file(out_file, numbers);
return 0;
}
You might forgot to store values in num array. Just update your code as follows and it will work.
infile.open(file_nameI);
if (!infile){
cout << "Could not open input file \n";
return 0;
} else{
i = 0;
while (infile >> num[i]){
i++;
}
}

I/O program stuck in loop C++

I'm working on a code that reads in a C++ source file and converts all ‘<’ symbols to “<” and all ‘>’ symbols to “>”. I wrote out the main method and everything compiled nicely but now that I'm actually writing out my convert function at the top of the program, I'm stuck in an infinite loop and I'm hitting a wall on what the culprit is. Could someone help me out?
I included the whole program in case the problem lies in my I/O coding but I surrounded the function with slashes. Hopefully I won't get flamed.
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <cstring>
using namespace std;
//FUNCTION GOES THROUGH EACH CHARACTER OF FILE
//AND CONVERTS ALL < & > TO < or > RESPECTIVELY
//////////////THIS IS THE FUNCTION IN QUESTION//////////
void convert (ifstream& inStream, ofstream& outStream){
cout << "start" << endl;
char x;
inStream.get(x);
while (!inStream.eof()){
if (x == '<')
outStream << "<";
else if (x == '>')
outStream << ">";
else
outStream << x;
}
cout << "end" << endl;
};
///////////////////////////////////////////////////////////////////////////
int main(){
//FILE OBJECTS
ifstream inputStream;
ofstream outputStream;
string fileName;
//string outFile;
//USER PROMPT FOR NAME OF FILE
cout << "Please enter the name of the file to be converted: " << endl;
cin >> fileName;
//outFile = fileName + ".html";
//ASSOCIATES FILE OBJECTS WITH FILES
inputStream.open(fileName.c_str());
outputStream.open(fileName + ".html");
//CREATES A CONVERTED OUTPUT WITH <PRE> AT START AND </PRE> AT END
outputStream << " <PRE>" << endl;
convert(inputStream, outputStream);
outputStream << " </PRE>" << endl;
inputStream.close();
outputStream.close();
cout << "Conversion complete." << endl;
return 0;
}
It isn't a good approach to manipulate a file while you're reading it. The right way is, first read the whole file, store the data, manipulate the stored data, and then update the file. Hope this code will help you :)
void convert()
{
int countLines = 0; // To count total lines in file
string *lines; // To store all lines
string temp;
ifstream in;
ofstream out;
// Opening file to count Lines
in.open("filename.txt");
while (!in.eof())
{
getline(in, temp);
countLines++;
}
in.close();
// Allocating Memory
lines = new string[countLines];
// Open it again to stroe data
in.open("filename.txt");
int i = 0;
while (!in.eof())
{
getline(in, lines[i]);
// To check if there is '<' symbol in the following line
for (int j = 0; lines[i][j] != '\0'; j++)
{
// Checking the conditon
if (lines[i][j] == '<')
lines[i][j] = '>';
}
i++;
}
in.close();
// Now mainuplating the file
out.open("filename.txt");
for (int i = 0; i < countLines; i++)
{
out << lines[i];
if (i < countLines - 1)
out << endl;
}
out.close();
}

Writing and reading from the same file

This program takes in an input, write it on a file character by character, count the amount of characters entered, then at the end copy it to an array of characters. The program works just fine until we get to the following snippet file.getline(arr, inputLength);. It changes the .txt file data and returns only the first character of the original input.
Any ideas?
#include <iostream>
#include <fstream>
using namespace std;
int getLine(char *& arr);
int main() {
char * arr = NULL;
cout << "Write something: ";
getLine(arr);
return 0;
}
int getLine(char *& arr) {
fstream file("temp.txt");
char input = '\0'; //initialize
int inputLength = 0; //initialize
if (file.is_open()) {
while (input != '\n') { //while the end of this line is not reached
input = cin.get(); //get each single character
file << input; //write it on a .txt file
inputLength++; //count the number of characters entered
}
arr = new char[inputLength]; //dynamically allocate memory for this array
file.getline(arr, inputLength); //HERE IS THE PROBLEM!!! ***
cout << "Count : " << inputLength << endl; //test counter
cout << "Array : " << arr << endl; //test line copy
file.close();
return 1;
}
return 0;
}
I see at least two problems with this code.
1) std::fstream constructor, by default, will open an existing file. It will not create a new one. If temp.txt does not exist, is_open() will fail. This code should pass the appropriate value for the second parameter to std::fstreams constructor that specifies that either a new file needs to be created, or the existing file is created.
Related to this: if the file already exists, running this code will not truncate it, so the contents of the file from this program's previous run will have obvious unexpected results.
2) The intent of this code appears to be to read back in the contents temp.txt that were previously written to it. To do that correctly, after writing and before reading it is necessary to seek back to the beginning of the file. This part appears to be missing.
There is no need in dynamic allocation because the std library functions get confused with mixed arguments such as cstring and pointer to cstring.I tested this code in Visual Studio 2015 compiler. It works good. Make sure to include all of the needed libraries:
#include <iostream>
#include <fstream>
#include<cstring>
#include<string>
using namespace std;
void getLine();
int main() {
cout << "Write something: ";
// no need to pass a pointer to a cstring
getLine();
system("pause");
return 0;
}
void getLine() {
char input[100]; // this is a cstring with
//a safe const number of elements
int inputLength; //to extract length of the actual input
//this function requires cstring as a first argument
// and constant length as a second
cin.get(input, 100, '\n'); //get each single character
//cast streamsize into int
inputLength = static_cast<int>(cin.gcount());
//testing input
cout << "Input: \n";
for (int i = 0; i < inputLength; i++)
{
cout << input[i];
}
cout << endl;
char arr[100];
strcpy_s(arr, input);
cout << "Count : " << inputLength << endl; //test counter
cout << "Array : " << endl; //test line copy
for (int i = 0; i < inputLength; i++)
{
cout << arr[i];
}
cout << endl;
// write cstring to a file
ofstream file;
file.open("temp.txt", ios::out);
if (file.is_open())
{
//write only what was entered in input
for (int i = 0; i < inputLength; i++)
file << arr[i];
file.close();
}
else cout << "Unable to open file";
}

C++ Getting values from file into array

#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <fstream>
using namespace std;
void make_array(ifstream& num, int (&array)[50]);
int main()
{
ifstream file; // variable controlling the file
char filename[100]; /// to handle calling the file name;
int array[50];
cout << "Please enter the name of the file you wish to process:";
cin >> filename;
cout << "\n";
file.open(filename);
if (file.fail()) {
cout << "The file failed to open.\n";
exit(1);
} else {
cout << "File Opened Successfully.\n";
}
make_array(file, array);
file.close();
return (0);
}
void make_array(ifstream& num, int (&array)[50])
{
int i = 0; // counter variable
while (!num.eof() && i < 50) {
num >> array[i];
i = i + 1;
}
for (i; i >= 0; i--) {
cout << array[i] << "\n";
}
}
I am trying to read values from a file to an array using fstream. When I try to display the contents of the array, I get 2 really big negative numbers, and then the contents of the file.
Any ideas what I did wrong?
Your use of num.get(array[i]) doesn't match any of its signatures. See get method description. What you want is this:
array[i] = num.get();
As discussed in the comments, you try to read an integer which is encoded as text. For this, you need to use operator>> (which reads any type encoded as string) instead of get (which reads a single byte):
num >> array[i];