C++ accessing vector of vector got segmentation fault - c++

I created a vector of vector (10*10000) and try to access this vector through member function. but I got a segmentation fault. I don't know what's wrong here...
Here is Simple.h
class Simple
{
private:
std::vector<double> data_row;
std::vector<std::vector<double> > data;
public:
Simple():data_row(10000), data(10, data_row){};
/*initialize data vector*/
int getSampleCounts(std::istream &File);
/*return number of packet samples in this file*/
Result getModel(std::istream &File);
/*return average and variance of simple delta time*/
void splitData (std::istream &File, const int & sample_in_fold);
};
#endif /* SIMPLE_H */
here is Simple.cpp
void Simple::splitData(std::istream& File, const int & sample_in_fold) {
double value = 0.0;
bool isFailed = true;
int label = 0;
while (File >> value) {
// for each value, generate a label
srand(time(NULL));
label = rand() % 10; // generate label between 0 to 9
while (isFailed) {
// segmentation fault in the next line!
std::cout << "current data size is: " << this->data.size() <<endl;
std::vector<double>::size_type sz = this->data[label].size();
if (sz <= sample_in_fold) {
std::cout << "current size is " << sz << "< samples in fold: " << sample_in_fold << endl;
this->data[label].push_back(value);
std::cout << "push_back succeed!" << endl;
isFailed = false;
} else {
std::cout << "label " << label << "if full. Next label. \n";
srand(time(NULL));
label = rand() % 10;
sz = this->data[label].size();
}
}
}
}
and I'm attaching the main file here.
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib> // for system())
#include <sys/types.h>
#include <dirent.h>
#include <vector>
#include <limits.h> // for PATH_MAX
#include "Complex.h"
#include "Result.h"
#include "Simple.h"
#include <math.h>
using namespace std;
int main(int argc, char ** argv) {
struct dirent *pDirent;
DIR *pDir;
std::string line;
// check for args
if (argc == 1) {
printf("Usage: ./main + folder name. \n");
return 1;
}
pDir = opendir(argv[1]);
if (pDir == NULL) {
printf("Cannot open directory '%s' \n", argv[1]);
return 1;
}
// readdir returns a pointer to the next direcctory entry dirent structure
while ((pDirent = readdir(pDir)) != NULL) {
// get file name and absolute path
char *name = pDirent->d_name;
char buf[PATH_MAX + 1];
realpath(name, buf);
// std::cout << "Current file is: " << (pDirent->d_name) << endl;
if (has_suffix(pDirent->d_name, ".txt")) {
printf("[%s]\n", pDirent->d_name);
//printf("absolute path is %s. \n", buf);
ifstream infile;
// open file with absolute path
infile.open(buf, ios::in);
if (!infile) {
cerr << "Can't open input file " << buf << endl;
exit(1);
}
//processing for simple pattern
if (has_suffix(name, "testfile.txt")) {
Simple* simple_obj;
int number = simple_obj->getSampleCounts(infile);
Result simplerst = simple_obj->getModel(infile);
std::cout << "Number of delta time is " << number << endl;
infile.clear();
infile.seekg(0);
write_to_file(pDirent->d_name, simplerst);
// divide data into k = 10 folds, get number of data in each fold
int sample_in_fold = floor(number / 10);
std::cout << sample_in_fold << std::endl;
simple_obj->splitData(infile, sample_in_fold);
}
} else {
// printf("This is not a txt file. Continue\n");
}
}
closedir(pDir);
return 0;
}
And here is a sample testfile.txt. I only copied part of the original file, for illustration.
10.145906000
10.151063000
10.131083000
10.143461000
10.131745000
10.151285000
10.147493000
10.123198000
10.144975000
10.144484000
10.138129000
10.131634000
10.144311000
10.157710000
10.138047000
10.122754000
10.137675000
10.204973000
10.140399000
10.142194000
10.138388000
10.141669000
10.138056000
10.138679000
10.141415000
10.154170000
10.139574000
10.140207000
10.149151000
10.164629000
10.106818000
10.142431000
10.137675000
10.204973000
10.140399000
10.142194000
10.138388000
10.141669000
10.138056000
10.138679000
10.141415000
Here is Result.h
#ifndef RESULT_H
#define RESULT_H
typedef struct Result {
double average;
double sigma;
}Result;
and getModel function in Simple.cpp:
Result Simple::getModel(std::istream &File) {
double value = 0.0;
double average = 0.0;
double sum = 0.0;
double counter = 0.0;
double sumsqr = 0.0;
double var = 0.0;
double sigma = 0.0;
while (File >> value) {
++counter;
sum += value;
sumsqr += value * value;
}
average = sum / counter;
var = sumsqr / counter - average * average; //E(x^2) - (E(x))^2
sigma = sqrt(var);
std::cout << "average is " << average << std::endl;
std::cout << "std deviation is " << sigma << std::endl;
File.clear();
File.seekg(0);
Result result = {average, sigma};
return result;
}

