I am new to C++ so what I am trying to do is, reading a CSV file in my function readRecord(readRecord() templated function). In my CSV file I have stored some data such as years and crime, crime rate etc and display it using display function. I posted my code so far but it is giving me error I am not sure about how to make it work. can someone help me out please?
#ifndef SICT_DATA_H
#define SICT_DATA_H
#include <fstream>
#include <iomanip>
namespace sict {
const int LARGEST_NUMBER = 1000000000; // 1,000,000,000
const int SMALLEST_NUMBER = 0;
const int COLUMN_WIDTH = 15;
template <typename T>
T max(const T* data, int n)
{
int maximum = data[0];
for (int i = 0; i < n; i++)
{
if (data[i] > maximum)
{
maximum = data[i];
//*data = maximum;
}
}
return maximum;
}
template <typename T>
T min(const T* data, int n)
{
T minimum = data[0];
for (int i = 0; i < n; i++)
{
if ((dataa[i] < minimum) && (data[i] >= SMALLEST_NUMBER))
{
minimum = data[i];
//*data = minimum;
}
}
return minimum;
}
template <typename T>
T sum(const T* data, int n)
{
double sum;
for (int i = 0; i <= n; i++)
{
sum = sum + data[i];
}
return sum;
}
template <typename T>
double average(const T* data, int n)
{
double average;
for (int i = 0; i <= n; i++)
{
average = (sum(data, n) / n);
}
return average;
}
template <typename T>
bool read(std::istream& input, T* data, int n)
{
char comma;
for (int i = 0; i < n; i++)
{
input >> comma >> data[i];
if (cin.fail())
{
return false;
}
}
return true;
}
template <typename T>
void readRecord()
{
ifstream ip("crimedata.csv");
int year[5];
int pop[5];
int crime[5];
int rate[5];
int autoo[5];
int rate1[5];
while (ip.EOF())
{
for (int i = 0; i < 5 i++)
{
getline(ip.year[i], ',');
getline(ip.pop[i], ',');
getline(ip.crime[i], ',');
getline(ip.rate[i], ',');
getline(ip.autoo[i], ',');
getline(ip.rate1[i], '\n');
cout << year[i] << pop[i] << crime[i] << endl;
}
}
ip.close;
}
template <typename T>
void display(const char* name, const T* data, int n)
{
readRecord();
cout << setw(20) << name ;
cout << setw(15) << data << endl;
}
}
#endif
Csv File:
5
Year 2000 2001 2002 2003 2004
Population 281421906 285317559 287973924 290788976 293656842
ViolentCrime 1425486 1439480 1423677 1383676 1360088
ViolentCrime_Rate 506.5 504.5 494.4 475.8 463.2
GrandTheftAuto 1160002 1228391 1246646 1261226 1237851
GrandTheftAuto_Rate 412.2 430.5 432.9 433.7 421.5
Related
There are two files:
Matrix.hpp:
template <typename T>
class Matrix {
private:
size_t rows = 0;
size_t cols = 0;
T* data = nullptr;
public:
Matrix() = default;
~Matrix();
Matrix(size_t n, size_t m);
T& operator() (size_t i, size_t j);
};
template <typename T>
Matrix<T>::Matrix(size_t n, size_t m) : rows(n), cols(m) {
try {
data = new T[rows*cols];
} catch (const std::bad_alloc& e) {
std::exit(EXIT_FAILURE);
}
};
template <typename T>
Matrix<T>::~Matrix() {
delete[] data;
}
template <typename T>
T& Matrix<T>::operator()(size_t i, size_t j) {
if (i < rows && i >= 0 && j < cols && j >= 0) {
return data[(i+1)*cols + (j+1)];
} else {
throw std::logic_error("matrix indices out of range");
}
}
and
Main.cpp:
#include <iostream>
#include "Matrix.hpp"
int main() {
size_t n, k;
std::cin >> n >> k;
Matrix<long double> m = {n, k};
for (size_t i = 0; i < m.getNumRows(); ++i) {
for (size_t j = 0; j < m.getNumCols(); ++j) {
std::cin >> m(i,j);
}
}
for (size_t i = 0; i < m.getNumRows(); ++i) {
std::cout << "\n";
for (size_t j = 0; j < m.getNumCols(); ++j) {
std::cout << m(i, j) << " ";
}
}
return 0;
}
When I'm entering something like:
1 2 3 4
I can get
3 4
as answer but sometimes the same input causes Segmentation fault 11 moreover when I'm changing template argument from long double to int, error disappears. How can I fix it?
Your operator function is accessing data outside its bounds.
Passing (0,0) to the function should return data[0]. Currently it returns data[2].
Change line
return data[(i+1)*cols+(j+1)];
to
return data[i*cols+j];
After looking through articles, tutorials and solutions everywhere, i haven't come across anything that explains how to use quicksort for string arrays. All examples I found are of either "int" or "char".
This is my edited code.
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <time.h>
#include <string>
#include <ctime>
#include <stdio.h>
using namespace std;
int count;
template <class T>
void printArray(T ar[], int sz);
template <class T>
void bubbleSort(T ar[], int sz);
void quickSortMain(string items[], int ct);
void quickSort(string items[], int left, int right);
//////////////////////////////////////////////////////////////////////////
// Main Function Implementation
//////////////////////////////////////////////////////////////////////////
int main() {
int numOfData = 50000;
string line, temp;
ofstream resultFile;
ofstream tableFile;
double data[100][2];
string patient[numOfData];
ifstream dataFile("shufflePatient.txt");
int i;
int SIZE = 0;
cout << "Program to shuffle data" << endl << endl;
cout << "This program will calculate swapping processes and running time.";
/*Storing data*/
cout << "Reading data in process.." << endl;
if (dataFile.is_open()) {
i=-1;
while (dataFile.good()) {
getline (dataFile, line);
if (i>=0) patient[i] = line;
i++;
}
dataFile.close();
}
SIZE = 5;
quickSortMain(patient, 5);
/*Writing to file*/
cout << "Writing to file.." << endl;
resultFile.open ("test.txt");
for (int i=0 ; i<numOfData ; i++) {
resultFile << patient[i] << "\n";
}
resultFile.close();
system("pause");
return 0;
}
void quickSortMain(string items[], int ct)
{
quickSort(items, 0, ct-1);
}
void quickSort(string items[], int left, int right)
{
int i, j;
char *x;
string temp[10];
i = left;
j = right;
x = items[(left+right)/2];
do {
while((strcmp(items[i],x) < 0) && (i < right)) {
i++;
}
while((strcmp(items[j],x) > 0) && (j > left)) {
j--;
}
if(i <= j) {
strcpy(temp, items[i]);
strcpy(items[i], items[j]);
strcpy(items[j], temp);
i++;
j--;
}
} while(i <= j);
if(left < j) {
quickSort(items, left, j);
}
if(i < right) {
quickSort(items, i, right);
}
}
//----------------------------------------------------------------------------
// prints array of size size
//----------------------------------------------------------------------------
template <class T>
void printArray(T patient[], int size)
{
for(int i = 0; i < size; i++)
cout << patient[i] << " ";
cout << endl;
}
//----------------------------------------------------------------------------
// sorts array of size size by Bubble Sort method
//----------------------------------------------------------------------------
template <class T>
void bubbleSort(T patient[], int size) //returning an int
{
bool noChange = true;
for(int i = size; i > 0; i--)
{
noChange = true;
for(int j = 1; j < i; j++)
{
if(patient[j] < patient[j - 1])
{
swap(patient[j], patient[j-1]);
count = count + 1;
noChange = false;
}
}
if (noChange)
return ;
}
}
The error i got was in this line:
x = items[(left+right)/2];
I changed
char x*; to string x;
I don't know if that was correct. Now the error im getting is that strcmp and strcpy are not declared. Any help on what i should do next?
string patient[numOfData];
vs.
template <class T>
void quickSortMain(char items[][10], int ct)
vs.
quickSortMain(patient, 5);
quickSortMain expects an array of char[10], not string[]. Not only this, but it also depends on a template parameter. Drop the template <class T> and replace char[][10] with string[].
This is my code. I don't know how to get the code to run. Im having problems with quicksorting for string.
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <time.h>
#include <string>
#include <ctime>
#include <stdio.h>
using namespace std;
int count;
template <class T>
void printArray(T ar[], int sz);
template <class T>
void bubbleSort(T ar[], int sz);
void quickSortMain(string items[], int ct);
void quickSort(string items[], int left, int right);
//////////////////////////////////////////////////////////////////////////
// Main Function Implementation
//////////////////////////////////////////////////////////////////////////
int main() {
int numOfData = 50000;
string line, temp;
ofstream resultFile;
ofstream tableFile;
double data[100][2];
string patient[numOfData];
ifstream dataFile("shufflePatient.txt");
int i;
int SIZE = 0;
cout << "Program to shuffle data" << endl << endl;
cout << "This program will calculate swapping processes and running time.";
/*Storing data*/
cout << "Reading data in process.." << endl;
if (dataFile.is_open()) {
i=-1;
while (dataFile.good()) {
getline (dataFile, line);
if (i>=0) patient[i] = line;
i++;
}
dataFile.close();
}
SIZE = 5;
quickSortMain(patient, 5);
/*Writing to file*/
cout << "Writing to file.." << endl;
resultFile.open ("test.txt");
for (int i=0 ; i<numOfData ; i++) {
resultFile << patient[i] << "\n";
}
resultFile.close();
system("pause");
return 0;
}
void quickSortMain(string items[], int ct)
{
quickSort(items, 0, ct-1);
}
void quickSort(string items[], int left, int right)
{
int i, j;
char *x;
string temp[10];
i = left;
j = right;
x = items[(left+right)/2];
do {
while((strcmp(items[i],x) < 0) && (i < right)) {
i++;
}
while((strcmp(items[j],x) > 0) && (j > left)) {
j--;
}
if(i <= j) {
strcpy(temp, items[i]);
strcpy(items[i], items[j]);
strcpy(items[j], temp);
i++;
j--;
}
} while(i <= j);
if(left < j) {
quickSort(items, left, j);
}
if(i < right) {
quickSort(items, i, right);
}
}
//----------------------------------------------------------------------------
// prints array of size size
//----------------------------------------------------------------------------
template <class T>
void printArray(T patient[], int size)
{
for(int i = 0; i < size; i++)
cout << patient[i] << " ";
cout << endl;
}
//----------------------------------------------------------------------------
// sorts array of size size by Bubble Sort method
//----------------------------------------------------------------------------
template <class T>
void bubbleSort(T patient[], int size) //returning an int
{
bool noChange = true;
for(int i = size; i > 0; i--)
{
noChange = true;
for(int j = 1; j < i; j++)
{
if(patient[j] < patient[j - 1])
{
swap(patient[j], patient[j-1]);
count = count + 1;
noChange = false;
}
}
if (noChange)
return ;
}
}
The error i got was in this line:
x = items[(left+right)/2];
I changed
char x*; to string x;
I don't know if that was correct. Now the error im getting is that strcmp and strcpy are not declared. Any help on what i should do next?
That's correct, now change
strcmp(items[i],x) < 0
to
items[i] < x
and
strcmp(items[j],x) > 0
to
items[j] > x
and
strcpy(temp, items[i]);
to
temp = items[i];
etc.
But really this is a case of RTFM. If you're competent enough to write a quicksort routine you should be competent enough to look up how std::string works. Being able to access reference information is a very important skill for a programmer.
I keep getting a segmentation fault error in my code
Header
#ifndef DUALSTK
#define DUALSTK
#include <deque>
using namespace std;
enum stackNumber {One, Two};
template <typename T>
class dualStack {
public:
// constructor. set counts to 0
dualStack() : dualStackElements(20, 0) {}
void push(const T& item, stackNumber n);
void pop(stackNumber n);
T& top(stackNumber n);
//const T& top(stackNumber n) const;
bool empty(stackNumber n) const;
int size(stackNumber n) const;
int getCount1() const {return count1;}
int getCount2() const {return count2;}
private:
deque<T> dualStackElements;
int count1, count2;
};
#endif // DUALSTK
main.cpp
#include <iostream>
#include <deque>
#include "dualstk.h"
using namespace std;
template <typename T>
T& dualStack<T>::top(stackNumber n) {
int num = 0;
if (n == 0) {
num = count1 - 1;
return num;
}
if (n == 1) {
num = 20 - count2;
return num;
}
}
template <typename T>
void dualStack<T>::push(const T& item, stackNumber n) {
if (n == 0) {
count1++;
dualStackElements[top(One)] = item;
}
if (n == 1) {
count2++;
dualStackElements[top(Two)] = item;
}
}
template <typename T>
void dualStack<T>::pop(stackNumber n) {
int item = 0;
int item2 = 0;
if (n == 0) {
item = dualStackElements[top(One)];
cout << item << " ";
count1--;
}
if (n == 1) {
item2 = dualStackElements[top(Two)];
cout << item2 << " ";
count2--;
}
}
template <typename T>
bool dualStack<T>::empty(stackNumber n) const {
return 1;
}
int main() {
dualStack<int> stack;
for(int i = 1; i < 21; i++) {
if(i % 2 == 0) {
stack.push(i, One);
}
else {
cout << i;
stack.push(i, Two);
}
}
cout << endl;
for (int j = 0; j < 10; j++)
stack.pop(One);
cout << endl;
for (int i = 0; i < 10; i++)
stack.pop(Two);
cout << endl;
cout << stack.getCount2();
cout << stack.getCount1();
cout << endl;
cout << "\n" << stack.top(One);
cout << stack.top(Two) << endl;
return 0;
}
Whenever I have one loop for my stack.pop it will work fine
but if I do a for loop right after I use one to do stack.pop it wont work
I am not sure what I did wrong to this
for (int j = 0; j < 10; j++)
stack.pop(One);
for (int i = 0; i < 10; i++)
stack.pop(Two);
function top() returns reference to local variable ‘num’. Its storage is on stack so the value would be modified when the function returns and then you use it as the index into dualStackElements. This may lead to access to invalid memory address.
I think you are misunderstanding what this does (or I misunderstood your code):
dualStackElements[top(One)] = item;
you have not declared an array of dualStackElements
Better to declare two dequeues instead.
deque<T> dualStackElementsOne;
deque<T> dualStackElementsTwo;
Your Top method needs some error checking. What if count1 is 0 (or count2 > 20)? You'd return a negative value and then use it as an index to your deque. And remove the return by reference!
top() method returns a reference to local variable num which was freed after the method call. But different OS have different limits on accessing illegal memory, sometimes, it is just OK in Linux.
In your constructor, there is no initializing operations for fields: count1, count2. The program always returns "Segmentation fault;" if I comment out "count1=count2=0;" in my modified constructor.
In order to get the stable result for a program, you should do a clean before a make. I don't know exactly why, but it did happen in my test run.
I'm getting an error regarding "disgarded qualifiers" when I use this. The Entier class is posted below.
cout << d // where d is of type dynamic_array.
The global overloaded function:
template <class T> std::ostream& operator<<(std::ostream& stream, dynamic_array<T> const& data)
{
data.print_array(stream);
return stream;
}
A public member of dynamic_array
void print_array(std::ostream &os = cout)
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
Entire Class dynamic array:
/*
Needs a reszie function added
Merge sort is better for sequential, stable(equal elements not re-arranged, or
*/
#include "c_arclib.cpp"
using namespace std;
template <class T> class dynamic_array
{
private:
T* array;
T* scratch;
void merge_recurse(int left, int right)
{
if(right == left + 1)
{
return;
}
else
{
int i = 0;
int length = right - left;
int midpoint_distance = length/2;
int l = left, r = left + midpoint_distance;
merge_recurse(left, left + midpoint_distance);
merge_recurse(left + midpoint_distance, right);
for(i = 0; i < length; i++)
{
if((l < (left + midpoint_distance)) && (r == right || array[l] > array[r]))
{
scratch[i] = array[l];
l++;
}
else
{
scratch[i] = array[r];
r++;
}
}
for(i = left; i < right; i++)
{
array[i] = scratch[i - left];
}
}
}
void quick_recurse(int left, int right)
{
int l = left, r = right, tmp;
int pivot = array[(left + right) / 2];
while (l <= r)
{
while (array[l] < pivot)l++;
while (array[r] > pivot)r--;
if (l <= r)
{
tmp = array[l];
array[l] = array[r];
array[r] = tmp;
l++;
r--;
}
}
if (left < r)quick_recurse(left, r);
if (l < right)quick_recurse(l, right);
}
public:
int size;
dynamic_array(int sizein)
{
size=sizein;
array = new T[size]();
}
void print_array(std::ostream &os = cout)
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
void print_array()
{
for (int i = 0; i < size; i++) cout << array[i] << endl;
}
int merge_sort()
{
scratch = new T[size]();
if(scratch != NULL)
{
merge_recurse(0, size);
return 1;
}
else
{
return 0;
}
}
void quick_sort()
{
quick_recurse(0,size);
}
void rand_to_array()
{
srand(time(NULL));
int* k;
for (k = array; k != array + size; ++k)
{
*k=rand();
}
}
void order_to_array()
{
int* k;
int i = 0;
for (k = array; k != array + size; ++k)
{
*k=i;
++i;
}
}
void rorder_to_array()
{
int* k;
int i = size;
for (k = array; k != array + size; ++k)
{
*k=i;
--i;
}
}
};
template <class T> std::ostream& operator<<(std::ostream& stream, dynamic_array<T> const& data)
{
data.print_array(stream);
return stream;
}
int main()
{
dynamic_array<int> d1(1000000);
d1.order_to_array();
clock_t time_start=clock();
d1.merge_sort();
clock_t time_end=clock();
double result = (double)(time_end - time_start) / CLOCKS_PER_SEC;
cout << result;
cout << d1;
}
The problem is in following lines:
template <class T>
std::ostream& operator<<(std::ostream& stream, dynamic_array<T> const& data)
^^^^^^
and
void print_array(std::ostream &os = cout) /* const */
^^^^^ missing
Since you are passing data as const& to operator <<, you have to maintain its const qualification. i.e. data cannot call any non-const member of class dynamic_array. You can solve this problem in 2 ways:
pass data as simple dynamic_array<T>& to operator <<
make print_array a const method (uncomment above)
"Discards const qualifiers", presumably...
Replace:
void print_array(std::ostream &os = cout)
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
void print_array()
{
for (int i = 0; i < size; i++) cout << array[i] << endl;
}
...with...
void print_array(std::ostream &os = cout) const
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
...or, better still ...
void print_array(std::ostream &os = cout) const
{
std::copy(array, array + size, std::ostream_iterator<T>(os, "\n"));
}
This member function can be declared const since it doesn't modify any attributes of the class. See the FAQ on Const-Correctness.
Your second print_array() method is redundant since the first takes a default argument of std::cout.