C++ Input Output Sorting - c++

The assignment calls for using 3 input and 3 output files, but for now I am trying just one. The program is supposed to include a function template that sorts an array of values in ascending order. The function will receive an unordered array and will return an ordered array. The function isn't supposed to perform any input or output.
My code exists as the following:
#include <iostream>
#include <iostream>
#include <fstream>
using namespace std;
ifstream inNumbers("intTestRead.txt");
ofstream outNumbers("intTestWrite.txt");
template<typename int[], typename int> void SelectionSort(int[], int);
void SelectionSort(int v[], int n)
{
int iMin;
for (int i = 0; i < n - 1; i++)
{
iMin = i;
for (int j = i + 1; j < n; j++)
{
if (v[j] < v[iMin])
{
iMin = j;
}
}
int aux = v[i];
v[i] = v[iMin];
v[iMin] = aux;
}
}
void main()
{
int data[100];
int i;
int length = 0;
if (!inNumbers)
cerr << "intTestRead.txt file could not be opened" << endl;
for (i = 0; i < 100 && inNumbers; ++i)
{
inNumbers >> data[i];
if (inNumbers)
{
length += 1;
}
SelectionSort(data, length);
outNumbers << data[i] << endl;
}
}
I mainly program in Java, and now just beginning C++ confuses me with templates and whatnot. The sorting function was given to us by the professor. My reading file looks like this:
65 40 84 9 79 90 71 93 39 44
It's supposed to look like this:
9 39 40 44 65 71 79 84 90 93
But look's like this:
65
65
84
84
84
90
90
93
93
93
-858993460
^^ I know because I'm using endl results in the new lines, but multiple recursions of the same number + the -85 is putting me off. Any help would be greatly appreciated.

Don't call the sort function after each input. Just call it when all input is ready.
Something like:
void main()
{
int data[100];
int i;
int length = 0;
if (!inNumbers)
cerr << "intTestRead.txt file could not be opened" << endl;
for (i = 0; i < 100 && inNumbers; ++i)
{
inNumbers >> data[i];
if (inNumbers)
{
length += 1;
}
}
SelectionSort(data, length);
for (i = 0; i < length; ++i)
{
outNumbers << data[i] << endl;
}
}

Looked at it again, and used an alternative:
#include <iostream>
#include <iostream>
#include <fstream>
#define NUMBERS 10
using namespace std;
ifstream inNumbers("intTestRead.txt");
ofstream outNumbers("intTestWrite.txt");
template <class T>
void Swap(T& A, T& B)
{
T temp;
temp = A;
A = B;
B = temp;
}
template <class T>
void SelectionSort(T A[], int N)
{
T min;
int j, k, minIndex;
for (k = 0; k < N; k++) {
min = A[k]; minIndex = k;
for (j = k + 1; j < N; j++) {
if (A[j] < min) { min = A[j]; minIndex = j; }
}
Swap(A[k], A[minIndex]);
}
}
void main()
{
int data[100];
int i = 0;
if (!inNumbers)
cerr << "intTestRead.txt file could not be opened" << endl;
for (i = 0; i < NUMBERS && inNumbers; ++i)
{
inNumbers >> data[i];
}
SelectionSort(data, NUMBERS);
for (int i = 0; i < NUMBERS; ++i)
outNumbers << data[i] << endl;
}
Input:
65
40
84
9
79
90
71
93
39
44
Output:
9
39
40
44
65
71
79
84
90
93

Related

How do I avoid printing the numbers within the string of this file io program?