One issue right away:
Simple* simple_obj;
int number = simple_obj->getSampleCounts(infile);
simple_obj is an uninitialized pointer, thus your program exhibits undefined behavior at this point.
Why use a pointer anyway? You could have simply done this to avoid the issue:
Simple simple_obj;
simple_obj.getSampleCounts(infile);
Also, this line may not be an issue, but I'll mention it anyway:
Result simplerst = simple_obj->getModel(infile);
We already know that in your original code, simple_obj is bogus, but that's not the issue here. If Result is an object, and that object does not have correct copy semantics, then that assignment will also cause undefined behavior.

You've got a couple of uses of endl without specifying std::endl (they're not the same thing - you always have to type the std:: ). Is endl silently referring to another variable somewhere else?

Related

std::stof() rounds numbers, how to avoid

Im trying to get a float value from a file.txt into a string. When I output that value with std::stof(str) it gets rounded. Example, in the text file there's "101471.71", whet i use the std::stof(str) it returns "101472", how to I avoid this?
Here's a part of that code (some parts are in spanish, sorry :p):
double CaptureLine(std::string filepath, int fileline, int linesize)
{
std::fstream file;
std::string n_str, num_n;
int current_line = 0, n_size, filesize = FileSize(filepath);
char ch_n;
double n_float = 0.0;
int n_line = filesize - fileline;
file.open("registros.txt");
if (file.is_open()) {
while (!file.eof()) {
current_line++;
std::getline(file, n_str);
if (current_line == n_line) break;
}
if (current_line < n_line) {
std::cout << "Error" << std::endl;
return 1;
}
file.close();
}
n_size = n_str.length();
for (int i = linesize; i < n_size; i++) {
ch_n = n_str.at(i);
num_n.push_back(ch_n);
}
std::cout << ">>" << num_n << "<<\n";
n_float = std::stof(num_n); //Here's the error
return n_float;
}
The issue probably isn't with std::stof, but is probably with the default precision of 6 in std::cout. You can use std::setprecision to increase that precision and capture all of your digits.
Here's a program that demonstrates:
#include <iostream>
#include <iomanip>
#include <string>
int main() {
std::cout << 101471.71f << "\n";
std::cout << std::stof("101471.71") << "\n";
std::cout << std::setprecision(8) << 101471.71f << "\n";
std::cout << std::stof("101471.71") << "\n";
return 0;
}
Outputs:
101472
101472
101471.71
101471.71
Be aware that std::setprecision sticks to the std::cout stream after it's called. Notice how the above example calls it exactly once but its effect sticks around.

How can i convert a specific vector<string> to a string[n] [duplicate]

