I'm a student and I can't figure out how to complete this assignment. Basically were supposed to automatically compute a checksum on a datafile and store that checksum in an unsigned int array. The name of the file is supposed to be stored in another parallel array, and the contents of the file are to be read into a char array to compute the checksum.
This is what I have so far:
#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
//declare variables
string filePath;
void savefile();
char choice;
int i,a, b, sum;
sum = 0;
a = 0;
b = 0;
ifstream inFile;
//arrays
const int SUM_ARR_SZ = 100;
string fileNames[SUM_ARR_SZ];
unsigned int checkSums[SUM_ARR_SZ];
do{
cout << "Please select: " << endl;
cout << " A) Compute checksum of specified file" << endl;
cout << " B) Verify integrity of specified file" << endl;
cout << " Q) Quit" << endl;
cin >> choice;
if (choice == 'a' || choice == 'A')
{
//open file in binary mode
cout << "Specify the file path: " << endl;
cin >> filePath;
inFile.open(filePath.c_str(), ios::binary);
//save file name
fileNames[a] = filePath;
a++;
//use seekg and tellg to determine file size
char Arr[100000];
inFile.seekg(0, ios_base::end);
int fileLen = inFile.tellg();
inFile.seekg(0, ios_base::beg);
inFile.read(Arr, fileLen);
inFile.close();
for (i = 0; i < 100000; i++)
{
sum += Arr[i];
}
//store the sum into checkSums array
checkSums[b] = sum;
b++;
cout <<" File checksum = "<< sum << endl;
}
if (choice == 'b' || choice == 'B')
{
cout << "Specify the file path: " << endl;
cin >> filePath;
if (strcmp(filePath.c_str(), fileNames[a].c_str())==0)
{
}
}
} while (choice != 'q' && choice != 'Q');
system("pause");
}
And an example of what our output is supposed to be(the 'a' is user input):
Please select:
A) Compute checksum of specified file
B) Verify integrity of specified file
Q) Quit
a
Specify the file path: c:\temp\tmp1
File checksum = 1530
Please select:
A) Compute checksum of specified file
B) Verify integrity of specified file
Q) Quit
Update: I've got the first part of the program sorted out now, the one which checks the sum. The problem I have now is getting the output correct for if you select B on the menu.
It's supposed to check both arrays and make sure the name is right and make sure that the checksums are the same, but I'm completely lost on how to put that into code.
The problem is the limit of your for loop. You have it reading 100000 times regardless of the length of the file. Changing 100000 to fileLen limits the read to each character read into Arr:
for (i = 0; i < fileLen; i++) {
sum += Arr[i];
}
output:
$ ./bin/cscpp
Please select:
A) Compute checksum of specified file
B) Verify integrity of specified file
Q) Quit
a
Specify the file path:
tmpkernel315.txt
File checksum = 46173
Change your code to read from file char by char.
File length is unknown.
Do this untill End Of File:
inFile.seekg(0, ios_base::end);
int fileLen = inFile.tellg();
inFile.seekg(0, ios_base::beg);
for(int i =0; i<fileLen; i++)
{
char Arr[1];
inFile.read(Arr, 1);
sum += Arr[0];
}
inFile.close();
//sum is your answer
Related
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'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();
}
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";
}
the pseudocode for this assignment is essentually:
1. Open the specified file in binary mode
2. Save the file name in the fileNames array.
3. Determine the file size using seekg and tellg
4. Read the file contents into the character array in one statement
5. Close the file
6. Loop through the array, one character at a time and accumulate the sum of each byte
7. Store the sum into the checkSums array.
#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
//declare variables
string filePath;
void savefile();
char choice;
int i, a, b, sum;
sum = 0;
a = 0;
b = 0;
ifstream inFile;
//arrays
const int SUM_ARR_SZ = 100;
string fileNames[SUM_ARR_SZ];
unsigned int checkSums[SUM_ARR_SZ];
do {
cout << "Please select: " << endl;
cout << " A) Compute checksum of specified file" << endl;
cout << " B) Verify integrity of specified file" << endl;
cout << " Q) Quit" << endl;
cin >> choice;
if (choice == 'a' || choice == 'A')
{
//open file in binary mode
cout << "Specify the file path: " << endl;
cin >> filePath;
inFile.open(filePath.c_str(), ios::binary);
//save file name
fileNames[a] = filePath;
a++;
//use seekg and tellg to determine file size
char Arr[100000];
inFile.seekg(0, ios_base::end);
int fileLen = inFile.tellg();
inFile.seekg(0, ios_base::beg);
inFile.read(Arr, fileLen);
inFile.close();
for (i = 0; i < 100000; i++)
{
sum += Arr[i];
}
//store the sum into checkSums array
checkSums[b] = sum;
b++;
cout << " File checksum = " << sum << endl;
}
if (choice == 'b' || choice == 'B')
{
cout << "Specify the file path: " << endl;
cin >> filePath;
if (strcmp(filePath.c_str(), fileNames[a].c_str()) == 0)
{
}
}
} while (choice != 'q' && choice != 'Q');
system("pause");
}
I'm getting values like "-540000" and I'm not sure how to fix this. Any help is greatly appreciated!
You're creating an array on the stack without zeroing its contents, so Arr will contain "garbage" data.
You're creating the buffer with a fixed size, which means you're wasting space if the file is smaller than 100,000 bytes and you can't process a file that's larger than 100,000 bytes (without reusing the buffer)
You iterate over every byte in the buffer instead of those bytes that represent the file if it's smaller than 100,000 bytes.
I also note you're mixing C and C++ string functions. You don't need to call C's strcmp if you're using string then use string::compare.
C++ does not require forward-declaration of local variables, your code would be cleaner if you only declared local variables when they're used, instead of all-at-once.
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.