C++ combine two files output - c++

I am new to C/C++ .I have 2 text files and need to combine two files contents
I executed like this g++ merge.cc -o merge and created two text files with content like this:
file1 : 1 3 5 7
file2 : 2 4 6 8
then excuted this command : ./merge 10 t1.txt t2.txt
Out came : 1 2 3 4 5 6 7 81 2 3 4 5 6 7 8
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
void combine(char s[], char t[], char result[]);
int main(int argc, char* argv[])
{
const int MAX = 20;
char inBuffer1[MAX];
char inBuffer2[MAX];
char outBuffer[MAX*2];
int max = atoi(argv[1]);
ifstream file1(argv[2]);
ifstream file2(argv[3]);
file1.getline(inBuffer1,max);
file2.getline(inBuffer2,max);
combine (inBuffer1, inBuffer2, outBuffer);
cout << outBuffer << endl;
}
void combine(char s[], char t[], char result[])
{
int i, j, k;
for (i = j = k = 0; s[i] && t[j]; k++)
{
if (s[i] <= t[j])
result[k] = s[i++];
else
result[k] = t[j++];
cout << result[k];
}
//tidy up
for (; s[i]; )
{
result[k] = s[i++];
cout << result[k++];
}
for (; t[j]; )
{
result[k] = t[j++];
cout << result[k++];
}
result[k] = 0;
}
Could you please anyone explain about this. I thave to sort files and reserve output using -c, -r commands
Thanks in advance

The c++ standard library has std::merge to do exactly what you seem to want here. Basically open the files, then do the merge from a couple of istream_iterators to an ostream_iterator.

Try the following C-program example (without combine function):
#include <stdio.h>
#include <stdlib.h>
// compare function to sort int values
int comparator(const void *p, const void *q)
{
int l = *(int*)p;
int r = *(int*)q;
return (l - r);
}
int main(int argc, char* argv[])
{
const int MAX = 20;
int buffer[MAX*2];
int cnt = 0; // numbers in buffer
// check arguments
if( argc < 3)
{
printf("Provide correct arguments: one number and two files with numbers\n");
return 1;
}
// reading from 2 files in series
FILE * f;
for(int i = 2; i <= 3; i++)
{
f = fopen(argv[i], "r");
if( f == NULL )
{
printf("File %s cannot be read!\n", argv[2]);
break;
}
while( !feof(f) && cnt < MAX*2 ) // while file is not finished and array is not full
{
if( fscanf(f, "%d", &buffer[cnt]) ) // read data
cnt++; // and if reading is successful count
}
fclose(f);
}
// sort the resulting array (instead of combine function)
qsort(buffer, cnt , sizeof(int), comparator);
// printing results
for( int i = 0; i < cnt; i++)
{
printf("%d ", buffer[i]);
}
}
This example is for cases when initial files can consist not ordered values, so all values from both files are read to memory and then sorted by standard function from stdlib.h (to use that qsort we need function comparator, read more in the references).
But for case when both input files are already arranged (sorted) program can be simpler, but you need open both files and compare values while reading to output the smallest value from two "current", and you do not need buffer array for that case (it is just a tip, try to write a program yourself).
EDIT:
It is C++ example with merge and sort from <algorithm>:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
int data; // buffer to read one value from file
ifstream file1(argv[1]);
ifstream file2(argv[2]);
vector<int> v1, v2; // vectors to store data
// reading initial data to vectors
while( !file1.eof() )
{
file1 >> data;
v1.push_back(data);
}
file1.close();
while( !file2.eof() )
{
file2 >> data;
v2.push_back(data);
}
file2.close();
// sorting (essential if files are not sorted)
sort(v1.begin(), v1.end(), less <int>());
sort(v2.begin(), v2.end(), less <int>());
// marging
vector<int> res(v1.size() + v2.size()); // vector to store result
merge(v1.begin(), v1.end(), v2.begin(), v2.end(), res.begin(), less <int>());
// printing result
for(vector<int>::iterator i = res.begin(); i != res.end(); i++)
{
cout << *i << " ";
}
}
NOTE: In this example you do not need to ask user about size of data sequence, so argv[1] is name of the first file, and argv[2] is name of the second one (add appropriate check by yourself).