This question already has answers here:
How to convert vector to array
(10 answers)
Closed 6 years ago.
Here is my vector from a dictionary file :
//
//
//
//
#include <iostream>
#include <string>
#include <math.h>
#include <fstream>
#include <vector>
#include <regex>
using namespace std;
/**
* Read file function
* #params path : path of the file
* #params skip_line : num of line to skip from begining
* #params limit_line
* #params parse_data : put data from file to array
* #return : execution time
*/
long read_data(string path, int skip_line, int limit_line, vector<string> &parse_data) {
long time = clock();
ifstream stream(path);
if (!stream) {
cerr << "File : " + path + " not found." << endl;
return -1;
}
string line; int count = 0;
while (getline(stream, line)) {
if (count<skip_line) {
count++;
continue;
}
if (count >= limit_line && limit_line > 0) {
break;
}
if (line.empty()) {
continue;
}
count++;
try{
string delimiter_keyword = "#";
string delimiter_translate = "*";
string pre_translate = line.substr(0, line.find(delimiter_translate));
string translate = line.substr(line.find(delimiter_translate)+1);
string key_word = pre_translate.substr(0, pre_translate.find(delimiter_keyword));
string pronounce_word = pre_translate.substr(pre_translate.find(delimiter_keyword));
// cout << translate << endl;
// cout << pronounce_word << endl;
parse_data.push_back(key_word);
} catch(exception ex) {
// parse exception
}
}
stream.close();
time = (clock() - time)/ double(CLOCKS_PER_SEC) * 1000;
return time;
}
long heap_sort(){
long time = clock();
/**
* Help code here.
*/
time = (clock() - time)/ double(CLOCKS_PER_SEC) * 1000;
return time;
}
long quick_sort(){
long time = clock();
/**
* Help code here.
*/
time = (clock() - time)/ double(CLOCKS_PER_SEC) * 1000;
return time;
}
int main() {
int limit_line = 0;
vector<string> dictionary_data;
int exec_time = read_data(
"D:\Nam 2\Cau truc du lieu va giai thuat\av.dd",
3, limit_line, dictionary_data
);
cout << "Total time : " << exec_time << " ms" << endl;
for (string line : dictionary_data) {
cout << line << endl;
}
}
How can i convert this vector to a string[n] so i can put my sort algothrims into it ?
Thanks
How can i convert this vector to a string[n]
A vector can not be converted to an array.
What you can do, is copy the contents of a vector to an array. But you don't want to do that, because you usually cannot know at compile time, how big the vector is going to be.
so i can put my sort algothrims into it ?
You don't need to "convert" a vector to an array in order to do that. Use the array contained within the vector as it is.

Using a for loop to modify string name when reading data

