Sorting multidimensional array C++ strange behaviour - c++

I'm doing some programming practice right now by trying to sort a 2D array on it's first "column".
I am reading input from a file:
100 5
8 80
5 20
9 40
3 10
6 30
This is my code:
#include <cstdio>
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
bool helper(vector<long> k, vector<long> l)
{
return (k[0] < l[0]);
}
int main()
{
ifstream fi("milk.in");
ofstream fo("milk.out");
long price = 0, n, m, i, p, a;
vector< vector<long> > farmers;
vector<long> farmer(2,0);
fi >> n >> m;
for (i=0; i<n; ++i)
{
fi >> p >> a;
farmer[0] = p;
farmer[1] = a;
farmers.push_back(farmer);
}
sort(farmers.begin(),farmers.end(),helper);
for (i=0; i<m; ++i)
{
cout << farmers[i][0] << " " << farmers[i][1] << endl;
}
return 0;
}
As you can see, I try to sort the input by it's first column (I don't care about the first line at the moment).
However, this is the result:
3 10
5 20
6 30
6 30
6 30
This is the expected result:
3 10
5 20
6 30
8 80
9 40
I can't figure it out.

Your first line of your milk.in:
100 5
You're going to end up looping through trying to read in 100 inputs from this file because n = 100.
fi >> n >> m;
for (i=0; i<n; ++i)
If you change milk.in to:
5 5
8 80
5 20
9 40
3 10
6 30
That seems to work.
Perhaps a better idea is to just check if you're done reading input from the filestream:
for(i = 0; i < n; ++i)
{
if(!(fi >> farmer[0] >> farmer[1])) break;
farmers.push_back(farmer);
}

You need this loop to load the data from the file in:
And remember to close the file.
while(!fi.eof())
{
fi >> n >> m;
farmer[0] = n;
farmer[1] = m;
farmers.push_back(farmer);
}
fi.close( );
Also, I made some minor changes to your code:
#include <cstdio>
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
bool helper(vector<long> k, vector<long> l)
{
return (k[0] < l[0]);
}
int main()
{
long price = 0, n, m, i, p=0, a=0,numlines=0;
vector< vector<long> > farmers;
vector<long> farmer(2,0);
cout<<"\nLoading data from file: milk.in\n\n";
ifstream fi("milk.in");
while(!fi.eof())
{
fi >> n >> m;
numlines++;
cout<<n<<" "<<m<<"\n";
farmer[0] = n;
farmer[1] = m;
farmers.push_back(farmer);
}
fi.close( );
cout<<"--- "<<numlines<<" lines loaded\n";
cout<<"\n---------------------\n";
cout<<"\nSorted data:\n\n";
sort(farmers.begin(),farmers.end(),helper);
ofstream fo("milk.out");
for (i=0; i<numlines; ++i)
{
cout << farmers[i][0] << " " << farmers[i][1] << endl;
fo<< farmers[i][0] << " " << farmers[i][1] << endl;
}
fo.close();
cout<<"\n---------------------\n";
return 0;
}
Output:
Sorted data:
3 10
5 20
6 30
8 80
9 40
100 5

Related

How can I read the numbers from a file, then write them into two files in ascending order, one at a time, into one file, then into the second?

For example:
First file has these numbers:
10 1 5 -3 -9 -12 34 0 2 -52
Second file:
-52 -9 0 2 10
Third file:
-12 -3 1 5 34
My code:
#include <fstream>
#include <iostream>
#include <ctime>
#include <algorithm>
using namespace std;
void main()
{
srand(time(NULL));
int n = 10;
int *a = new int[n];
ifstream f("numbers.txt");
ofstream g("AscNum1.txt");
ofstream h("AscNum2.txt");
while (f.is_open()) {
for (int i = 0; i < n; i++) {
f >> a[i]; //reading numbers from file
}
sort(a, a + n);
for (int i = 0; i < n; i++) {
if (i % 2 == 0) {
g << a[i] << ' ';//writing number if its index is even
}
else
h << a[i] << ' '; //writing number if its index is not even
}
h.close();
g.close();
f.close();
}
}
In this code, i sort before "transferring" and "transfer" by even index(Second file contains numbers with even indexes).
How can I "transfer" without using sort? How can I make this by different way?

Bubble sort the numbers from a file in descending order for the first number