The following C++ example shows usage of istream_iterator and ostream_iterator with merge method:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
using namespace std;
int main(int argc, char* argv[])
{
// open input files
ifstream file1(argv[1]);
ifstream file2(argv[2]);
// link input streams with files
istream_iterator<int> it1(file1);
istream_iterator<int> it2(file2);
istream_iterator<int> eos; // end-of-stream iterator
// link output stream to standard output
ostream_iterator<int> oit (cout," "); // " " = usage of space as separator
// marging to output stream
merge(it1, eos, it2, eos, oit);
file1.close();
file2.close();
return 0;
}

Related

std::cin string to int array with variable length input

I have a task where i need to revert a list of variable length numbers. This could be "1 2 3" or "5 6 7 8 9 10".
The sorting itself works fine.
But I can't figure out how to read the user input (with variable length) and then only execute the reverseSort once.
How can I read the user input into an array where each index is based on the space between the numbers?
Here is my code:
#include <iostream>
#include <string>
using namespace std;
bool sorted = true;
int temp;
int * arr;
int arrLength = 5;
int arrs;
// int arr = {1,2,3,4,5};
void reverseSort(int arr[], int n){
sorted = true;
for (int i = 0; i < n-1; i++){
if (arr[(i + 1)] > arr[i]){
temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
sorted = false;
}
}
if (!sorted){
reverseSort(arr,n);
}
}
int main(void){
// get user input !?!?!?!?!
cin >> arrs;
cout << arrs;
reverseSort(arr,arrLength);
for (int i = 0; i < arrLength; i++){
std::cout << arr[i] << " ";
}
return 0;
}
If you don't know number of inputs you need struct that can be resized. std::vector is good for it. For adding new data you can use member function push_back.
You can read the input line as std::string (by std::getline) and you can open new stream with read data (std::istringstream). Further one can read values from new stream.
And I think you can use std::sort instead of reverseSort (but for 'reverse' you need use std::greater as comparator).
#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <algorithm>
int main(void){
std::vector<int> arrs;
// read only one line
std::string input;
std::getline(std::cin, input);
std::istringstream row(input);
int x;
while (row >> x)
{
arrs.push_back(x);
}
//like your reverseSort
std::sort(arrs.begin(), arrs.end(), std::greater<int>{});
for (auto var : arrs) {
std::cout << var << "; ";
}
return 0;
}

how to save string in longest common subsequence recursive algorithm

