How to change this code? - c++

#include <iostream>
#include <string.h> // for strlen
#include <stdlib.h> // for atoi
#include <sstream>
void expand_combinations(const char *remaining_string, std::ostringstream& i, int remain_depth)
{
if(remain_depth==0)
{
std::cout << i.str() << std::endl;
return;
}
for(int k=0; k < strlen(remaining_string); ++k)
{
std::ostringstream l;
l << i.str();
l << remaining_string[k];
expand_combinations(remaining_string+k+1, l, remain_depth - 1);
}
return;
}
int main(int argc, char **argv)
{
std::ostringstream i;
if(argc<3) return 1;
expand_combinations(argv[1], i, atoi(argv[2]));
return 0;
}
How can this code be changed so that it doesn't use ostringstream?

The following is your code with string in place of ostringstream. Normally I'd refactor the code but since your question was pretty specific I'll leave it alone.
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
void expand_combinations(const char *remaining_string, string const & s, int remain_depth)
{
if(remain_depth==0)
{
std::cout << s << std::endl;
return;
}
for(int k=0; k < strlen(remaining_string); ++k)
{
string str(s);
str.append(1, remaining_string[k]);
expand_combinations(remaining_string+k+1, str, remain_depth - 1);
}
return;
}
int main(int argc, char **argv)
{
if(argc<3) return 1;
expand_combinations(argv[1], "", atoi(argv[2]));
return 0;
}

Related

Identify Memory Corruption

I'm having trouble identifying a possible source of memory corruption in the following code. Is it due to the fact that I don't call the free() function on char *stringToAdd?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <iostream>
using namespace std;
#define MAX 1024
char* add_strings(char *stringOne, char *stringTwo);
int main() {
char s = 'x';
char *stringOne = &s;
char *stringTwo = new char[1025]();
char *final = add_strings(stringOne, stringTwo);
return 0;
}
char* add_strings(char *stringOne, char *stringTwo) {
unsigned int lengthOfStringOne = strlen(stringOne);
unsigned int lengthOfStringTwo = strlen(stringTwo);
cout << lengthOfStringOne << endl;
cout << lengthOfStringTwo << endl;
char *stringToAdd = lengthOfStringOne < lengthOfStringTwo ? stringOne : stringTwo;
unsigned int lengthOfAdd = lengthOfStringOne < lengthOfStringTwo ? lengthOfStringOne : lengthOfStringTwo;
char *final = static_cast<char*>(calloc(MAX, sizeof(char)));
unsigned int avgLengthOfStrings = (lengthOfStringOne + lengthOfStringTwo) / 2;
if (avgLengthOfStrings < MAX) {
strncat(final, stringToAdd, lengthOfAdd);
printf("DONE\n");
} else {
printf("Average length of both input strings exceeds liimit.\n");
free(final);
return NULL;
}
return final;
}

2 dimensional array of TCHAR

I try to create 2 matrices: 1 of char* and 1 of THAR*. But for TCHAR* matrix instead of strings I get addresses of some kind. What's wrong?
Code:
#include <tchar.h>
#include <iostream>
using namespace std;
int main(int argc, _TCHAR* argv[])
{
//char
const char* items1[2][2] = {
{"one", "two"},
{"three", "four"},
};
for (size_t i = 0; i < 2; ++i)
{
cout << items1[i][0] << "," << items1[i][1] <<endl;
}
/*
Correct output:
one,two
three,four
*/
//TCHAR attempt
const TCHAR* items2[2][2] = {
{_T("one"), _T("two")},
{_T("three"), _T("four")},
};
for (size_t i = 0; i < 2; ++i)
{
cout << items2[i][0] << "," << items2[i][1] <<endl;
}
/*
Incorrect output:
0046AB14,0046AB1C
0046AB50,0046D8B0
*/
return 0;
}
To fix the issue we need to use wcout for Unicode strings. Using How to cout the std::basic_string<TCHAR> we can create flexible tcout:
#include <tchar.h>
#include <iostream>
using namespace std;
#ifdef UNICODE
wostream& tcout = wcout;
#else
ostream& tcout = cout;
#endif // UNICODE
int main(int argc, _TCHAR* argv[])
{
//char
const char* items1[2][2] = {
{"one", "two"},
{"three", "four"},
};
for (size_t i = 0; i < 2; ++i)
{
tcout << items1[i][0] << "," << items1[i][1] <<endl;
}
/*
Correct output:
one,two
three,four
*/
//TCHAR attempt
const TCHAR* items2[2][2] = {
{_T("one"), _T("two")},
{_T("three"), _T("four")},
};
for (size_t i = 0; i < 2; ++i)
{
tcout << items2[i][0] << "," << items2[i][1] <<endl;
}
/*
Correct output:
one,two
three,four
*/
return 0;
}