Here's my code:
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
string substring(string a, int b, int c) {
string result = "";
for (int i = b; i < b + c; i++) {
result += a[i];
}
return result;
}
int main() {
ifstream in_stream;
in_stream.open("HW3Test.txt");
ofstream output_stream("HW3output.txt");
string result[100];
int i = 0;
while (in_stream >> result[i]) {
i++;
}
string check[i];
for (int k = 0; k < i; k++) {
check[k] = substring(result[k], 0, 2);
}
string scores[i];
for (int k = 0; k < i; k++) {
if (check[k][0] >= '0' && check[k][0] <= '9') {
scores[k] = check[k];
}
}
for (int k = i; k >= 0; k--) {
output_stream << scores[k] << endl;
}
for (int k = 0; k < i; k++) {
if (!(result[k][0] >= '0') && !(result[k][0] <= '9')) {
output_stream << result[k];
}
}
}
In this problem, I'm given this input:
86 Bill Fun
93 Kelly Jelly
74 Bob Squee
81 Jim Flim
72 John Fraggle
87 June Prune
63 Roberta Robertson
and trying to achieve this output:
Fun, Bill: 63
Jelly, Kelly: 87
Squee, Bob: 72
Flim, Jim: 81
Fraggle, John: 74
Prune, June: 93
Robertson, Roberta: 86
So, I first got the scores in from the text file, and stored it in a scores array. Now, I need to get only the names, but for some reason, the program is not outputting any text when I check if the first character in the string is not a number. How can I get it to print out only the strings that start with a letter?
The following code may not be the most optimal, but it seems to work as expected.
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib> // for atoi function to convert to int,
//since c++ 11 you can use std::stoi(string) without this #include (but I didn't check it)
struct Leaderboard
{
std::string FirstName;
std::string Surname;
int score;
};
int main()
{
std::ifstream in_stream;
in_stream.open("HW3Test.txt");
if(!in_stream)
{
throw "Input File not Found";
}
std::ofstream output_stream("HW3output.txt");
//std::string result[100]; why only 100?
std::vector<Leaderboard> tLeaderBoardVector; // it can be bigger with for example vector
std::string tLine;
while (in_stream >> tLine)
{
Leaderboard tmpLeaderboard;
tmpLeaderboard.score = atoi(tLine.c_str());
in_stream >> tLine;
tmpLeaderboard.FirstName = tLine;
in_stream >> tLine;
tmpLeaderboard.Surname = tLine;
tLeaderBoardVector.push_back(tmpLeaderboard);
}
//reverse points output to get the same output as in question output, but I don't know why reverse it
for(int i = 0; i < tLeaderBoardVector.size() / 2; i++)
{
int tmp = tLeaderBoardVector[i].score;
tLeaderBoardVector[i].score = tLeaderBoardVector[tLeaderBoardVector.size() - 1 - i].score;
tLeaderBoardVector[tLeaderBoardVector.size() - 1 - i].score = tmp;
}
for (int i = 0; i < tLeaderBoardVector.size(); i++)
{
output_stream << tLeaderBoardVector[i].Surname << ", ";
output_stream << tLeaderBoardVector[i].FirstName << ": ";
output_stream << tLeaderBoardVector[i].score << "\n";
}
return 0;
}

sorting by smallest digit using selection sort

my task is to sort an array by the smallest digit of a number using selection sort. for example: 61 < 35, because 1 < 3. in case of coincidence of digits, i have to print the smallest of 2.
so this is my code:
#include <iostream>
#include <time.h>
using namespace std;
int smallestOfTwo(int a, int b) {
if (a < b) return a;
else return b;
}
int smallestDigit(int a) {
int smallDigit = 9;
while (a != 0) {
if (a % 10 < smallDigit) {
smallDigit = a % 10;
}
a /= 10;
}
return smallDigit;
}
void selectionSort(int arr[], const int size) {
for (int i = 0; i < size - 1; i++) {
int min = i;
for (int j = i + 1; j < size; j++) {
if (smallestDigit(arr[j]) == smallestDigit(arr[min])) min = smallestOfTwo(j, min);
else if (smallestDigit(arr[j]) < smallestDigit(arr[min])) min = j;
}
if (min != i) {
swap(arr[min], arr[i]);
}
}
}
int main() {
srand(time(NULL));
const int size = 5;
int arr[size];
for (int i = 0; i < size; i++) {
arr[i] = rand() % 201;
cout << arr[i] << " ";
}
cout << "\n--------------------------------------------------------------------------------------\n";
selectionSort(arr, size);
for (int i = 0; i < size; i++) cout << arr[i] << " ";
return 0;
}
the problem is that for some numbers it works (for example, for 23 63 70 37 183 the output is correct: 70 183 23 37 63), but for some it doesnt work(for example, 27 26 156 178 47. the output is 156 178 27 26 47, but it should be 156 178 26 27 47 instead) and i cant figure out why. any help would be appreciated. thanks!
26 and 27 both have smallest digit 2, so they are equivalent and can be in any order in the result. To preserve original order, you can try looking up algorithms for "stable sort." To fall back on second smallest digit, third smallest digit, etc. you can count each digit and compare.
struct digit_counts {
int counts[10];
};
digit_counts convert(int a) {
digit_counts out = {};
while (a != 0) {
++out.counts[a % 10];
a /= 10;
}
return out;
}
bool operator<(const digit_counts& dc1, const digit_counts& dc2) {
for (int i = 0; i < 10; ++i) {
if (dc1.counts[i] > dc2.counts[i]) {
return true;
}
else if (dc2.counts[i] > dc1.counts[i]) {
return false;
}
}
return false;
}
If you want to fall back on the smaller of the two, then write your own comparison function.
bool special_less_than(int a, int b) {
int small_digit_a = smallestDigit(a);
int small_digit_b = smallestDigit(b);
if (small_digit_a < small_digit_b) {
return true;
}
else if (small_digit_a > small_digit_b) {
return false;
}
else {
return a < b;
}
}