I'm trying to implement a naive approach of the longest common subsequence algorithm. I'm using a recursive approach, passing two strings into the function lcs. I successfully counted the number of characters in the longest subsequence.
My problem is printing the characters of the lcs. I thought I could do this by storing matched characters in a string called sub and passing it as a parameter. However, I'm stuck on how to save the string. I've always struggled with recursion, and would appreciate any tips on approaching this problem the right way.
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
int lcs(string a, string b,string sub){
int aLen = a.length();
int bLen = b.length();
if (aLen==0 || bLen==0){
return 0;
}
if(a.at(aLen-1)==b.at(bLen-1)){
return 1+lcs(a.substr(0,aLen-1),b.substr(0,bLen-1),a.at(aLen-1)+sub); // add letter to subsequence
}
else {
return max(lcs(a.substr(0,aLen-1),b.substr(0,bLen),sub),lcs(a.substr(0,aLen),b.substr(0,bLen-1),sub));
}
}
int main(int argc, const char * argv[])
{
char sub[]="";
int charsInLCS = lcs("sdmc","msdc",sub); //i want to output "sdc"
cout << charsInLCS << endl;
return 0;
}
Be careful, your base case is wrong as you never check a[0] against b[0]. Also, passing string copies is very expensive, much faster to pass just the indexes and work with that. We need to keep track of what characters we matched when a[idxa] == b[idxb]. Here is a solution using vectors:
#include <iostream>
#include <string>
#include <queue>
#include <math.h>
#include <algorithm> // std::reverse
using namespace std;
string s1, s2;
int lcs(int idx1, int idx2, vector<char> &v){
if (idx1 == -1 || idx2 == -1){
return 0;
}
if (s1[idx1] == s2[idx2]) {
v.push_back(s1[idx1]); // record that we used this char
return 1 + lcs(idx1 - 1, idx2 - 1, v);
} else {
vector<char> v1, v2;
int p1 = lcs(idx1 - 1, idx2, v1);
int p2 = lcs(idx1, idx2 - 1, v2);
if (p1 > p2) { // we used the chars we already had in v + the ones in v1
v.insert(v.end(), v1.begin(), v1.end());
return p1;
} else { // we used the chars we already had in v + the ones in v2
v.insert(v.end(), v2.begin(), v2.end());
return p2;
}
}
}
int main(int argc, const char * argv[])
{
s1 = "sdmc";
s2 = "msdc";
vector<char> v; // chars we used
int sol = lcs(s1.length() - 1, s2.length() - 1, v); //i want to output "sdc"
cout << sol << " ";
reverse(v.begin(), v.end());
for (auto num : v) {
cout << num;
}
return 0;
}

Sort command line args in C++

I wanna sort an array of command line arguments. All arguments are integer.
Here is my code, but it does not work.
#include <iostream>
using namespace std;
int main (int argc, char *argv[]) {
for (int i=0; i<argc-1; ++i) {
int pos = i;
for (int j=i+1; j<argc; ++j) {
if (argv[j] - '0' < argv[pos] - '0') {
pos = j;
}
}
char *tempt = argv[i];
argv[i] = argv[pos];
argv[pos] = tempt;
}
for (int i=0; i<argc; ++i) {
cout << argv[i] <<endl;
}
}
After compiling, when I called ./a.out 4 3 2 1, it still printed 4 3 2 1 to the screen instead of 1 2 3 4.
What's wrong?
Thanks in advance.
Try std::sort from <algorithm> with a custom comparator
std::sort(argv, argv + argc, [](char * const & a, char * const & b) {
return atoi(a) < atoi(b);
});
In modern c++ you can use auto types for lambdas. For string to int convertion I would prefer stoi function over atoi (you can look for differences here). Also worth noting that first argument (argv[0]) is a program name, e.g. ./a.out, so you need to skip it from sorting. Final result could be looks like this:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
int main (int argc, char *argv[]) {
std::sort(argv + 1, argv + argc, [](auto l, auto r){ return std::stoi(l) < std::stoi(r); } );
std::copy(argv + 1, argv + argc, std::ostream_iterator<const char*>(std::cout, " "));
}
If all of command line arguments a unsigned number with fixed digits count you could also sort them like string, i.e. without explicit converting to numbers via std::stoi. In this case std::vector<std::string> could be used:
std::vector<std::string> v(argv + 1, argv + argc);
std::sort(v.begin(), v.end());
There is no need to use lambda or another custom comparator for std::sort.

Traverse file vertically

