I am trying to send array of char from one process to another using pipe, the characters are passing but not all of them! only the part of the beginning.
This is my code:
int p1[2], p2[2];
int main()
{
pipe(p1);
int f1= fork();
if(f1 == 0)
{
char ar[100];
int n = 38;
for(int i=0;i<n;i++)
{ ar[i] = 'f'; }
close(p1[0]); //close the read
write(p1[1],ar,n+1);
} else if (f1 > 0)
{
wait(NULL);
int f2 = fork();
if(f2 == 0)
{
char arr2[100];
close(p1[1]); //close the write
int m = read(p1[0],arr2,strlen(arr2));
cout << arr2 << " " << m << endl;
}
else if (f2 > 0)
{wait(NULL);}
}
return 0;
}
You invoke std::strlen() on an uninitialized char array, which is your mistake. std::strlen() looks for the first occurence of a null byte in the array and returns its position. But the array is uninitialized, thus making the first occurence of the null byte undefined.
Besides, you should check the return values of the library functions (pipe(), read(), write(), fork(), etc.).
Related
sorry for such a stupid question but I couldn't find any obvious answer.
I need to read from stdin first an int n with the size of an array, and then integer values from a string in the format "1 2 3 4 5 6" with n elements.
If I knew the number of parameters at compile time I could use something like a scanf (or the safe alternatives) with a format string like "%d %d %d %d %d %d", but here I will only know that value at run time.
What would be the best way to do this in C++? Performance is important but more than that safety.
How should I read a format string of variable length in C++ from stdin?
You should not attempt to do such thing. Only ever use constant format strings.
I need to read from stdin first an int n with the size of an array, and then integer values
What would be the best way to do this in C++?
Read one value at a time. Repeat using a loop.
Here's a function that does what errorika describes:
const int SIZE = //as much of your memory as you'd like the user to have access to
***caller function must include this:
//allocate a string to hold some data;
char* buffer = NULL;
buffer = malloc (SIZE * sizeof(char));
if (buffer == NULL) {
printf("malloc error terminating\n");
return;
}
***
void getEntry(char* buffer) {
int count = 0;
int maxlen = SIZE - 1;
char a = '0';
for (int i = 0; i < SIZE; i++) {
buffer[i] = '0';
}
while (a != '\n' && count < maxlen) {
a = fgetc(stdin);
buffer[count] = a;
count++;
}
if (a == '\n') {
buffer[count - 1] = '\0';
}
else {
buffer[count] = '\0';
do {
a = fgetc(stdin);
} while (a != '\n');
}
}
This is all basic C code but user entry is evil. Here is what I've come up with for more C++ idiomatic user input functions (query is just the message string you pass in):
template<typename T>
void getInput(const std::string query, T& entry) {
std::string input;
std::cout << query << std::endl;
getline(std::cin, input);
std::stringstream buffer{input};
buffer >> entry;
}
OR
template<typename T>
void getInput2(std::string query, T& entry) {
bool validInput = false;
while (validInput == false)
{
validInput = true;
std::cout << query << std::endl;
std::cin >> entry;
if (std::cin.fail()) {
validInput = false;
std::cout << "Unacceptable entry\n" << std::endl;
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
I want to scan to separate strings separated by a / using sscanf but it doesn't work. It works fine with a space.
For example, I want to separate the string 50%/60% into two strings like 50% and 60%.
You can have a look at code here:
#include <iostream>
using namespace std;
int extract_break_rewrites(int *m, int *n, const char *arg)
{
char m_str[10];
char n_str[10];
int err;
int count = sscanf(arg, "%s %s", n_str, m_str);
printf("%s %s %d\n",n_str, m_str,count);
if (count == 0) {
count = sscanf(arg, "/%s", m_str);
if (count == 0) {
*m = 0;
*n = 0;
return -1;
}
if (sscanf(m_str, "%d%%", m) != 1)
return -1;
}
else if (count == 1) {
if (sscanf(n_str, "%d%%", n) != 1)
return -1;
}
else if (count==2) {
if (sscanf(n_str, "%d%%", n) != 1)
return -1;
if (sscanf(m_str, "%d%%", m) != 1)
return -1;
}
return 1;
}
int main() {
int n,m;
const char * command = "50% 60%";
if (extract_break_rewrites(&m,&n,command)!=-1)
cout<<"Successful. The values of m and n are "<<m<<" and "<<n<<", respectively.\n";
else
cout<<"There was error in processing, may be input was not in the correct format.\n";
return 0;
}
You don't need to worry about what the code does, the important lines are 10, 11 and main function.
Try the following (assuming from stdin):
scanf("%[^/]/%s");
Use sscanf(buf, ...); if reading from a buffer.
The issue is that %s for scanf assumes that the string is followed by a space. This approach instructs scanf to find a string delimited by /, and then match the rest as a separate string.
EDIT: accidentally dropped the / in the scan string
Use a scan set
char a[100];
char b[100];
scanf("%[^/]/%s", a, b);
This scans in everything until it gets a /, then it starts and reads in a string.
You can also use std::strings and their facilities to achieve the same result:
#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::stoi;
bool extract_break_rewrites(int &m, int &n, const string &arg) {
// find position of %/ in the string
string::size_type pos_first = arg.find("%/");
// check if the return value is valid (the substring is present and there
// is something else first)
if ( pos_first == string::npos || !pos_first ) // wrong input
return false;
string::size_type pos_2 = pos_first + 2,
pos_last = arg.find("%", pos_2);
if ( pos_last == string::npos || pos_last == pos_2 )
return false;
try {
m = stoi(arg.substr(0, pos_first));
n = stoi(arg.substr(pos_2, pos_last - pos_2));
}
// invalid argument or out of range
catch (...) {
return false;
}
return true;
}
int main() {
int n = 0, m = 0;
string command = "150%/60%";
if ( extract_break_rewrites(m, n, command) )
cout << "Successful. The values of m and n are "
<< m << " and " << n << ", respectively.\n";
else
cout << "There was error in processing, "
<< "maybe input was not in the correct format.\n";
return 0;
}
My code is making me crazy as it sometimes works fine but sometimes get core dumped or segmentation fault or double free(faststop ) error.
I think it's because some threads can not be created but I couldn't make it. What is wrong with this code?
This code is supposed to find \n's in a text file that is stored in path.
Here is the code:
This is Search_inp struct
typedef struct Search_inp{
string * path;
string * phrase;
int a ;
int b;
int file_size;
vector<int>* vec;
}search_inp;
This function should return a void * pointer to the struct that contains my data that I want to pass to thread!
void * make_search_inp(string & path , string & phrase , int a , int b , int file_size , vector<int>&vec){
search_inp * res = (search_inp*)malloc(sizeof(search_inp));
res->path = &path;
res->phrase = & phrase;
res->a = a;
res->b = b;
res -> file_size = file_size;
res->vec = &vec;
return (void *)res;
}
This function will starting the search of \n's in the file
// this function will multi thread the search of \n's and do this through search func
void find_backslash(string path , vector<int> &place_backslash , int file_size){
int counter = 0;
string backslash = "\n";
vector<void*>temp;
vector<pthread_t> tid;
pthread_t t;
while(counter * range <= file_size ){
temp.push_back( make_search_inp(path , backslash , counter*range , (counter+1)*range-1 , file_size , place_backslash ));
pthread_create(&t, NULL , search , temp.back() );
tid.push_back(t);
counter++;
}
for(int i = 0 ; i<tid.size() ;i++) pthread_join(tid[i] , NULL);
//when the erorr happend program can not reach this place...
while(tid.size()) tid.pop_back();
while(temp.size()) temp.pop_back();
sort(place_backslash.begin() , place_backslash.end());
}
This is search function of my code:
void* search(void * temp){
search_inp* Stemp = (search_inp*)temp;
string path = *(Stemp->path);
string phrase = *(Stemp->phrase);
int a = Stemp->a;
int b = Stemp->b;
int file_size = Stemp->file_size;
vector<int>&vec = *(Stemp->vec);
if(path == "" ) return NULL;//check the path correctness
ifstream fin;//1opening the file 2check if the file opening is successful 3put the g in the correct place with seekg
fin.open(path.c_str());
if(a < 0) a=0;
if(b < 0) b=0;
if(a >file_size)
a = b = file_size;
if(b > file_size){
b = file_size;
}
fin.seekg(a , fin.beg);
if(!fin){
cout << "ERROR:File Does Not Exist!" << endl;
return NULL;
}
//opening the output file for
//The search phase
int counter=0 , charNum =a;//this counter hold the number of appearance of the phrase in the file
while(!fin.eof() && charNum < b){
int cnt = 0;char inp;
do{
fin.get(inp);charNum++;
if(phrase[cnt] == inp)
cnt++;
else
break;
}while( cnt<phrase.length() && !fin.eof());
if( cnt == phrase.length()){
counter++;
vec.push_back( ((int)fin.tellg())-1 );
}
}
fin.close();
}
I will run this program calling find_backslah(path_of_my_file , a vector<int> , size_of_file) and get the error sometimes and it isn't happening always.
I'm just guessing at the problem here, but you pass a (pointer to a) structure to all threads, and all threads have some common pointers that they all share in the structure, for example the std::vector. If more than one thread tries to modify the vector at the same time you have a race condition.
Race conditions are bad and you need to protect against them using some kind of lock, for example using a mutex.
Phase 1
example 1: I have string text = "01100001" then I want write to file "a"
example 2: I have string text = "0110000101100010" So I want write to file "ab"
NOTE:I solved phase 1 and result of writing is true.
Phase 2
for example 1:
I want read the file and put it to temp.
So temp = "a" and i convert it to "01100001"
for example 2:
I want read the file and put it to temp.
So temp = "ab" and i convert it to "0110000101100010"
Question
in my code i have below input
string text ="00000110101011100010001011111110011011110101100101110101101111010111111110101011"
"00111011000011100011100000100010111110111110111001100001110001110000101001111010"
"00000101";
I did "phase 1" and I opened the file in a hex editor the writing is true.
But after doing "phase 2" temp != text. Why?
My code
#include <iostream>
#include <sstream>
#include <vector>
#include <fstream>
#include <string>
#include <stdlib.h>
using namespace std;
class bitChar{
public:
unsigned char* c;
int shift_count;
string BITS;
bitChar()
{
shift_count = 0;
c = (unsigned char*)calloc(1, sizeof(char));
}
string readByBits(ifstream& inf)
{
string s ="";
while (inf)
{
string strInput;
getline(inf, strInput );
for (int i =0 ; i < strInput.size() ; i++)
{
s += getBits(strInput[i]);
}
}
return s;
}
void setBITS(string X)
{
BITS = X;
}
int insertBits(ofstream& outf)
{
int total = 0 ;
while(BITS.length())
{
if(BITS[0] == '1')
*c |= 1;
*c <<= 1;
++shift_count;
++total;
BITS.erase(0, 1);
if(shift_count == 7 )
{
if(BITS.size()>0)
{
if(BITS[0] == '1')
*c |= 1;
++total;
BITS.erase(0, 1);
}
writeBits(outf);
shift_count = 0;
free(c);
c = (unsigned char*)calloc(1, sizeof(char));
}
}
if(shift_count > 0)
{
*c <<= (7 - shift_count);
writeBits(outf);
free(c);
c = (unsigned char*)calloc(1, sizeof(char));
}
outf.close();
return total;
}
string getBits(unsigned char X)
{
stringstream itoa;
for(unsigned s = 7; s > 0 ; s--)
{
itoa << ((X >> s) & 1);
}
itoa << (X&1) ;
return itoa.str();
}
void writeBits(ofstream& outf)
{
outf << *c;
}
~bitChar()
{
if(c)
free(c);
}
};
int main()
{
ofstream outf("ssSample.dat",ios::binary);
string text ="00000110101011100010001011111110011011110101100101110101101111010111111110101011"
"00111011000011100011100000100010111110111110111001100001110001110000101001111010"
"00000101";
cout<< text<<endl;
//write to file
bitChar bchar;
bchar.setBITS(text);
bchar.insertBits(outf);
outf.close();
ifstream inf("ssSample.dat" ,ios::binary);
//READ FROM FILE
string temp=bchar.readByBits(inf);
cout << endl;
cout << temp << endl;
return 0;
}
You have a LF Line Feed character. This is the character that is getting omitted.
0000 1010
This may be unrelated, but Windows requires a CR and LF for a new line. This code may act differently in Windows vs. Unix.
Read one byte at a time.
string readByBits(ifstream& inf)
{
string s ="";
char buffer[1];
while (inf.read (buffer, 1))
{
// string strInput;
//getline(inf, strInput );
//for (int i =0 ; i < strInput.size() ; i++)
//{
s += getBits(*buffer);
//}
}
return s;
}
Program output:
000001101010111000100010111111100110111101011001011101011011110101111111101010110011101100001110001110000010001011111011111011100110000111000111000010100111101000000101
000001101010111000100010111111100110111101011001011101011011110101111111101010110011101100001110001110000010001011111011111011100110000111000111000010100111101000000101
One problem with your approach is that your text must be a multiple of 8 bits to work. Otherwise, even if everything is correct, that last character will be read from the file and converted to 8 binary digits in the string adding trailing zeros.
Two problems I quickly identified (but I assume there are more)
Your input is not a multiple of 8-bits
By using getLine you're reading until you meet a delimiting character and thus spoiling your result since you're not dealing with a text-based file
I'm trying to split up a line of 80 characters of input into an array where each element points to a string of chars. Essentially, turn a char a[80] like "Hello world!" into a char* b[64] where b[0] points to "Hello" and b[1] points to "world!"
Basically, what strsep() would allow me with the following code:
while((cmd->argv[argc++] = strsep(clPtr, WHITESPACE)) != NULL);
I would like to know how I would go about modifying this code:
int parse(char* comm, char** commarray) {
int count = 0;
char word[80] = "";
char ch[2] = {' ', '\0'};
if(strlen(comm) == 0) {
commarray[0] = "NULL";
return 0;
}
for(size_t i = 0; i < strlen(comm); i++) {
int c = int(comm[i]);
if(!isspace(c)) {
ch[0] = comm[i];
strcat(word, ch);
if(i == (strlen(comm) - 1)) {
commarray[count] = word;
cout << commarray[count] << endl;
count++;
}
}
else if(isspace(c) && word != "") {
commarray[count] = word;
cout << commarray[count] << endl;
word[0] = '\0';
count++;
}
}
return 1;
}
//main
int main() {
char command[80];
char* args[64];
while(true) {
cout << "order>";
cin.getline(command, 80);
if(strcmp(command, "quit") == 0 || strcmp(command, "exit") == 0) {
break;
}
parse(command, args);
cout << args[0] << endl;
if(strcmp(args[0], "quit") == 0 || strcmp(args[0], "exit") == 0) {
break;
}
/*for(int i = 0; i < 3; i++) {
cout << args[i] << endl;
}*/
}
return 0;
}
The variable args in the main() does not display what the variable commarray does in parse(). Instead, I get gibberish. Why is this? I thought passing an array was by default a pass by reference? For commarray, I get the appropriate array of pointers to strings (I think). For args, I get nothing usable.
Pointer hell is where you are at. I can see at least two fundamental problems with the code, but there's possibly more.
1) You reuse word for all your assignments to commarray. So you end up with all the pointers in commarray pointing at the same word array. Obviously that cannot work.
2) When you have exited the parse function the word array is no longer in scope, so it becomes invalid memory. So you have all your args array pointers pointing at the same piece of invalid (hence garbage) memory.
My advice, stop using pointers, start using C++, namely the std::string class, which will behave much more logically and intuitively than any pointer would.