When I try to read a matrix from a file, I get all kinds of errors, but works fine when just using data entered in

When I try to read from a file using the same numbers I get errors like: the array has an unknown storage capacity.
#include<iostream>
#include <fstream>
using namespace std;
const int N = 7;
When I uncomment this function and try to read from a file, I get errors. This is the code that doesn't work:
void readFile(int magicSquareArray[][N]);
bool isMagicSquare(int magicSquareArray[][N]);
int main()
{
int magicSquareArray[][N];
when I change readFile(magicSquareArray[][N]); to readFile(magicSquareArray); I get the same error plus: main.cpp:19:5: error: 'readFile' was not declared in this scope
readFile(magicSquareArray);
readFile(magicSquareArray[][N]);
if (isMagicSquare(magicSquareArray))
{
cout << "Magic Square";
}
else
cout << "Not a magic Square";
return 0;
}
Returns true if magicSquareArray[][] is magic
square, else returns false.
bool isMagicSquare(int magicSquareArray[][N])
{
// calculate the sum of
// the prime diagonal
int sumOfDiagonal = 0;
int sumOfReverseDiagonal = 0;
for (int i = 0; i < N; i++)
{
sumOfDiagonal += magicSquareArray[i][i];
sumOfReverseDiagonal += magicSquareArray[i][N- i-1];
}
if(sumOfDiagonal != sumOfReverseDiagonal)
return false;
// For sums of Rows
for (int i = 0; i < N; i++)
{
int calculateSumRows = 0;
for (int j = 0; j < N; j++)
{
calculateSumRows += magicSquareArray[i][j];
}
// check if every row sum is
// equal to prime diagonal sum
if (calculateSumRows != sumOfDiagonal)
return false;
}
// For sums of Columns
for (int i = 0; i < N; i++)
{
int calculateSumColumns = 0;
for (int j = 0; j < N; j++)
calculateSumColumns += magicSquareArray[j][i];
// check if every column sum is
// equal to prime diagonal sum
if (sumOfDiagonal != calculateSumColumns)
return false;
}
return true;
}
the file looks like this:
30 39 48 1 10 19 28
38 47 7 9 18 27 29
46 6 8 17 26 35 37
5 14 16 25 34 36 45
13 15 24 33 42 44 4
21 23 32 41 43 3 12
22 31 40 49 2 11 20
this function gives me errors when I enable it:
void readFile(int magicSquareArray[][N])
{
ifstream matrix { "360magictext.txt" };
if (!matrix.is_open())
cout << "Error! Unable to open file!";
for (int i{}; i != N; ++i)
{
for (int j{}; j != N; ++j)
{
matrix >> magicSquareArray[i][j];
}
}
}
Is there a reason you cannot use std::vector? This is C++ and in C++ we should be using the standard library to help us out with these kinds of things. I think your first error comes from the fact that the first [] in your array is empty and needs to know a number before hand. I think there might be a way around it with size_tif you are reading a matrix in of unknown size.
I was able to get your program to compile and run with the following changes:
#include <vector>
#define Matrix std::vector<std::vector<int>>
const int N = 7;
void readFile(Matrix magicSquareArray);
bool isMagicSquare(Matrix magicSquareArray);
int main()
{
Matrix magicSquareArray(N,std::vector<int>(N));
readFile(magicSquareArray);
//readFile(magicSquareArray[N][N]);
if (isMagicSquare(magicSquareArray))
{
std::cout << "Magic Square";
}
else
std::cout << "Not a magic Square";
return 0;
}
void readFile(Matrix magicSquareArray)
{
std::ifstream matrix { "360magictext.txt" };
if (!matrix.is_open())
std::cout << "Error! Unable to open file!";
for (int i = 0; i != N; ++i)
{
for (int j = 0; j != N; ++j)
{
matrix >> magicSquareArray[i][j];
}
}
}
What I did was #define Matrix by created a Matrix with a two dimensional std::vector's. I then went ahead and constructed an NxN Matrix by calling Matrix magicSquareArray(N,std::vector<int>(N)); I left the original commented out in case you still need it. However, you will still have a lot more compiler errors with your original code.