I want to sort using the "Bubble Sort" algorithm of the 2d array. My array size will be about array[100000][100000]. my input number will be n=100,000.
For now we can use a small size of the array to fix the sorting issue.
I need to sort them in descending order for the first number(first number's line).
If the first number of 2 values are the same, then I have to sort them according to their second number.
Finally I have to output the result into a txt file
Let's' understand using an example. Here, my input looks like this
41 11
34 4
69 4
78 6
62 8
5 5
81 3
5 10
above our input example and we have a couple of inputs. Now I need to sort them descending orders for the first number. But if the first number of 2 values are the same, then sort them according to their second number.
Example output below,
81 3
78 6
69 4
62 8
41 4
34 4
5 10
5 5
If anyone can please help me.
I am a beginner so I am trying to input the file manually to solve this sorting problem. I can solve the sorting problem then I will try to input and out the text.
Something I have tried but not worked. I am still trying to solve it.
#include<bits/stdc++.h>
#include <algorithm>
using namespace std;
int main ()
{
int arr[100][100];
int n,j;
cin >>n;
cout << "Please enter a number: " << endl;
for(int i=0;i<n;i++)
{ for (int j=i; j<n; j++)
{
cin>>arr[i][j];
}
}
cout << "Unsorted array:" << endl;
for (int i=0; i<n; i++)
{
for (int j=i; j<n; j++)
{
cout<<arr[i][j]<<"\t";
}
}
for (int i=0; i<=n; i++)
{
for (int j=i+1; j<=n-1; j++)
{
int temp;
if(arr[i]>arr[j])
{
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
return 0;
}
Use a std::vector<std::array<int,2>>for your base container. The dynamic growth capabilities of std::vector solves your stack space issue, and the std::array use gives you tied cell comparison. I.e. you can do this:
std::array<int, 2> ar1{1,2}, ar2{1,3};
if (ar1 < ar2) ...
and it will do the right thing. The result then boils down to effectively this:
#include <iostream>
#include <array>
#include <vector>
#include <utility>
int main()
{
std::vector< std::array<int,2> > v;
std::size_t n;
if (std::cin >> n && n > 0)
{
std::array<int,2> row;
while (n-- && std::cin >> row[0] && std::cin >> row[1])
v.emplace_back(row);
// bubblesort the content
std::size_t len = v.size();
while (len-- > 0)
{
bool swapped = false;
for (std::size_t i=0; i<len; ++i)
{
// std::array support multi-cell comparison.
if (v[i] < v[i+1])
{
// use library swap to swap entire row.
std::swap(v[i], v[i+1]);
swapped = true;
}
}
// early exit if no swaps happened on the last pass
if (!swapped)
break;
}
// report final output.
for (auto const& row : v)
std::cout << row[0] << ' ' << row[1] << '\n';
}
}
Input
8
41 11
34 4
69 4
78 6
62 8
5 5
81 3
5 10
Output
81 3
78 6
69 4
62 8
41 11
34 4
5 10
5 5

How to compare numbers from a stream if the same number repeats

I am trying to get the same numbers that repeat to be writen to a different stream
the function void lygink
void lygink (int s,int e,int n,int a , int m,info K[],int &sk)
{
a=0;
for (int i=1; i<=m; i++)
{
if(K[i].j==K[i].l) ;
else {
e=K[i].j;
s=K[i].j;
if (e==s) {
cout << e<< endl;
}
}
}
}
The whole code is as follows:
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
struct info
{
int jurg,lin,k;
};
void skaityk(int &n,int &m,int lin, int jurg, info K[])
{
{
ifstream fd ;
fd.open ("U2duom.txt");
fd >> n >> m;
for (int i=1; i<=n; i++)
{
fd>>K[i].lin ;
cout<<fixed<<setprecision(2)<<" " <<K[i].lin;
}
cout << " "<< endl;
for (int i=1; i<=m; i++)
{
fd>>K[i].jurg ;
cout<<fixed<<setprecision(2)<<" " <<K[i].jurg;
}
cout << " "<< endl;
fd.close();
}
}
void lygink (int s,int e,int n,int a , int m,info K[],int &k)
{
a=0;
for (int i=1; i<=m; i++)
{
if(K[i].jurg==K[i].lin) ;
else {
e=K[i].jurg;
s=K[i].jurg;
if (e==s) {
cout << e<< endl;
}
}
}
}
int main()
{
int n,e,m,a,lin,jurg,s,k;
s=22;
info K[500];
skaityk(n, m,lin, jurg, K);
lygink(s,e,n,a,m,K,k);
int i;
return 0;
}
and the file is
8 14
5 6 6 9 14 25 8 26
5 20 6 7 13 7 9 10 12 20 15 16 21 5
It should only give me 7 and 20 but it gives all that are not the same and I can't figure out how to extract those numbers I need to eliminate the numbers that do not repeat or somehow get the numbers that repeat
I would do the job somewhat differently. As a first attempt at things, I'd probably do something on this general order:
#include <iostream>
#include <set>
#include <sstream>
int main() {
std::istringstream input(R"(
8 14
5 6 6 9 14 25 8 26
5 20 6 7 13 7 9 10 12 20 15 16 21 5
)");
std::set<int> numbers;
int n;
while (input >> n)
if (!numbers.insert(n).second)
std::cout << n << "\n";
}
This produces more output than just 7 and 20, but hand inspection seems to confirm that everything it says is a duplicate actually is.
Use std::sort to sort the array and std::adjacent_find to find duplicates. A good programmer uses the available tools and doesn't reinvent the wheel every time.
std::unordered_set<int> unique(std::vector v) {
std::sort(std::begin(v), std::end(v));
auto it = std::adjacent_find(std::begin(v), std::end(v));
std::unordered_set<int> ret;
while (it != std::end(v)) {
ret.insert(*it);
std::advance(it, 2);
it = std::adjacent_find(it, std::end(v));
}
return ret;
}

Sorting arrays and in output getting extra first line of random symbols

I wrote a program where program sorts people by the each person time, and if time is the same, program sorts by the name alphabetically. Everything works fine, just I am getting extra first line full of random symbols. I of course can write if function and say not to show that first line, but is it good thing to do?
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
struct people {
string full_name;
int h;
int min;
int sec;
};
bool comp(const people &p1, const people &p2) {
return (p1.min < p2.min || p1.min == p2.min && p1.sec < p2.sec ||
p1.min == p2.min && p1.sec == p2.sec && p1.full_name < p2.full_name);
}
int main() {
int time;
string fullnamechange[30];
people peo[30];
cin >> time;
for (int i = 0; i < time; i++) {
getline(cin, peo[i].full_name); // taking everything into a string
fullnamechange[i] = peo[i].full_name;
fullnamechange[i].erase(fullnamechange[i].begin(),
fullnamechange[i].end() - 8);
peo[i].h = atoi(fullnamechange[i].c_str());
fullnamechange[i].erase(fullnamechange[i].begin(),
fullnamechange[i].end() -
5); // changing time in string to int
peo[i].min = atoi(fullnamechange[i].c_str());
fullnamechange[i].erase(fullnamechange[i].begin(),
fullnamechange[i].end() - 2);
peo[i].sec = atoi(fullnamechange[i].c_str());
}
for (int i = 0; i < time; i++) { // erasing time from string
peo[i].full_name.erase(peo[i].full_name.begin() + 20,
peo[i].full_name.end());
}
sort(peo, peo + time, comp);
cout << endl;
for (int i = 0; i < time; i++) {
cout << peo[i].full_name << " " << peo[i].min << " " << peo[i].sec << endl;
}
return 0;
}
/*
input for example:
6
Petras A. Petraitis 0 20 00
Jurgis Jurgutis 0 12 59
Romas Jonas 0 15 12
Zigmas Nosis 0 23 9
Rimas Senasis 0 15 12
output I get:
em3╣Mg n Ç 0 0 //random numbers I get
Jurgis Jurgutis 12 59
Rimas Senasis 15 12
Romas Jonas 15 12
Petras A. Petraitis 20 0
Zigmas Nosis 23 9 */

how to get max values from each string in a text file - C++

I have a text file like this;
1 13 330 323 18 1 40 410 413 45 1 28 381 347 16 1 16 230 261 27
2 6 208 218 8 2 24 253 277 21 2 13 223 244 14 2 10 177 185 6
3 0 12 1 1 3 20 417 416 18 3 23 322 320 23 3 5 21 23 4
4 1 7 18 2 4 11 149 138 11 4 11 120 116 10 4 2 27 24 3
and i want to take each string's maximum value. For example, in 1st string, i have 413 for highest number, for the 2nd i have 277. And i have 40 lines like this. I used this code but my code doesn't working properly - i knew i do it wrong btw- it takes all of the arrays and takes just only 1 highest value. I think i need two for loops for doing this but i already done first wrong and there in no 2nd one :) Maybe this can be done with "getline" function i really don't know but i need your help atm... Thanks.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <iomanip>
#include <fstream>
#include <string.h>
using std::cin;
using std::endl;
using std::cout;
using namespace std;
int main()
{
int a[20][40];
int x,y;
int sum = 0;
FILE *myDataFile1;
ofstream myOutFile1;
myOutFile1.open ("highestValues.txt");
myDataFile1 = fopen("input.txt", "r");
for ( x = 0; x < 20; x++)
{
for ( y = 0; y < 40; y++)
{
a[x][y] = 0;
}
}
for (x = 0; x < 20; x++)
{
for ( y = 0; y < 40; y++)
{
fscanf(myDataFile1, "%d,", &a[x][y] );
}
}
for (x = 0; x < 20; x++)
{
for ( y = 0; y < 40; y++)
{
sum = a[x][y];
}
}
int maxValue = 0;
for(x = 1; x < 20; x++)
{
for(y = 1; y < 40; y++)
{
if(a[x][y] > maxValue)
{
maxValue = a[x][y];
}
}
}
if (myOutFile1.is_open())
{
myOutFile1 << left << setw (5) << maxValue << endl;
}
cout << "The highest value is: " << maxValue << endl;
}
}
One possible solution:
std::fstream fs("test.txt");
std::string line;
while(std::getline(fs, line)) {
std::stringstream str(line);
std::istream_iterator<int> begin(str), end;
std::vector<int> vec(begin, end)
std::cout << *std::max_element(vec.begin(), vec.end()) << std::endl;
}
[edit]
Your code is more C - like, C++ version (as you have tagged your question) looks as above code.
headers you can find on http://en.cppreference.com/w/, to make this answer complete I add them below:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <fstream>
Here is a Live Example
It looks like your main problem is in reading the file. I suggest starting with a framework like this instead of hardcoding the numbers 20 and 40.
#include <fstream>
#include <sstream>
#include <iostream>
int main (void)
{
std::ifstream infile("input.txt");
std::string line;
while (std::getline(infile, line)) // std::getline returns infile, which evaluates to false at the end of the file.
{
std::cout << "\nNew Line.\n";
std::istringstream iss(line); // Turn the line into its own stream
int a;
while (iss >> a) // iss evaluates to false at the end of the stream
{
std::cout << a << " ";
// You can find the max element here.
// Exercise left for the reader.
}
}
return 0;
}
Read file line by line was very helpful in making this answer, I suggest giving it a read too.
You made a matrix of 20X40, so I presume you already know the number of numbers in one line. What you are doing wrong is your matrix size and indexing. Your input has 40 lines,so rows = 40, and 20 integers in a line, so 20 columns.
Now your matrix looks like:
int a[40][20];
Now just read integers in the matrix using for loop and fscanf or ifstream.
Here is your new code:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <iomanip>
#include <fstream>
#include <string.h>
using std::cin;
using std::endl;
using std::cout;
using namespace std;
int main()
{
int a[40][20];
int x,y;
int sum = 0;
FILE *myDataFile1;
ofstream myOutFile1;
myOutFile1.open ("highestValues.txt",ios::out);
myDataFile1 = fopen("input.txt", "r");
for ( x = 0; x < 40; x++)
for ( y = 0; y < 20; y++)
fscanf(myDataFile1,"%d ",&a[x][y]); //removed the comma, since your integers are not comma saperated
for (x = 0; x < 40; x++)
{
int maximum = a[x][0];
for ( y = 0; y < 20; y++)
maximum = max(maximum,a[x][y]);
myOutFile1 << "Maximum for line "<<x<<": "<<maximum << endl;
}
fclose(myDataFile1);
myOutFile1.close();
return 0;
}
Firstly, decide if you want to use C++ or C in your code. Don't mix both, it just looks ugly.
ifstream is for input. ofstream is for output. ">>" and "<<" operators do work for them as well and that's why C++ is comfortable.
I suppose each line has 20 integers right ? So what you have to do is to make 3 loops for the 3 lines and add each integer into an array[n] where 0<=n<=3 is the line. In code :
ifstream input;
int max[3] /*Because you have 3 lines in your quote*/, a;
input.open(...);
/* don't forget max[n] iniliazation */
for (int i = 0; i < 3; i++)
for (int j = 0; j < 20; j++)
input >> a;
max[i] = max[i] < a ? a : max[i];
And there you have for each line the maximum value