Making a shell in c++, trying to create shell variables - c++

So I have a relatively simple shell, it handles pipes, chdir, redirects and running programs. But I need a way of implementing shell variables like you would have in a normal shell(E.g HELLO=world).
int main()
{
while(true)
{
string result;
char * left[128];
char * right[128];
cout << "$$ ";
char command[128];
cin.getline(command,128);
if(strlen(command) != 0)
{
vector<char*>args;
char* prog = strtok(command, " ");
char* tmp = prog;
while ( tmp != NULL )
{
args.push_back( tmp );
tmp = strtok( NULL, " " );
}
char** argv = new char*[args.size()+1];
for ( int k = 0; k < args.size(); k++ )
{
argv[k] = args[k];
}
argv[args.size()] = NULL;
if ( strcmp( command, "exit" ) == 0 )
{
return 0;
}
if(!strcmp(prog,"cd"))
{
chdir(argv);
}
if(prog[0] == '.')
{
std::system(args[0]);
}
else
{
pid_t kidpid = fork();
if(kidpid < 0)
{
perror("Could not fork");
return -1;
}
else if (kidpid == 0)
{
execvp(prog,argv);
}
else
{
if(waitpid(kidpid,0,0) <0 )
{
return -1;
}
}
}
}
}
return 0;
}
Here's the shell from the simplest form, the function calls do pretty much what they say.

You need 3 things:
Parse FOO=foo variable assignments in the input lines
Parse $FOO variable references in the input lines, replace with value
Storage of the variable names and values
There are endless possibilities how to do the latter.
Single dynamic char array, all variables stored in a single string, with a magic character of your choice separating the entries: FOO=foo#BAR=baz#SPAM=eggs. Scales O(n) with the number of entries.
Dynamic array containing pairs of char pointers for variable names and values. Scales O(n).
Linked list, where you insert above pairs in a sorted way. Scales O(log n) if you do insertions and lookups with a binary search.
Binary tree for above pairs, if unbalanced, scales between O(log n) and O(n).
Hash table. Scales O(1).
Etc, etc, etc.
With a dynamic array, I mean that you always realloc the whole thing upon insertions.

If you want to store the variables in your shell, you should look into getenv() and setenv() found in stdlib.
http://pubs.opengroup.org/onlinepubs/009695399/functions/setenv.html
http://pubs.opengroup.org/onlinepubs/009695399/functions/getenv.html
This avoids having to use storage in your C/C++ program with the STL. For example, you can set variables by
setenv("variablename", "value", 1);
Where the 1 turns on overwrite for the current variable if it exists. So in your example, we would use
setenv("HELLO", "world", 1);
You can also retrieve the value of the variable by using
char *value = getenv("variablename");
You do not need to dynamically allocate value.
Note: These values persist for the life of the program that simulates the shell, after which they no longer exist.

Related

iterating vector of strings C++