How to correct my nested for loop in the input_data function?

My Question is that in the input_data() function takes in two parameters, the infile and the statistics_array. This function reads (loops) through the five sets of semester final exam data and populates a portion of the statistics_array.that includes the year,the number of grades and input the number of grades into the grade array that is within the Exam Type Struct I feel as the loop is wrong because at the end when i output all the information is wrong my code and the file contents are below how do i fix this problem?
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;
struct ExamType {
string semester_name;
int year;
int num_grades;
float average_grade;
int grades_above_average;
int grades_below_average;
int grades_array[35];
};
void input_data(ExamType[], ifstream&);
void calculate_statistics(ExamType[]);
void print_results(ExamType[]);
void calculate_average(ExamType[], int);
void calculate_above_average(ExamType[], int);
void calculate_below_average(ExamType[], int);
int main()
{
char make_type;
ifstream myfile;
ExamType statistics_array[5];
myfile.open("infile.txt");
input_data(statistics_array, myfile);
calculate_statistics(statistics_array);
print_results(statistics_array);
}
void input_data(ExamType statistics_array[], ifstream& myfile)
{
int num_students;
for (int i = 0; i < 5; i++) {
myfile >> statistics_array[i].semester_name;
myfile >> statistics_array[i].year;
myfile >> statistics_array[i].num_grades;
for (int j = 0; j < statistics_array[i].num_grades; j++) {
statistics_array[j].grades_array[i];
}
}
}
void calculate_statistics(ExamType statistics_array[])
{
for (int index = 0; index < 5; index++)
{
calculate_average(statistics_array, index);
calculate_above_average(statistics_array, index);
calculate_below_average(statistics_array, index);
}
}
void calculate_average(ExamType statistics_array[], int index)
{
float sum=0;
float total_average;
for (int i = 0; i < statistics_array[index].num_grades; i++)
{
sum=sum+statistics_array[index].grades_array[i];
}
total_average = sum / statistics_array[index].num_grades;
statistics_array[index].average_grade = total_average;
}
void calculate_above_average(ExamType statistics_array[], int index)
{
int count = 0;
for (int i = 0; i < statistics_array[index].num_grades; i++)
{
if (statistics_array[index].grades_array[index] > statistics_array[index].average_grade)
{
count++;
}
statistics_array[index].grades_above_average = count;
}
}
void calculate_below_average(ExamType statistics_array[], int index)
{
int count = 0;
for (int i = 0; i < statistics_array[index].num_grades; i++)
{
if (statistics_array[index].grades_array[index] < statistics_array[index].average_grade)
{
count++;
}
statistics_array[index].grades_below_average = count;
}
}
void print_results(ExamType statistics_array[])
{
for (int i = 0; i < 5; i++)
{
cout << "Analysis of exams in fall" << " " << statistics_array[i].semester_name << statistics_array[i].year<<endl;
cout << endl;
cout << "The number of grades above average are" << " " << statistics_array[i].grades_above_average<<endl;
cout << "The number of grades above average are" << " " << statistics_array[i].grades_below_average<<endl;
}
}
And the output:
Fall 2013 17
54
96
68
99
35
81
93
32
12
23
45
55
66
77
88
99
100
Spring 2014 10
99
48
22
41
66
80
91
55
83
92
Fall 2014 12
32
12
23
45
51
62
97
38
59
80
91
98
Spring 2015 20
93
41
60
80
90
55
88
99
32
12
23
45
55
66
77
88
99
100
99
98
Fall 2015 15
92
45
61
86
90
55
82
92
32
12
23
45
53
61
73
int j = 0; j < statistics_array[i].num_grades; j++) {
myfile >> statistics_array[i].grades_array[j];
}
the input_data function nest loop code should modify according to above.