Segmentation fault (core dumped), storing char * to string vector of struct

#include <iostream>
#include <fstream>
#include <string.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <vector>
#include <sstream>
#define SHMSIZE 1024
using namespace std;
namespace patch
{
template < typename T > std::string to_string( const T& n )
{
std::ostringstream stm ;
stm << n ;
return stm.str() ;
}
}
struct process
{
int r;
string name;
vector<string> lines;
};
int main(int argc, char * argv[])
{
int firstRun = 1; //Skipping First Line of Assign-1.ip.
int quantum = 0; //For taking input of quantum.
int count = 0; //For number of processes.
int pchtoint;
string c;
char * pch; //For tokenization.
string reading_file; //Reading a line from file.
char * readarr; //Converting "reading_file" to readarr for tokenization.
process * p;
//=== Quantum Input ===//
cout<<"Enter Quantum size [1-1000]: ";
cin>>quantum;
while(quantum < 1 || quantum > 1000)
{
cout<<"Wrong input!!! Enter Again [1-1000]: ";
cin>>quantum;
}
//=====================//
//===Filing===//
ifstream read("Assign-2.ip");
if(read.is_open())
{
while(!read.eof())
{
getline(read, reading_file);
readarr = new char[reading_file.size() + 1];
for(int i = 0; i < reading_file.length(); i++)
{
readarr[i] = reading_file[i];
}
if(firstRun > 1)
{
int countingline = 0; //counting the number of lines in a process.
pch = strtok (readarr," ,");
while (pch != NULL)
{
c = pch[1];
pchtoint = atoi(c.c_str());
p[pchtoint-1].r++;
p[pchtoint-1].lines.push_back(pch);
for(int i = 0; i < p[pchtoint-1].lines.size(); i++)
cout<<p[pchtoint-1].name<<"=="<<p[pchtoint-1].lines.at(i)<<endl;
pch = strtok (NULL, " ,");
}
}
else
{
pch = strtok (readarr,",.-");
while (pch != NULL)
{
count++;
pch = strtok (NULL, ",.-");
}
p = new process[count];
string s = "p";
for(int i = 0; i < count; i++)
{
s = s + patch::to_string(i+1);
p[i].name = s;
s = s[0];
}
firstRun++;
}
}
}
else
{
cout<<"Cannot open file!!!"<<endl;
}
read.close();
return 0;
}
Enter Quantum size [1-1000]: 2
p1==p1-l1
p2==p2-l1
p3==p3-l1
p1==p1-l1
p1==p1-l2
p2==p2-l1
p2==p2-l2
p3==p3-l1
p3==p3-l2
p1==p1-l1
p1==p1-l2
p1==p1-l3
p3==p3-l1
p3==p3-l2
p3==p3-l3
p1==p1-l1
p1==p1-l2
p1==p1-l3
p1==p1-l4
Segmentation fault (core dumped)
I am reading data from a cvs file. and storing it in struct that is p here. but I don't know why it is giving segmentation fault. I am compiling it on ubuntu terminal.
The input file contains data:
P1, P2, P3,
p1-l1, p2-l1, p3-l1
p1-l2, p2-l2, p3-l2
p1-l3, , p3-l3
p1-l4, ,

How to cut the content of a string till a particular string or position?

After all my research, I am here to cut this string :
{[(2015/11/30|01:07:53.357|-1227639088|DefaultThread|./src/Myprogram.cpp:564|int main(int, argv**))]} Server Starting....
to string:
./src/Myprogram.cpp:564|int main(int, argv**))]} Server Starting....
Below is my code:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
void func(std::ostream&obj){
std::string dbgmsg = dynamic_cast<std::ostringstream&>(obj).str();
cout << dbgmsg; //I need to convert this string to ./src/Myprogram.cpp:564|int main(int, argv**))]} Server Starting....
}
int main() {
std::ostringstream ss;
ss <<"{[(2015/11/30|01:07:53.357|-1227639088|DefaultThread|./src/Myprogram.cpp:564|int main(int, argv**))]} Server Starting....";
func(ss);
return 0;
}
My GCC: gcc version 4.5.3 (GCC)
You can use find to find the 4th occurence of | and then substring
void func(std::ostream&obj){
std::string dbgmsg = dynamic_cast<std::ostringstream&>(obj).str();
int occurrences = 0;
int start = 0;
while (occurrences !=4 && (start = dbgmsg.find("|", start)) != string::npos) {
++occurrences;
++start;
}
if (start != string::npos)
{
cout << dbgmsg.substr (start);
}
}
At last I found the solution :) here is it:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
void func(std::ostream&obj){
std::string dbgmsg = dynamic_cast<std::ostringstream&>(obj).str();
std::size_t pos = dbgmsg.find("./");
std::string str3 = dbgmsg.substr (pos);
cout << str3; //now o/p : ./src/Myprogram.cpp:564|int main(int, argv**))]} Server Starting....
}
int main() {
std::ostringstream ss;
ss <<"{[(2015/11/30|01:07:53.357|-1227639088|DefaultThread||./src/Myprogram.cpp:564|int main(int, argv**))]} Server Starting....";
func(ss);
return 0;
}
A bit late to the party but here's my solution
#include <iostream>
#include <string>
std::string getString(std::string fullString){
int pos = 0;
for(int i = 0; i < 4; i++){
pos = fullString.find("|", pos+1);
}
return fullString.substr(pos+1);
}
int main( void ){
std::string str("{[(2015/11/30|01:07:53.357|-1227639088|DefaultThread|./src/Myprogram.cpp:564|int main(int, argv**))]} Server Starting....");
std::cout << getString(str) << std::endl;
return 0;
}