I need to traverse a file in a vertical manner. If suppose the file contents are:
adg
beh
cfi
It should print the file as:
abc
def
ghi
The length for each line will be same(i.e. all lines will be of length 3 for above example). I have written a code but it doesn't traverse the file as required.
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main()
{
fstream fs;
fs.open("asd.txt",ios::in);
string str;
char *ch = new char();
int lineLen = 0, k = 0;
if(getline(fs,str))
{
lineLen = str.length();
}
fs.seekg(0);
if(lineLen > 0)
{
for(int i = 0;i<lineLen;i++)
{
fs.seekg(i+k*lineLen);
while(fs.read(ch,1))
{
k++;
fs.seekg(i+k*lineLen);
cout<<*ch;
}
k = 0;
}
}
fs.close();
cin.ignore();
}
I am a bit new to file handling and couldn't find the mistake. Also, is there a better approach for this to be followed?
Pretty much your way with some little tweaks
//lines = no. of lines in file
fs.seekg(0, fs.beg);
fs.clear();
if(lineLen > 0)
{
for(int k = 0; k < lineLen; k++) {
for(int i = 0;i<lines;i++){
fs.seekg(k+i * (lineLen + 2), fs.beg); //use lines + 2
if(fs.read (ch,1));
cout << *ch;
}
cout << endl;
}
Untested pseudo-code that may give you some ideas. Basically, load the whole file into a 2d vector of characters for easy access. It will use more memory than reading directly from the file but this won't matter unless the file is very big.
vector<vector<char>> filemap;
string line;
while (getline(filestream, line))
{
filemap.push_back(vector<char>(line.begin(), line.end()));
}
for (int x = 0; x < XSIZE; x++)
{
for (int y = 0; y < YSIZE; y++)
{
filestream << filemap[y][x]; // note x/y are opposite way round in 2d vectors
}
filestream << '\n';
}
You might find this task much simpler if you were to use mmap(2). There may be a C++ equivalent or wrapper, but I'm afraid I'm not much of an expert on that front. Hopefully someone will come along with a better answer if that's the case.
Here's a quick C (not ++) example. I'll see if I can google around and C++ify it some more:
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
int main(void)
{
int fd = open("input", O_RDONLY);
struct stat s;
fstat(fd, &s);
// map the file as one big string
char *c = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
// calculate sizes
int columns = strchr(c, '\n') - c; // first newline delimits a row
int stride = columns + 1; // count the newline!
int rows = s.st_size / stride; // all rows are the same length
for (int x = 0; x < columns; x++)
{
for (int y = 0; y < rows; y++)
{
putchar(c[y*stride + x]);
}
putchar('\n');
}
munmap(c, s.st_size);
close(fd);
return 0;
}
Edit: A quick search around didn't turn up a much better way to handle this in C++ as far as I could tell. I mean, I can add a typecast on the mmap line and change the putchar calls to std::cout, but that doesn't really seem like it makes any difference.
Instead of trying to seek() repeatedly in the source file it is much easier and faster to simply read in the whole source file then generate output from the in-memory contents.
This sounds an awful like like a class assignment, so I won't simply write the answer for you. However this should point you in the right way -- Some PseodoCode is included
To avoid pain, it should presumably be safe to assume some upper bound on line length and max lines, i.e.,
const int MaxLines = 100;
const int MaxLength = 80;
int lineno, linelength;
// array of char pointers for each line
char *lines[] = (*lines[])malloc(Maxlines * sizeof(char*));
// ReadLoop
lineno = 0;
while (not eof)
{
getline(buffer);
if (++lineno++ == 1)
{
linelength = strlen(buffer);
}
else
{
if (linelength != strlen(buffer))
{
cout "Line # " << lineno << " does not match the expected length";
exit();
}
}
lines[lineno] = malloc(strlen(buffer)+1));
strcpy(lines[lineno], buffer);
}
int cc, linecnt = lineno;
// now all data in memory, output "vertical data"
for (cc = 0; cc < linelength; ++cc)
{
for (lineno=0; lineno<<linelength; ++lineno)
{
cout << lines[xx][yy]; // xx && yy left you to figure out
}
cout "\n";
}
Provided that your file is not enormous, there's no reason not to just slurp the whole thing into memory. There may be a more idiomatic way to do this in C++, but the following works:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
int main(int argc, char *argv[])
{
std::fstream infile("foo.txt");
std::vector<std::string> lines;
std::string line;
while(std::getline(infile,line)) {
lines.push_back(line);
}
int m=lines.size();
int n=lines[0].length();
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
std::cout << lines[j].at(i);
}
std::cout << std::endl;
}
return 0;
}
Problems arise when all the lines in the file are not the same length, of course.
And now, a version that “doesn't use any extra memory” (of course, it does, but not much):
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>
int main(int argc, char *argv[])
{
std::fstream infile("foo.txt");
std::vector<std::string> lines;
std::string line;
std::getline(infile, line);
int n = line.length();
int m = 1+std::count(std::istreambuf_iterator<char>(infile),
std::istreambuf_iterator<char>(), '\n');
infile.clear();
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
infile.seekg(j*m+i);
std::cout << char(infile.peek());
}
std::cout << std::endl;
}
return 0;
}