Merge sort algorithm not working correctly

As part of a homework assignment, I need to be able to implement a merge sort using a structure as the main argument. Having not been familiar with the merge sort until today, i have attempted to write my own implementation of it. For some reason I cannot get it to work.
Here is my code:
#include<iostream>
#include<stdlib.h>
using namespace std;
struct MergeArgument
{
int *numArray;
int *tempArray;
int lowIndex, highIndex;
};
void merge(MergeArgument*);
void merge_sort(MergeArgument*);
int main(int argc, char** argv)
{ int SIZE = 25;
MergeArgument arg;
int arr[SIZE];
int temp[SIZE];
for(int k = 0; k < SIZE; k++)
{
arr[k] = rand() % 100;
cout << arr[k] << " ";
}
arg.numArray = arr;
arg.tempArray = temp;
arg.lowIndex = 0;
arg.highIndex = SIZE - 1;
cout << endl;
merge_sort(&arg);
cout << "Sorted array: \n";
for (int i = 0; i < SIZE; i++)
cout << arr[i] << " ";
cout << endl;
return 0;
}
void merge_sort(MergeArgument *arg)
{ int tempHigh, tempLow;
if(arg->lowIndex < arg->highIndex)
{
tempHigh = arg->highIndex;
tempLow = arg->lowIndex;
arg->highIndex = (tempHigh + tempLow) / 2;
merge_sort(arg);
arg->highIndex = tempHigh;
arg->lowIndex = ((tempHigh + tempLow) / 2) + 1;
merge_sort(arg);
arg->lowIndex = tempLow;
merge(arg);
}
}
void merge(MergeArgument *arg)
{ int low = arg->lowIndex, mid = ((arg->lowIndex + arg->highIndex) / 2), high = arg->highIndex;
int i = low, lowCounter = low, highCounter = mid + 1;
while((lowCounter <= mid) && (highCounter <= high))
{
if(arg->numArray[lowCounter] < arg->numArray[highCounter])
{
arg->tempArray[i] = arg->numArray[lowCounter];
lowCounter++;
}
else
{
arg->tempArray[i] = arg->numArray[highCounter];
highCounter++;
}
i++;
}
if (lowCounter < mid)
{
for (int k = lowCounter; k < mid; k++)
{
arg->tempArray[i] = arg->numArray[k];
i++;
}
}
else
{
for (int k = highCounter; k <= arg->highIndex; k++)
{
arg->tempArray[i] = arg->numArray[k];
i++;
}
}
for(int k = arg->lowIndex; k <= arg->highIndex; k++)
{
arg->numArray[k] = arg->tempArray[k];
}
}
Here is the output I am getting:
83 86 77 15 93 35 86 92 49 21 62 27 90 59 63 26 40 26 72 36 11 68 67 29 82
Sorted array:
11 -1216235240 15 0 21 26 -1079135248 26 27 -1079135396 29 -1216770650 35 -1216235240 49 -1216492084 59 0 68 72 82 83 0 86 82
Can anyone point out what exactly I am doing wrong?
This is pretty close to working, although you might want to consider some of the comments folks have made on making this more C++ like. No doubt this is from hard-won experience that there is never enough time to go back and do what you really should do.
The problem I see is here, in merge:
if (lowCounter < mid)
{
for (int k = lowCounter; k < mid; k++)
{
arg->tempArray[i] = arg->numArray[k];
i++;
}
}
You might want to compare and contrast the bounds here to the initial loop.