What's the correct way to add a character array to a constant character array in C++?

What's the correct way to add a character array to a constant character array in C++?
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
int pathSize = 0;
char* pathEnd = &argv[0][0];
while(argv[0][pathSize] != '\0') {
if(argv[0][pathSize++] == '/')
pathEnd = &argv[0][0] + pathSize;
}
pathSize = pathEnd - &argv[0][0];
char *path = new char[pathSize];
for(int i = 0; i < pathSize; i++)
path[i] = argv[0][i];
cout << "Documents Path: " << path + "docs/" << endl; // Line Of Interest
delete[] path;
return 0;
}
This code outputs:
Documents Path: �\
Using 'path' instead of '*path' will give me the compile error:
invalid operands of types ‘char*’ and ‘const char [6]’ to binary ‘operator+’
May I suggest using C++ to begin with, and (Boost) Filesystem for maximum benefits:
#include <iostream>
#include <boost/filesystem.hpp>
using namespace std;
using namespace boost::filesystem;
int main(int argc, const char *argv[])
{
const std::vector<std::string> args { argv, argv+argc };
path program(args.front());
program = canonical(program);
std::cout << (program.parent_path() / "docs").native();
}
This will use the platform's path separator, know how to translate 'funny' paths (e.g. containing ..\..\, or UNC paths).
Something like this should do it (totally untested):
const char* end = strrchr(argv[0], '/');
std::string docpath = end ? std::string(argv[0], end) : std::string(".");
docpath += '/docs/';
Your way:
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
int pathSize = 0;
char* pathEnd = &argv[0][0];
while(argv[0][pathSize] != '\0') {
if(argv[0][pathSize++] == '/')
pathEnd = &argv[0][0] + pathSize;
}
pathSize = pathEnd - &argv[0][0];
char *path = new char[pathSize + 5]; //make room for "docs/"
for(int i = 0; i < pathSize; i++)
path[i] = argv[0][i];
char append[] = "docs/";
for(int i = 0; i < 5; i++)
path[pathSize+i] = append[i];
cout << "Documents Path: " << path << endl;
function_expecting_charptr(path);
delete[] path;
return 0;
}
Sane C way:
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
char* pathEnd = strrchr(argv[0], '/');
if (pathEnd == NULL)
pathEnd = argv[0];
int pathSize = (pathEnd-argv[0]) + 5; //room for "docs/"
char *path = new char[pathSize];
if (pathSize)
strncpy(path, argv[0], pathSize+1);
strcat(path, "docs/");
cout << "Documents Path: " << path << endl;
function_expecting_charptr(path);
delete[] path;
return 0;
}
C++ way:
#include <iostream>
#include <string>
int main(int argc, char** argv) {
std::string path = argv[0];
size_t sep = path.find('/');
if (sep != std::string::npos)
path.erase(sep+1);
else
path.clear();
path += "docs/";
std::cout << "Documents Path: " << path << endl;
function_expecting_charptr(path.c_str());
return 0;
}
Note that argv[0] holds an implementation defined value, and especially in *nix environments isn't guaranteed to hold anything useful. The first parameter passed to the program is found in argv[1].
I combined some of your guys' ideas into this compact code:
#include <iostream>
#include <cstring>
using namespace std;
int main(int argc, char** argv) {
const string path_this = argv[0];
const string path = path_this.substr(0, strrchr(argv[0], '/') - argv[0] +1);
const string path_docs = path + "docs/";
cout << "Documents Path: " << path_docs << endl;
return 0;
}
To get the character array from this I can then run 'path_docs.c_str()'.
Credits: #MooingDuck, #MarkB, Google.