Algorithm to generate all permutation by selecting some or all charaters

I need to generate all permutation of a string with selecting some of the elements. Like if my string is "abc" output would be { a,b,c,ab,ba,ac,ca,bc,cb,abc,acb,bac,bca,cab,cba }.
I thought a basic algorithm in which I generate all possible combination of "abc" which are {a,b,c,ab,ac,bc,abc} and then permute all of them.
So is there any efficient permutation algorithm by which I can generate all possible permutation with varying size.
The code I wrote for this is :
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <map>
using namespace std;
int permuteCount = 1;
int compare (const void * a, const void * b)
{
return ( *(char*)a - *(char*)b);
}
void permute(char *str, int start, int end)
{
// cout<<"before sort : "<<str;
// cout<<"after sort : "<<str;
do
{
cout<<permuteCount<<")"<<str<<endl;
permuteCount++;
}while( next_permutation(str+start,str+end) );
}
void generateAllCombinations( char* str)
{
int n, k, i, j, c;
n = strlen(str);
map<string,int> combinationMap;
for( k =1; k<=n; k++)
{
char tempStr[20];
int index =0;
for (i=0; i<(1<<n); i++) {
index =0;
for (j=0,c=0; j<32; j++) if (i & (1<<j)) c++;
if (c == k) {
for (j=0;j<32; j++)
if (i & (1<<j))
tempStr[ index++] = str[j];
tempStr[index] = '\0';
qsort (tempStr, index, sizeof(char), compare);
if( combinationMap.find(tempStr) == combinationMap.end() )
{
// cout<<"comb : "<<tempStr<<endl;
//cout<<"unique comb : \n";
combinationMap[tempStr] = 1;
permute(tempStr,0,k);
} /*
else
{
cout<<"duplicated comb : "<<tempStr<<endl;
}*/
}
}
}
}
int main () {
char str[20];
cin>>str;
generateAllCombinations(str);
cin>>str;
}
I need to use a hash for avoiding same combination, so please let me know how can I make this algorithm better.
Thanks,
GG
#include <algorithm>
#include <iostream>
#include <string>
int main() {
using namespace std;
string s = "abc";
do {
cout << s << '\n';
} while (next_permutation(s.begin(), s.end()));
return 0;
}
Next_permutation uses a constant size, but you can add a loop to deal with varying size. Or just store in a set to eliminate the extra dupes for you:
#include <set>
int main() {
using namespace std;
string s = "abc";
set<string> results;
do {
for (int n = 1; n <= s.size(); ++n) {
results.insert(s.substr(0, n));
}
} while (next_permutation(s.begin(), s.end()));
for (set<string>::const_iterator x = results.begin(); x != results.end(); ++x) {
cout << *x << '\n';
}
return 0;
}
I don't think you can write much faster program than you have already. The main problem is the output size: it has order of n!*2^n (number of subsets * average number of permutations for one subset), which is already > 10^9 for a string of 10 different characters.
Since STL's next_permutation adds very limited complexity for such small strings, your program's time complexity is already nearly O(output size).
But you can make your program a bit simpler. In particular, for( k =1; k<=n; k++) loop seems unnecessary: you already calculate size of subset in variable c inside. So, just have int k = c instead of if (c == k). (You'll also need to consider case of empty subset: i == 0)
edit
Actually, there's only 9864100 outputs for n == 10 (not ~ 10^9). Still, my point remains the same: your program already wastes only "O(next_permutation)" time for each output, which is very, very little.