The idea of this part of my code is relatively simple; I am doing a for loop that iterates over some range of integers, and the value of the iteration is placed within a number to string conversion and then called within the for loop to read a data file.
The code snippet:
for (int z = 11; z < 33; z++) {
const std::string filename_1 = "detection";
int value = z;
std::string filename_2;
std::ostringstream convert;
convert << value;
filename_2 = convert.str();
const std::string filename_3 = ".rat";
const std::string my_file = filename_1 + filename_2 + filename_3;
// Reading data from the .rat files of the detected signal.
Reading(my_file, times_det, signal_det);
// Further calculations go here.
The code compiles and executes, but after reading out two results of the calculations I am returned with the error:
./test
0.527679
0.639159
*** Error in `./test': double free or corruption (out): 0x0000000000f52a30 ***
Aborted (core dumped)
Am I not clearing memory where is necessary? Using .clear() did not remove this issue.
Thank you for the advice!
EDIT: The function 'Reading' for clarity:
void Reading(const std::string &filename, rarray<double,1> &times, rarray<std::complex<double>,1> &signal) {
std::ifstream f(filename.c_str());
// Read in the signal.
f >> times;
f >> signal;
}
#kam, I tried to reproduce the issue by using the following code and I am suspecting that it may have to do with the rarrays that you are using, but commented out as I don't have the details of the library you are using.
#include <iostream>
#include <fstream>
#include <strstream>
#include <sstream>
using namespace std;
void Reading(const std::string &filename, /*rarray< */double /*,1> */ &times, /* rarray<std::complex< */ double /*>,1> */ &signal) {
std::ifstream f(filename.c_str());
// std::ifstream f;
std::string ofile = "o_" + filename;
std::ofstream o;
//f.open(filename.c_str());
o.open(ofile.c_str());
// Read in the signal.
f >> times;
f >> signal;
cout << "file open :" << f.is_open() << " ";
cout << times << " " << signal << endl << flush;
//o << "file open :" << f.is_open() << " ";
o << times << " " << signal << endl << flush;
//f.close();
o.close();
}
int main(int argc, const char * argv[]) {
const std::string filename_1 = "detection";
const std::string filename_3 = ".rat";
double times_det = 0.0, signal_det = 0.0;
for (int z = 11; z < 33; z++) {
int value = z;
std::string filename_2;
std::ostringstream convert;
convert << value;
filename_2 = convert.str();
const std::string my_file = filename_1 + filename_2 + filename_3;
// Reading data from the .rat files of the detected signal.
Reading(my_file, times_det, signal_det);
// Further calculations go here.
}
return 0;
}

C++ getline segmentation fault, std::vector<custom class>

I've been looking at this for a while in the debugger while Googling around, but I think I've stumbled upon some C++ behavior that I'm not familiar with. I'm going to give a quick outline on what I'm doing and what/where the problem is. I'll put code block below.
The rough outline of what's happening is:
Created a custom class (LogReader) to handle a single log file.
LogReader contains a pointer to an ifstream (ifstream *log_file)
The ifstream is used with getline() in the constructor, this works fine.
The LogReader is placed in a vector.
The code below for main.cpp is using the LogReader directly (without the vector). The segfault occurs in both cases.
LogReader.advance() is called. getline() is used in this function. The segfault occurs here (commented in LogReader.cpp).
Thanks for any help on what C++ behaviors I'm missing that might be causing this!
EDIT: Not placing the LogReader into a vector removes the segfault (failing elsewhere now, but not a problem). The change is commenting the following line out in main.cpp
readers.push_back(&label_reader);
I guess now the question is why using std::vector is causing this problem.
LogReader.h
#ifndef LOGREADER
#define LOGREADER
using namespace std;
class LogReader {
private:
LogReader(){} // private default constructor
public:
ifstream *log_file; // file the log is read from
vector<int> val_locations; // offsets in line for values
string next_line; // next line from the file
int current_time; // time for most recent reading
string current_line;
int next_time; // what is the next time in the file
vector<string> current_vals; // what the current vals are
LogReader(string log_loc, vector<int> offsets); // given a file to start on
bool advance(int new_time); // advance the log reader, return true if advanced
bool has_more(); // is there more in the log
};
#endif
LogReader.cpp
// c++ imports
#include <boost/algorithm/string.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
// my imports
#include "LogReader.h"
#include "functions.h"
using namespace std;
LogReader::LogReader(string log_loc, vector<int> offsets){
// make the file reader
ifstream lf(log_loc);
log_file = &lf;
// pull out the first line
getline(*log_file, current_line);
cout << current_line << endl;
// get the set of current values
val_locations = offsets;
for(int i = 0; i < val_locations.size(); i++) {
current_vals.push_back(get_line_part(current_line,
val_locations.at(i)));
}
// get the current time
current_time = stoi(get_line_part(current_line, 0));
// pull down the next line
getline(*log_file, next_line);
cout << next_line << endl;
// get the next time
next_time = stoi(get_line_part(next_line, 0));
}
bool LogReader::advance(int new_time){
if(new_time < next_time)
return false; // nothing to do, current still good
cout << "can check time" << endl;
// update the time and values
current_time = next_time;
current_line = next_line;
current_vals.clear();
cout << "can do housekeeping" << endl;
for(int i = 0; i < val_locations.size(); i++) {
current_vals.push_back(get_line_part(next_line,
val_locations.at(i)));
}
cout << "can push in new values" << endl;
// move the line
next_line.clear();
if(!getline(*log_file, next_line)) { // **SEGFAULT**
// no more lines
cout << "no more lines" << endl;
next_line.clear();
next_time = -1;
return true;
}
cout << "got the line" << endl;
// update the time as well
next_time = stoi(get_line_part(next_line, 0));
return true;
}
bool LogReader::has_more(){
return next_time != -1;
}
main.cpp
// c imports
#include <time.h>
// c++ imports
#include <algorithm>
#include <boost/algorithm/string.hpp>
#include <boost/date_time.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/filesystem.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
// my imports
#include "LogReader.h"
#include "functions.h"
// custom shorter namespaces
namespace bfs = boost::filesystem;
// used namespaces
using namespace std;
void update_line(int *current_time, string *current_line,
ifstream *current_file){
if(!getline(*current_file, *current_line)){
*current_time = -1;
current_line->clear();
return;
}
try {
*current_time = stoi(get_line_part(*current_line, 0));
} catch (int e) {
cout << "update line, bad stoi on time" << endl;
cout << *current_line << endl;
throw e;
}
}
void update_vals(vector<float*> vals, string line) {
for(int i = 0; i < vals.size(); i++) {
// offset for fact that first two are time and sensor
try {
*(vals.at(i)) = stof(get_line_part(line, 2 + i));
} catch (int e) {
cout << "update_vals, bad stof for " << i << endl;
cout << line << endl;
throw e;
}
}
}
string get_correct_file(string name, vector<string> options) {
for(int i =0; i < options.size(); i++) {
string option = options.at(i);
if(boost::algorithm::contains(option, name)){
return option;
}
}
return string("");
}
int main(int argc, char* argv[]) {
// open the base dir
bfs::path base_dir("log/");
if(!bfs::exists(base_dir) && !bfs::is_directory(base_dir)){
cout << "Bad base directory" << endl;
return 1;
}
// create a vector of the possible traces
vector<string> traces;
for(bfs::directory_iterator iter(base_dir);
iter != bfs::directory_iterator(); iter++) {
stringstream trace_path;
trace_path << iter->path().string();
traces.push_back(trace_path.str());
}
int trace_index = user_choose_option(traces);
// load that directory
bfs::path trace_dir(traces.at(trace_index));
if(!bfs::exists(base_dir) && !bfs::is_directory(base_dir)){
cout << "Selected a bad trace directory" << endl;
return 1;
}
// get the image directory
cout << "loading image directory" << endl;
string img_path_string = trace_dir.string();
stringstream img_path_stream;
img_path_stream << img_path_string << "/img/";
bfs::path img_dir(img_path_stream.str());
if(!bfs::exists(img_dir) && !bfs::is_directory(img_dir)){
cout << "no image directory" << endl;
return 1;
}
// get image list, ends up in sorted order from naming conventions
cout << "getting image paths" << endl;
vector<string> image_paths;
for(bfs::directory_iterator iter(img_dir);
iter != bfs::directory_iterator(); iter++) {
stringstream image_path;
image_path << iter->path().string();
image_paths.push_back(image_path.str());
}
// get the data traces
cout << "loading data traces" << endl;
vector<string> log_paths;
vector<string> label_paths;
string trace_path_string = trace_dir.string();
for(bfs::directory_iterator iter(trace_path_string);
iter != bfs::directory_iterator(); iter++) {
string cur_file = iter->path().string();
cout << cur_file << endl;
if(boost::algorithm::contains(cur_file, "label-")) {
label_paths.push_back(cur_file);
} else if(boost::algorithm::contains(cur_file, "log-")) {
log_paths.push_back(cur_file);
}
}
cout << endl;
// temp for reading in line parts
// istringstream temp;
cout << "getting log readers" << endl;
// choose the label file to use, get first line
int label_index = user_choose_option(label_paths);
vector<int> label_offsets;
label_offsets.push_back(1);
LogReader label_reader(label_paths.at(label_index), label_offsets);
/*
ifstream label_file(label_paths.at(label_index));
string label_line;
getline(label_file, label_line);
int label_time;
temp.clear();
temp.str(get_line_part(label_line, 0));
temp >> label_time;
string label_current = get_line_part(label_line, 1);
*/
/*
// get the accel
string accel_path = get_correct_file("accel", log_paths);
vector<int> accel_offsets;
accel_offsets.push_back(2);
accel_offsets.push_back(3);
accel_offsets.push_back(4);
LogReader accel_reader(accel_path, accel_offsets);
*/
vector<LogReader*> readers;
vector<bool> updated;
readers.push_back(&label_reader);
updated.push_back(true);
// readers.push_back(&accel_reader);
// updated.push_back(true);
int l_time = current_time_min(readers);
while(label_reader.has_more() ){ // || accel_reader.has_more()) {
// figure out what time to advance to
int n_time;
cout << label_reader.has_more() << endl;
if(same_current_time(readers)) {
n_time = next_time_min(readers);
} else {
n_time = current_time_nextmin(readers);
}
cout << n_time << endl;
label_reader.advance(n_time);
cout << label_reader.current_line << endl;
/*
// advance all the readers
for(int i = 0; i < readers.size(); i++) {
cout << "loop " << i << endl;
// keep track of which values updated
readers.at(i);
cout << "can get from vector" << endl;
bool advanced = readers.at(i)->advance(n_time);
cout << advanced << endl;
if(advanced) {
updated.at(i) = true;
} else {
updated.at(i) = false;
}
}
// sanity check printing
for(int i = 0; i < readers.size(); i++) {
cout << readers.at(i)->current_line << endl;
}
*/
// deal with statistics here
}
/*
ifstream accel_file(accel_path);
string accel_line;
getline(accel_file, accel_line);
int accel_time;
temp.clear();
temp.str(get_line_part(accel_line, 0));
temp >> accel_time;
float accel_current_x = stof(get_line_part(accel_line, 2));
float accel_current_y = stof(get_line_part(accel_line, 3));
float accel_current_z = stof(get_line_part(accel_line, 4));
vector<float*> accel_vals;
accel_vals.push_back(&accel_current_x);
accel_vals.push_back(&accel_current_y);
accel_vals.push_back(&accel_current_z);
// get the sprox
string sprox_path = get_correct_file("sprox", log_paths);
ifstream sprox_file(sprox_path);
string sprox_line;
getline(sprox_file, sprox_line);
int sprox_time;
temp.clear();
temp.str(get_line_part(sprox_line, 0));
temp >> sprox_time;
float sprox_current = stof(get_line_part(sprox_line, 2));
vector<float*> sprox_vals;
sprox_vals.push_back(&sprox_current);
// get the lprox
string lprox_path = get_correct_file("lprox", log_paths);
ifstream lprox_file(lprox_path);
string lprox_line;
getline(lprox_file, lprox_line);
int lprox_time;
temp.clear();
temp.str(get_line_part(lprox_line, 0));
temp >> lprox_time;
float lprox_current = stof(get_line_part(lprox_line, 2));
vector<float*> lprox_vals;
lprox_vals.push_back(&lprox_current);
// get the light
string light_path = get_correct_file("light", log_paths);
ifstream light_file(light_path);
string light_line;
getline(light_file, light_line);
int light_time;
temp.clear();
temp.str(get_line_part(light_line, 0));
temp >> light_time;
float light_current = stof(get_line_part(light_line, 2));
vector<float*> light_vals;
light_vals.push_back(&light_current);
*/
// int time_current = min(label_time, min(sprox_time,
// min(lprox_time, min(accel_time,
// light_time))));
/*
// variables for processing here
int total_time = 0;
map<string, int> label_counts;
while(label_time != -1 || accel_time != -1 || sprox_time != -1
|| lprox_time != -1 || light_time != -1) {
time_current++;
if(label_time != -1 && time_current > label_time) {
update_line(&label_time, &label_line, &label_file);
if(label_line.size() > 0) // if last label, don't overwrite
label_current = get_line_part(label_line, 1);
}
if(accel_time != -1 && time_current > accel_time) {
update_line(&accel_time, &accel_line, &accel_file);
if(accel_line.size() > 0) // if last line, don't overwrite
update_vals(accel_vals, accel_line);
}
if(sprox_time != -1 && time_current > sprox_time) {
update_line(&sprox_time, &sprox_line, &sprox_file);
if(sprox_line.size() > 0) // if last line, don't overwrite
update_vals(sprox_vals, sprox_line);
}
if(lprox_time != -1 && time_current > lprox_time) {
update_line(&lprox_time, &lprox_line, &lprox_file);
if(lprox_line.size() > 0) // if last line, don't overwrite
update_vals(lprox_vals, lprox_line);
}
if(light_time != -1 && time_current > light_time) {
update_line(&light_time, &light_line, &light_file);
if(light_line.size() > 0) // if last line, don't overwrite
update_vals(light_vals, light_line);
}
// Processing happens here
total_time++;
if(label_counts.count(label_current) == 0)
// not in map
label_counts[label_current] = 0;
label_counts[label_current]++;
}
// post processing happens here
cout << "Labels Counts:" << endl;
for(map<string, int>::iterator it = label_counts.begin();
it != label_counts.end(); it++) {
cout << it->first << " -> " << it->second << " -> ";
cout << 1.0 * it->second / total_time << endl;
}
*/
}
Your program exhibits undefined behavior since you are using a pointer to an object that has been deleted.
ifstream lf(log_loc);
log_file = &lf;
if gets deleted when the constructor returns and you are still holding on to a pointer to the object.
Change log_file to an object instead of a pointer.

Frequency table in C++

This is what I have so far; I am trying to have an array with probability of all chars and space in a text file, but I have a problem with the data type.
int main()
{
float x[27];
unsigned sum = 0;
struct Count {
unsigned n;
void print(unsigned index, unsigned total) {
char c = (char)index;
if (isprint(c)) cout << "'" << c << "'";
else cout << "'\\" << index << "'";
cout << " occured " << n << "/" << total << " times";
cout << ", propability is " << (double)n / total << "\n";
}
Count() : n() {}
} count[256];
ifstream myfile("C:\\text.txt"); // one \ masks the other
while (!myfile.eof()) {
char c;
myfile.get(c);
if (!myfile) break;
sum++;
count[(unsigned char)c].n++;
}
for (unsigned i = 0; i<256; i++)
{
count[i].print(i, sum);
}
x[0] = count[33];
int j=68;
for(int i=1;i<27;i++)
{
x[i]=count[j];
j++;
}
return 0;
}
#include <iostream>
#include <fstream>
#include <cctype>
using namespace std;
double probabilities[256]; // now it can be accessed by Count
int main()
{
unsigned sum = 0;
struct Count {
unsigned n;
double prob;
void print ( unsigned index, unsigned total ) {
// if ( ! n ) return;
probabilities[index] = prob = (double)n/total;
char c = (char) index;
if ( isprint(c) ) cout << "'" << c << "'";
else cout << "'\\" << index << "'";
cout<<" seen "<<n<<"/"<<total<<" times, probability is "<<prob<<endl;
}
Count(): n(), prob() {}
operator double() const { return prob; }
operator float() const { return (float)prob; }
} count[256];
ifstream myfile("C:\\text.txt"); // one \ masks the other
while(!myfile.eof()) {
char c;
myfile.get(c);
if ( !myfile ) break;
sum++;
count[(unsigned char)c].n++;
}
for ( unsigned i=0; i<256; i++ ) count[i].print(i,sum);
return 0;
}
I incorporated various changes suggested - Thanks!
Now, who finds the 4 ways to access the actual probabilities?
you are allocating a buffer with size 1000000 1 million characters.
char file[1000000] = "C:\text.txt";
This is not good as the extra values in the buffer are not guaranteed to be zero, the can be anything.
For Windows to read a file you need something like this. I will not give you the solution, you need to learn using msdn and documentation to understand this fully::
you need to include the #include <windows.h> header from the SDK first.
Look at this example here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363778(v=vs.85).aspx
this example as appending a file to another. Your solution will be similar, instead of writing list to other file, process the buffer to increment your local variables and update the state of the table.
Do not set a large number you come up with for the buffer, as there will risk of not enough buffer space, and thus overflow. You should do like example:
read some bytes in buffer
process that buffer and increment the table
repeat until you reach end of file
while (ReadFile(hFile, buff, sizeof(buff), &dwBytesRead, NULL)
&& dwBytesRead > 0)
{
// write you logic here
}