The code is to read instructions from text file and print out graphic patterns. One is my function is not working properly. The function is to read the vectors of strings I've got from the file into structs.
Below is my output, and my second, third, and sixth graphs are wrong. It seems like the 2nd and 3rd vectors are not putting the correct row and column numbers; and the last one skipped "e" in the alphabetical order.
I tried to debug many times and still can't find the problem.
typedef struct Pattern{
int rowNum;
int colNum;
char token;
bool isTriangular;
bool isOuter;
}Pattern;
void CommandProcessing(vector<string>& , Pattern& );
int main()
{
for (int i = 0; i < command.size(); i++)
{
Pattern characters;
CommandProcessing(command[i], characters);
}
system("pause");
return 0;
}
void CommandProcessing(vector<string>& c1, Pattern& a1)
{
reverse(c1.begin(), c1.end());
string str=" ";
for (int j = 0; j < c1.size(); j++)
{
bool foundAlpha = find(c1.begin(), c1.end(), "alphabetical") != c1.end();
bool foundAll = find(c1.begin(), c1.end(), "all") != c1.end();
a1.isTriangular = find(c1.begin(), c1.end(), "triangular") != c1.end() ? true : false;
a1.isOuter = find(c1.begin(), c1.end(), "outer") != c1.end() ? true : false;
if (foundAlpha ==false && foundAll == false){
a1.token = '*';
}
//if (c1[0] == "go"){
else if (c1[j] == "rows"){
str = c1[++j];
a1.rowNum = atoi(str.c_str());
j--;
}
else if (c1[j] == "columns"){
str = c1[++j];
a1.colNum = atoi(str.c_str());
j--;
}
else if (c1[j] == "alphabetical")
a1.token = 0;
else if (c1[j] == "all"){
str = c1[--j];
a1.token = *str.c_str();
j++;
}
}
}
Before debugging (or posting) your code, you should try to make it cleaner. It contains many strange / unnecessary parts, making your code harder to understand (and resulting in the buggy behaviour you just described).
For example, you have an if in the beginning:
if (foundAlpha ==false && foundAll == false){
If there is no alpha and all command, this will be always true, for the entire length of your loop, and the other commands are all placed in else if statements. They won't be executed.
Because of this, in your second and third example, no commands will be read, except the isTriangular and isOuter flags.
Instead of a mixed structure like this, consider the following changes:
add a default constructor to your Pattern struct, initializing its members. For example if you initialize token to *, you can remove that if, and even the two bool variables required for it.
Do the parsing in one way, consistently - the easiest would be moving your triangular and outer bool to the same if structure as the others. (or if you really want to keep this find lookup, move them before the for loop - you only have to set them once!)
Do not modify your loop variable ever, it's an error magnet! Okay, there are some rare exceptions for this rule, but this is not one of them.
Instead of str = c1[++j];, and decrementing later, you could just write str = c1[j+1]
Also, are you sure you need that reverse? That makes your relative +/-1 indexing unclear. For example, the c1[j+1 is j-1 in the original command string.
About the last one: that's probably a bug in your outer printing code, which you didn't post.

Working with big text files

I have a file in following format:
[1]
Parameter1=Value1
.
.
.
End
[2]
.
.
The number between brackets presents id of the entity. There're around 4500 entites. I need to parse through all entites and pick the ones matching my parameters and values. Size of file is around 20mb. My first approach was to reading file line by line and storing them in a struct array like:
struct Component{
std::string parameter;
std::string value;
};
struct Entity{
std::string id;
std::list<Component> components;
};
std::list<Entity> g_entities;
But this approach took enormous amount of memory and was very slow. I've also tried storing only the ones that match my parameters/values. But that also was really slow and took quite some memory. Ideally i would like to store all data in memory so that i won't have to load the file everytime i need to filter my parameters/values if it's possible with reasonable amount of memory usage.
Edit 1:
I read file line by line:
std::ifstream readTemp(filePath);
std::stringstream dataStream;
dataStream << readTemp.rdbuf();
readTemp.close();
while (std::getline(dataStream, line)){
if (line.find('[') != std::string::npos){
// Create Entity
Entity entity;
// Set entity id
entity.id = line.substr(line.find('[') + 1, line.find(']') - 1);
// Read all lines until EnumEnd=0
while (1){
std::getline(dataStream, line);
// Break loop if end of entity
if (line.find("EnumEnd=0") != std::string::npos){
if (CheckMatch(entity))
entities.push_back(entity);
entity.components.clear();
break;
}
Component comp;
int pos_eq = line.find('=');
comp.parameterId = line.substr(0, pos_eq);
comp.value = line.substr(pos_eq + 1);
entity.components.push_back(comp);
}
}
}
PS: After your edit. and Comment concerning memory consumption
500MB / 20MB = 25.
If each line is 25 chars long, the memory consumption looks ok.
OK you could use a look-up table for mapping parameter-names to numbers.
If the names-set is small, this will save the consumption up to 2 times.
Your data structure could look like this:
std::map<int, std::map<int, std::string> > my_ini_file_data;
std::map<std::string, int> param_to_idx;
(provided the parameter names within sections (entities as you call it) are not unique)
Putting the data is:
std::string param = "Param";
std::string value = "Val";
int entity_id = 0;
if ( param_to_idx.find(param) == param_to_idx.end() )
param_to_idx[param] = param_to_idx.size();
my_ini_file_data[entity_id][ param_to_idx[param] ] = value;
getting the data is:
value = my_ini_file_data[entity_id][ param_to_idx[param] ];
If the values-set is also considerably smaller than the number of entries,
you could even map values to numbers:
std::map<int, std::map<int, int> > my_ini_file_data;
std::map<std::string, int> param_to_idx;
std::map<std::string, int> value_to_idx;
std::map<int, std::string> idx_to_value;
Putting the data is:
std::string param = "Param";
std::string value = "Val";
int entity_id = 0;
if ( param_to_idx.find(param) == param_to_idx.end() )
param_to_idx[param] = param_to_idx.size();
if ( value_to_idx.find(value) == value_to_idx.end() )
{
int idx = value_to_idx.size();
value_to_idx[value] = idx;
idx_to_value[idx] = value;
}
my_ini_file_data[entity_id][ param_to_idx[param] ] = value_to_idx[value];
getting the data is:
value = idx_to_value[my_ini_file_data[entity_id][ param_to_idx[param] ] ];
Hope, this helps.
Initial answer
Concerning memory, I wouldn't care unless you have a kind of embedded system with very small memory.
Concerning the speed, I could give you some suggestions:
Find out, what is the bottleneck.
Use std::list! Using std::vector you re-initialize the memory each time the vector grows. If for some reason you need a vector at the end, create the vector reserving the requires number of entries, which you'll get by calling list::size()
Write a while loop, there you only call getline. If this alone is
already slow, read the entire block at once, create a reader-stream
out of the char* block and read line by line from the stream.
If the speed of the simple reading is OK, optimize your parsing code. You
can reduce the number of find-calls by storing the position. e.g.
int pos_begin = line.find('[]');
if (pos_begin != std::string::npos){
int pos_end = line.find(']');
if (pos_end != std::string::npos){
entity.id = line.substr(pos_begin + 1, pos_begin - 1);
// Read all lines until EnumEnd=0
while (1){
std::getline(readTemp, line);
// Break loop if end of entity
if (line.find("EnumEnd=0") != std::string::npos){
if (CheckMatch(entity))
entities.push_back(entity);
break;
}
Component comp;
int pos_eq = line.find('=');
comp.parameter= line.substr(0, pos_eq);
comp.value = line.substr(pos_eq + 1);
entity.components.push_back(comp);
}
}
}
Depending on how big your entities are, check if CheckMatch is slow. The smaller the entities, the slower the code - in this case.
You can use less memory by interning your params and values, so as not to store multiple copies of them.
You could have a map of strings to unique numeric IDs, that you create when loading the file, and then just use the IDs when querying your data structure. At the expense of possibly slower parsing initially, working with these structures afterwards should be faster, as you'd only be matching 32-bit integers rather than comparing strings.
Sketchy proof of concept for storing each string once:
#include <unordered_map>
#include <string>
#include <iostream>
using namespace std;
int string_id(const string& s) {
static unordered_map<string, int> m;
static int id = 0;
auto it = m.find(s);
if (it == m.end()) {
m[s] = ++id;
return id;
} else {
return it->second;
}
}
int main() {
// prints 1 2 2 1
cout << string_id("hello") << " ";
cout << string_id("world") << " ";
cout << string_id("world") << " ";
cout << string_id("hello") << endl;
}
The unordered_map will end up storing each string once, so you're set for memory. Depending on your matching function, you can define
struct Component {
int parameter;
int value;
};
and then your matching can be something like myComponent.parameter == string_id("some_key") or even myComponent.parameter == some_stored_string_id. If you want your strings back, you'll need a reverse mapping as well.

How to get subarray of C-Array

I am trying to find out what is the easiest way to get a subset of C-Array if there are start and end points give.
Example: I have a class Trip:
class Trip
{
private:
char* final_destination;
char* description;
public:
//all constructors, operators and stuff
};
And, lets say I have an array of Trips:
Trip* trips = new Trip[10];
I am trying to write a function that takes the Trip array, starting point(given destination), end point(given destination) and return a subset of type Trip*.
E.g.
Trip* GetSubTrip(Trip* trips, char* start_point, char* end_point)
{
//Logics that returns Trip*
}
In other words, If I had:
[{"London", "Big Ben"}, {"New York", "Manhattan"}, {"Paris", "Eifell Tower"}, {"Moscow", "Lots of fun"}]
That would be the Trip* trips and "New York" as a start and "Moscow" as an end passed to the GetSubTrip I am trying to make it return Trip*.
And the return has to be:
[{"Paris", "Eifell Tower"}, {"Moscow", "Lots of fun"}]
What I do is:
In an integer counter I get the length between start and end
Create a new pointer Trip* and assign it with length of the counter from 1
Iterate over the 'trips' parameter and keeping a track if I am between start and end and if yes-> add the object to the result else procceed further.
But this is a lot of code. I am sure that there is much easier way.
EDIT:
It has to be done WITHOUT the use of VECTOR!
Using std::vector:
std::vector<Trip> route;
bool go = false;
for( int i=0; i<tripsSize /* trips[i] != TRIP_GUARD */; ++i )
{
if( go )
{
route.push_back( trips[i] );
if( trips[i] == end )
break;
}
else if( trips[i] == start )
go = true;
}
Why use std::vector? You don't have to keep the size of resulting array. You may modify it freely and conveniently. You don't have to worry about memory allocation for Trip objects.
In case you don't want to use std::vector you would need some sort of guard for both of your arrays (input and output one ) or to pass length of the array.
Without std::vector:
Trip * route;
int tripsNum;
int startNum, endNum;
for( int i=0; i<tripsSize /* trips[i] != TRIP_GUARD */; ++i )
{
if( trips[i] == start )
startNum = i;
else if( trips[i] == end )
{
endNum = i;
break;
}
}
tripsNum = endNum - startNum;
route = new Trip[ tripsNum ];
for( int i=startNum + 1, j=0; i<=endNum; ++i, ++j )
route[ j ] = trips [ i ];
Since you are using C++ you can consider using std::vector class instead of raw C arrays.
For raw C arrays you would need to keep the size (number of elements) of the array somewhere.
If you prefer arrays the solution depends on whether you are going to modify the original array/sub-arrays.
If you don't modify the Trips array, you can get the pointer to the sub-array with pointer arithmetic:
return trips + 2;//The returned pointer points to {"Paris", "Eifell Tower"}
You would also need to store the size of the sub-array.
If you do need to modify the original array (and/or sub-array), then you would have to create a copy (I would strongly suggest using vectors in that case). You might find this useful:
Best way to extract a subvector from a vector?

AVL tree balance factor

I have an AVL tree class, I want to find balance factor of each node ( balance_factor: node->Left_child->height - node->right_Child->height )
Here is my code:
int tree::findBalanceFactor(node p){
int a;
if( p.lchild) p.lchild->balance_factor=findBalanceFactor( *p.lchild );
if( p.rchild) p.rchild->balance_factor=findBalanceFactor( *p.rchild );
if( p.rchild && p.lchild ) a=p.balance_factor = p.lchild->height - p.rchild->height ;
if( p.rchild && !p.lchild ) a=p.balance_factor = 0 - p.rchild->height;
if( !p.rchild && p.lchild ) a=p.balance_factor = p.lchild->height;
if( !p.rchild && !p.lchild ) a=p.balance_factor = 0;
cout << "md" << a << endl;
return a;
}
In the main function when I print root->balance_factor it shows me always number zero balance_factor is a public variable and in the constructor I assigned zero to that.
What is the wrong with my code?
There's a much simpler way to do this than testing every permutation of lchild and rchild:
int tree::findBalanceFactor(node &n) {
int lheight = 0;
int rheight = 0;
if (n.lchild) {
findBalanceFactor(*n.lchild);
lheight = n.lchild->height;
}
if (n.rchild) {
findBalanceFactor(*n.rchild);
rheight = n.rchild->height;
}
n.balance_factor = lheight - rheight;
std::cout << "md " << n.balance_factor << std::endl;
return n.balance_factor;
}
Since this otherwise seems to have ended up as an all-code answer, I'll add a brief note on how to get from the original code to this.
On one level, it's trivial to observe that each of the four branches in the original has the same form (left - right), but with left=0 whenever lchild is null, and right=0 whenever rchild is null.
More broadly, it's really useful to look for this kind of pattern (ie, that each branch has essentially the same expression). Writing out truth tables or otherwise partitioning your state space on paper, can help clarify these patterns in more complex code.
You should always aim to know what the general case is - whether because you implemented that first, or because you were able to factor it back out of several specific cases. Often implementing the general case will be good enough anyway, as well as being the easiest version of the logic to understand.
If the general case isn't good enough for some reason, then being easy to understand means it is still a good comment, as it provides a point of comparison for the special cases you actually implement.
I am guessing that the reason why the balance_factor of the root node is always 0 because of these 2 lines of code in the tree::findBalanceFactor method:
if( p.lchild) p.lchild->balance_factor=findBalanceFactor( *p.lchild );
if( p.rchild) p.rchild->balance_factor=findBalanceFactor( *p.rchild );
I suppose that the node struct/class looks something like this:
struct node {
struct node *lchild;
struct node *rchild;
int balance_factor;
int height;
};
What happens in findBalanceFactor( *p.lchild ) and findBalanceFactor( *p.rchild ) is that, we are passing new copies of p.lchild and p.rchild into findBalanceFactor (as seen from the pointer dereference), and hence the balance_factor attribute of the original p.lchild and p.rchild are not updated.
The solution will be to modify the tree::findBalanceFactor method to take in pointers to node, like this (I've taken the liberty to prettify the code a little):
int tree::findBalanceFactor(node *p) {
int a;
if (p->lchild) {
findBalanceFactor(p->lchild);
}
if (p->rchild) {
findBalanceFactor(p->rchild);
}
if (p->rchild && p->lchild) {
a = p->balance_factor = p->lchild->height - p->rchild->height;
} else if (p->rchild && !p->lchild) {
a = p->balance_factor = 0 - p->rchild->height;
} else if (!p->rchild && p->lchild) {
a = p->balance_factor = p->lchild->height;
} else {
// this is the case for !p->rchild && !p->lchild
a = p->balance_factor = 0;
}
cout << "md" << a << endl;
return a;
}
For p->lchild and p->rchild, we do not need to set their balance_factor another time, since the balance_factor of each node is already set in one of the 4 possible cases of the very long if statement.

C code - need to clarify the effectiveness

Hi I have written a code based upon a requirement.
(field1_6)(field2_30)(field3_16)(field4_16)(field5_1)(field6_6)(field7_2)(field8_1).....
this is one bucket(8 fields) of data. we will receive 20 buckets at a time means totally 160 fields.
i need to take the values of field3,field7 & fields8 based upon predefined condition.
if teh input argument is N then take the three fields from 1st bucket and if it is Y i need
to take the three fields from any other bucket other than 1st one.
if argumnet is Y then i need to scan all the 20 buckets one after other and check
the first field of the bucket is not equal to 0 and if it is true then fetch the three fields of that bucket and exit.
i have written the code and its also working fine ..but not so confident that it is effctive.
i am afraid of a crash some time.please suggest below is the code.
int CMI9_auxc_parse_balance_info(char *i_balance_info,char *i_use_balance_ind,char *o_balance,char *o_balance_change,char *o_balance_sign
)
{
char *pch = NULL;
char *balance_id[MAX_BUCKETS] = {NULL};
char balance_info[BALANCE_INFO_FIELD_MAX_LENTH] = {0};
char *str[160] = {NULL};
int i=0,j=0,b_id=0,b_ind=0,bc_ind=0,bs_ind=0,rc;
int total_bukets ;
memset(balance_info,' ',BALANCE_INFO_FIELD_MAX_LENTH);
memcpy(balance_info,i_balance_info,BALANCE_INFO_FIELD_MAX_LENTH);
//balance_info[BALANCE_INFO_FIELD_MAX_LENTH]='\0';
pch = strtok (balance_info,"*");
while (pch != NULL && i < 160)
{
str[i]=(char*)malloc(strlen(pch) + 1);
strcpy(str[i],pch);
pch = strtok (NULL, "*");
i++;
}
total_bukets = i/8 ;
for (j=0;str[b_id]!=NULL,j<total_bukets;j++)
{
balance_id[j]=str[b_id];
b_id=b_id+8;
}
if (!memcmp(i_use_balance_ind,"Y",1))
{
if (atoi(balance_id[0])==1)
{
memcpy(o_balance,str[2],16);
memcpy(o_balance_change,str[3],16);
memcpy(o_balance_sign,str[7],1);
for(i=0;i<160;i++)
free(str[i]);
return 1;
}
else
{
for(i=0;i<160;i++)
free(str[i]);
return 0;
}
}
else if (!memcmp(i_use_balance_ind,"N",1))
{
for (j=1;balance_id[j]!=NULL,j<MAX_BUCKETS;j++)
{
b_ind=(j*8)+2;
bc_ind=(j*8)+3;
bs_ind=(j*8)+7;
if (atoi(balance_id[j])!=1 && atoi( str[bc_ind] )!=0)
{
memcpy(o_balance,str[b_ind],16);
memcpy(o_balance_change,str[bc_ind],16);
memcpy(o_balance_sign,str[bs_ind],1);
for(i=0;i<160;i++)
free(str[i]);
return 1;
}
}
for(i=0;i<160;i++)
free(str[i]);
return 0;
}
for(i=0;i<160;i++)
free(str[i]);
return 0;
}
My feeling is that this code is very brittle. It may well work when given good input (I don't propose to desk check the thing for you) but if given some incorrect inputs it will either crash and burn or give misleading results.
Have you tested for unexpected inputs? For example:
Suppose i_balance_info is null?
Suppose i_balance_info is ""?
Suppose there are fewer than 8 items in the input string, what will this line of code do?
memcpy(o_balance_sign,str[7],1);
Suppose that that the item in str[3] is less than 16 chars long, what will this line of code do?
memcpy(o_balance_change,str[3],16);
My approach to writing such code would be to protect against all such eventualities. At the very least I would add ASSERT() statements, I would usually write explicit input validation and return errors when it's bad. The problem here is that the interface does not seem to allow for any possibility that there might be bad input.
I had a hard time reading your code but FWIW I've added some comments, HTH:
// do shorter functions, long functions are harder to follow and make errors harder to spot
// document all your variables, at the very least your function parameters
// also what the function is suppose to do and what it expects as input
int CMI9_auxc_parse_balance_info
(
char *i_balance_info,
char *i_use_balance_ind,
char *o_balance,
char *o_balance_change,
char *o_balance_sign
)
{
char *balance_id[MAX_BUCKETS] = {NULL};
char balance_info[BALANCE_INFO_FIELD_MAX_LENTH] = {0};
char *str[160] = {NULL};
int i=0,j=0,b_id=0,b_ind=0,bc_ind=0,bs_ind=0,rc;
int total_bukets=0; // good practice to initialize all variables
//
// check for null pointers in your arguments, and do sanity checks for any
// calculations
// also move variable declarations to just before they are needed
//
memset(balance_info,' ',BALANCE_INFO_FIELD_MAX_LENTH);
memcpy(balance_info,i_balance_info,BALANCE_INFO_FIELD_MAX_LENTH);
//balance_info[BALANCE_INFO_FIELD_MAX_LENTH]='\0'; // should be BALANCE_INFO_FIELD_MAX_LENTH-1
char *pch = strtok (balance_info,"*"); // this will potentially crash since no ending \0
while (pch != NULL && i < 160)
{
str[i]=(char*)malloc(strlen(pch) + 1);
strcpy(str[i],pch);
pch = strtok (NULL, "*");
i++;
}
total_bukets = i/8 ;
// you have declared char*str[160] check if enough b_id < 160
// asserts are helpful if nothing else assert( b_id < 160 );
for (j=0;str[b_id]!=NULL,j<total_bukets;j++)
{
balance_id[j]=str[b_id];
b_id=b_id+8;
}
// don't use memcmp, if ('y'==i_use_balance_ind[0]) is better
if (!memcmp(i_use_balance_ind,"Y",1))
{
// atoi needs balance_id str to end with \0 has it?
if (atoi(balance_id[0])==1)
{
// length assumptions and memcpy when its only one byte
memcpy(o_balance,str[2],16);
memcpy(o_balance_change,str[3],16);
memcpy(o_balance_sign,str[7],1);
for(i=0;i<160;i++)
free(str[i]);
return 1;
}
else
{
for(i=0;i<160;i++)
free(str[i]);
return 0;
}
}
// if ('N'==i_use_balance_ind[0])
else if (!memcmp(i_use_balance_ind,"N",1))
{
// here I get a headache, this looks just at first glance risky.
for (j=1;balance_id[j]!=NULL,j<MAX_BUCKETS;j++)
{
b_ind=(j*8)+2;
bc_ind=(j*8)+3;
bs_ind=(j*8)+7;
if (atoi(balance_id[j])!=1 && atoi( str[bc_ind] )!=0)
{
// length assumptions and memcpy when its only one byte
// here u assume strlen(str[b_ind])>15 including \0
memcpy(o_balance,str[b_ind],16);
// here u assume strlen(str[bc_ind])>15 including \0
memcpy(o_balance_change,str[bc_ind],16);
// here, besides length assumption you could use a simple assignment
// since its one byte
memcpy(o_balance_sign,str[bs_ind],1);
// a common practice is to set pointers that are freed to NULL.
// maybe not necessary here since u return
for(i=0;i<160;i++)
free(str[i]);
return 1;
}
}
// suggestion do one function that frees your pointers to avoid dupl
for(i=0;i<160;i++)
free(str[i]);
return 0;
}
for(i=0;i<160;i++)
free(str[i]);
return 0;
}
A helpful technique when you want to access offsets in an array is to create a struct that maps the memory layout. Then you cast your pointer to a pointer of the struct and use the struct members to extract information instead of your various memcpy's
I would also suggest you reconsider your parameters to the function in general, if you place every of them in a struct you have better control and makes the function more readable e.g.
int foo( input* inbalance, output* outbalance )
(or whatever it is you are trying to do)