I am trying to grasp pointers and I have this simple code for which I need some explanation.
I need to copy one char array to another. In my main function I have this code:
const int MAX_SIZE = 100;
char x[MAX_SIZE] = "1234565";
char* y = new char[MAX_SIZE];
copyArray(x, y);
std::cout << y;
delete [] y;
Now comes the question, how does this code (which works jut fine):
while ((*dest = *source) != '\0')
{
dest += 1;
source += 1;
}
Differ from this (gives strange characters at the end):
while (*source != '\0')
{
*dest = *source;
dest += 1;
source += 1;
}
Looking at this it seems those two functions are pretty similar.
It makes sense that we are copying until we reach a null-terminator in the source string, right (2nd function)?
But it's not working correctly - I get some strange characters at the end of the copied array. However, the first function works just fine.
void copyArray(const char* source, char* dest);
The form
while ((*dest = *source) != '\0')
{
dest += 1;
source += 1;
}
guarantees that the assignment of the character to copy ((*dest = *source)) is applied before testing the condition if the terminating '\0' character is reached is evaluated to false.
The second version doesn't copy the terminating '\0' character, because the loop ends before the
*dest = *source;
statement is ever reached.
(*dest = *source) is an evaluated expression just like the 1+1 part of int i = 1+1; so, after it is evaluated, the value is usable in an other expression
The difference is that in ((*dest = *source) != '\0'), the value of *source is assigned to *dest, then the whole expression is evaluated ( expression has the same value than *source ) while the value pointed by *source is only used to evaluate *source != '\0', but never assigned during the evaluation of that statement.
EDIT
user0042 brings a realy acute observation : by doing so, the following code
while ((*dest = *source) != '\0')
{
dest += 1;
source += 1;
}
ensures that the final char of the array has a value of '\0'
In the example you incrementing the addresses of x, y thus until the last character they point to Null-terminator so you have to declare a temporary variables to hold the first address:
char* x = "1234565";
char* y = new char[MAX_SIZE];
// Temporary pointers to hold the first element's address
char* tmp1 = x;
char* tmp2 = y;
while( (*y = *x) != '\0'){
x += 1; // X no longer points to the first element
y += 1; // Y no longer points to the first element
}
std::cout << tmp2;
You can use a do while loop instead of while:
char* x = "1234565";
const int size = strlen(x);
char* y = new char[size];
char* tmp1 = x;
char* tmp2 = y;
do{
*y = *x;
x += 1;
y += 1;
}while( *(x - 1) != '\0');
// Now no need for adding a null-terminator it is already added in the loop
// tmp2[size] = '\0';
std::cout << tmp2;
Because Assigning the values before incrementing so the last character \0 will break the loop before added to the destination pointer y. Thus I made the loop breaks not on n = '\0' but on n - 1 = '\0' to ensure that it is added to y.
Related
example code:
const char* list[] = {"Elem_E", "Elem_T", "Elem_R", "Turtle", "Rabbit"};
const char ** patterns=0;
.
.
.
bool sec_run = false;
patterns = list;
process_data(patterns, sec_run);
process_data function:
process_data(const char **& pattern, bool sec_run){
.
.
some_variable=0;
for(int i; i < num_patterns;++i){
if(!sec_run){
some_variable = *pattern[i];
}
else{
if(/* list element contains "_" */)continue;
some_variable= /*letter after "_" */
}
if(some_variable == 'E') multiplier = 0;
else if(some_variable == 'T') multiplier = 1;
else if(some_variable == 'R') multiplier = 2;
}
}
So there is the base of what I'm trying to do. I cannot change signature for process_data. To start i do not get how some_variable = *pattern[i]; returns E,T, or R, and I cannot figure out how to iteratively access the full elements in the list. ie "Elem_E" to check for underscore and parse off the E.
I have little background in C++, but have used C numerous times. I am having a difficult time finding visual representation for char **& to help with based understanding of what is going on here, if you can point in the direction of a good tutorial with visual that will also suffice.
Sorry for confusion, forgot quotes in the list.
In C++, reading a parameter passed by reference (with the &) works the same as reading a parameter passed by value (without the &). The difference happens when you assign to the parameter. If the parameter was passed by value then the assignment is only visible inside the function but if it was passed by reference the assignment will be visible outside.
int mynumber = 0;
void foo(int &x)
{
printf("%d\n", x); //prints 0;
x = 10;
}
int main()
{
foo(mynumber);
printf("%d\n", mynumber); // prints 10
}
The equivalent to this in plain C would be to make the x parameter into a pointer and add the required *s and &s:
int mynumber = 0;
void foo(int *x)
{
printf("%d\n", *x);
*x = 10;
}
int main()
{
foo(&mynumber);
printf("%d\n", mynumber); // prints 10
}
Coming back to your code, I don't really know how to solve all your problems (what does the constant Elem_E mean? Is your list NULL terminated or is there a length stored somewhere?) but what I can say is that as long as you don't want to change the patterns global variable from inside process_data, using a char **& will be the same as using a char **.
I don't know how some_variable and multiplier will be used, but I made these changes to calculate them for each string in the list. The variable sec_run is not required in this approach. If no match is found, some_variable and multiplier are set to default values of '\0' and -1.
Output:
item=Elem_E some_variable=E multiplier=0
item=Elem_T some_variable=T multiplier=1
item=Elem_R some_variable=R multiplier=2
item=Turtle some_variable= multiplier=-1
item=Rabbit some_variable= multiplier=-1
Code:
void process_data(const char **& pattern, int num_patterns)
{
const char * item;
for (int i = 0; i < num_patterns; ++i)
{
item = pattern[i];
if ( item == NULL ) continue;
char some_variable = '\0'; // set to default for no match
int multiplier = -1; // set to default for no match
int len = strlen(item);
for (int j = 0; j < len; ++j)
{
if (item[j] == '_' && j + 1 < len)
some_variable = item[j + 1]; /*letter after "_" */
}
if (some_variable == 'E') multiplier = 0;
else if (some_variable == 'T') multiplier = 1;
else if (some_variable == 'R') multiplier = 2;
cout << "item=" << item << " some_variable=" << some_variable << " multiplier=" << multiplier << endl;
}
}
void pattern_test()
{
const char* list[] = { "Elem_E", "Elem_T", "Elem_R", "Turtle", "Rabbit" };
const char ** patterns = list;
// trick to calculate array length
// length of entire array divided by length of one element
int num_length = sizeof(list) / sizeof(list[0]);
process_data(patterns, num_length);
}
i am a beginner in c++ ..so please help me get this right.
trying to read from the collection, in one version of implementation I have tried ,there was some bippings from the console, another test.. displays numbers so its probably the pointer to the string...
the code is as follows
DataCollection.h
typedef struct _DataC
{
char* buffer;
UINT Id;
} DataC;
void GetDataC( int ArrSize, DataC** DArr );
DataCollection.cpp
#include "DataCollection.h"
void GetDataC( int ArrSize, DataC** DArr )
{
int count = 0;
int strSize = 10;
*DArr = (DataC*)CoTaskMemAlloc( ArrSize * sizeof(DataC));
DataC* CurData = *DArr;
char TestS[] = "SomeText00";
for ( int count = 0; count < ArrSize; count++,CurData++ )
{
TestS[strSize-1] = count + '0';
CurData->Id = count;
CurData->buffer = (char*)malloc(sizeof(char)*strSize);
strcpy(CurData->buffer, TestS);
}
}
test the collection:
int main(void)
{
StpWatch Stw;long ResSw;
DataC* TestDataArr;// maybe use DataC TestDataArr[] instead...
GetDataC(100000, &TestDataArr);
}
how can i read the collection within a loop ?
for...
std::cout<<TestDataArr[count].buffer<<std::endl;
or ?
std::cout<<TestDataArr->buffer<<std::endl;
What is the correct implementation to read each element in a loop?
thanks for your time.
DataC* TestDataArr and DataC TestDataArr[] are the same thing. That said, when you try to reference TestDataArr you may do one of two things:
TestDataArr[index].buffer
or
(TestDataArr + index)->buffer
Because TestDataArr is a pointer you must deference it before you may use any of its members, this is what index does. Using the first method, as an array index, the pointer is dereferenced at index in the array and you then may use . to access members of the object. The second method, index advances the pointer to the memory location but does not dereference the pointer, so you must use -> to then access its members.
So to print the buffer in a loop, you could use either:
std::cout << TestDataArr[count].buffer << std::endl;
or
std::cout << (TestDataArr + count)->buffer << std::endl;
The blipping you mention is probably because of TestS[strSize-1] = count + '0'; where count + '0' creates a character outside of the ASCII range. Some of these characters will cause console beeps.
The problem is in TestS[strSize-1] = count + '0';. When you pass ArrSize == 100 0000 then in the for loop the count + '0' value at a some moment exceeds the range of char and you get a char value in the range [0-31] (non-printable characters). At least use
TestS[strSize-1] = '0' + count % (126 - '0');
The last char of TestS will be changed in the range [48-126] (ASCII printable characters).
I have a function like :
char * s;
{
char * i = s, * t;
for(t = s;*t != NULL;t++)
if (*t == '/') i = t+1;
return i;
}
The warning I get is comparison between pointer and integer. How can U resolve it?
Stop treating NULL as a character, it's supposed to be a pointer-type constant.
Your loop header should be:
for(t = s; *t != '\0'; ++t)
This is the "overly explicit" way of writing it, some C programmers aiming for maximum terseness will just say:
for(t = s; *t; ++t)
Since a comparison to '\0' is the same as a comparison to 0, which is implicit in just evaluating the expression. However, I think the != '\0' helps in reading since it makes it clear what's going on, we're looking for the string terminator '\0'. The comparison should be trivially optimized out by any sane compiler.
So, I am learning about pointers via http://cplusplus.com/doc/tutorial/pointers/ and I do not understand anything about the pointer arithmetic section. Could someone clear things up or point me to a tutorial about this that I may better understand.
I am especially confused with all the parentheses things like the difference between *p++,(*p)++, *(p++), and etc.
*p++
For this one, ++ has higher precedence then * so it increments the pointer by one but retrieves the value at the original location since post-increment returns the pointer and then increments its value.
(*p)++
This forces the precedence in the other direction, so the pointer is de-referenced first and then the value at that location in incremented by one (but the value at the original pointer location is returned).
*(p++)
This one increments the pointer first so it acts the same as the first one.
An important thing to note, is that the amount the pointer is incremented is affected by the pointer type. From the link you provided:
char *mychar;
short *myshort;
long *mylong;
char is one byte in length so the ++ increases the pointer by 1 (since pointers point to the beginning of each byte).
short is two bytes in length so the ++ increases the pointer by 2 in order to point at the start of the next short rather than the start of the next byte.
long is four bytes in the length so the ++ increases the pointer by 4.
I found useful some years ago an explanation of strcpy, from Kernighan/Ritchie (I don't have the text available now, hope the code it's accurate): cpy_0, cpy_1, cpy_2 are all equivalent to strcpy:
char *cpy_0(char *t, const char *s)
{
int i = 0;
for ( ; t[i]; i++)
t[i] = s[i];
t[i] = s[i];
i++;
return t + i;
}
char *cpy_1(char *t, const char *s)
{
for ( ; *s; ++s, ++t)
*t = *s;
*t = *s;
++t;
return t;
}
char *cpy_2(char *t, const char *s)
{
while (*t++ = *s++)
;
return t;
}
First you have to understand what post increment does;
The post increment, increases the variable by one BUT the expression (p++) returns the original value of the variable to be used in the rest of the expression.
char data[] = "AX12";
char* p;
p = data;
char* a = p++;
// a -> 'A' (the original value of p was returned from p++ and assigned to a)
// p -> 'X'
p = data; // reset;
char l = *(p++);
// l = 'A'. The (p++) increments the value of p. But returns the original
value to be used in the remaining expression. Thus it is the
original value that gets de-referenced by * so makeing l 'A'
// p -> 'X'
Now because of operator precedence:
*p++ is equivalent to *(p++)
Finally we have the complicated one:
p = data;
char m = (*p)++;
// m is 'A'. First we deference 'p' which gives us a reference to 'A'
// Then we apply the post increment which applies to the value 'A' and makes it a 'B'
// But we return the original value ('A') to be used in assignment to 'm'
// Note 1: The increment was done on the original array
// data[] is now "BXYZ";
// Note 2: Because it was the value that was post incremented p is unchaged.
// p -> 'B' (Not 'X')
*p++
Returns the content, *p, an then increases the pointer's value (postincrement). For example:
int numbers[2];
int *p;
p = &numbers[0];
*p = 4; //numbers[0] = 4;
*(p + 1) = 8; //numbers[1] = 8;
int a = *p++; //a = 4 (the increment takes place after the evaluation)
//*++p would have returned 8 (a = 8)
int b = *p; //b = 8 (p is now pointing to the next integer, not the initial one)
And about:
(*p)++
It increases the value of the content, *p = *p + 1;.
(p++); //same as p++
Increases the pointer so it points to the next element (that may not exist) of the size defined when you declared the pointer.
Recently in an interview i was asked a question to write a function which takes two character arrays(integers) as input and returns the output character array.
Function Signature:
char* find_sum(char* a, char* b)
How would one approach this?
Example scenario:
find_sum("12345","32142") = "44487"
Note:
The number of digits can be many(1-100).
u can add huge numbers using the char array approach. however you need to delete the char* after using it every time or use some smart pointer.
char* find_sum(char* a, char* b) {
int lenA = strlen(a), lenB = strlen(b);
int max = lenA > lenB ? lenA : lenB; // Get the max for allocation
char* res = (char*)malloc (max+2);
memset(res, '0', max +1); // set the result to all zeros
res[max+1] = '\0';
int i=lenA - 1, j = lenB - 1, k = max;
for (; i >= 0 || j >=0; --i, --j, --k) {
int sum = 0;
if (i >= 0 && j>=0)
sum = a[i] - '0' + b[j] - '0' + res[k] - '0' ; // add using carry
else if (j >= 0)
sum = b[j] - '0' + res[k] - '0' ; // add the carry with remaining
else if (i >= 0)
sum = a[i] - '0' + res[k] - '0' ;
res[k] = sum % 10 + '0';
res[k-1] = sum / 10 + '0';
}
return res;
}
int main() {
printf (" sum = %s ", find_sum("12345432409240242342342342234234234", "9934563424242424242423442424234"));
return 0;
}
Note: The precondition for the function is the input char arrays should contain only numbers.
The most obvious answer is internally to use something like atoi and sprintf to convert the numbers to integers, do the sum and return the response as a char* However the important thing here is not what the interviewer is asking but why.
In my experience, the interviewer is probably not wanting you to write a hum-dinger of a solution that covers all angles. What they most likely want to get to is what the most common approach would be, and what are the likely limitations of such a function. I.e.:
What happens if your input numbers aren't integers? (e.g. 13.245, 2.3E+7)
What happens if your 'numbers' aren't numbers at all?
What happens if your input integers are really big? (i.e. ~2^31)
How could you detect an error and how would you report it.
How would you allocate memory for the resultant string?
What would the memory allocation imply for the calling code?
What is the efficiency of the function and how could you make it more efficient?
In this way, the interviewer wants to probe your experience of critiquing approaches to problem solving. Naturally, there are many ways of solving this problem. Some of the approaches have side-effects but in certain contexts, these side effects (i.e. integer overflow) may not be greatly important.
Coding is often a trade off between a comprehensive solution and what can be produced quickly (and therefore less expensively) These questions allow the interviewer to get a feel for your understanding of quality - that is, can you design something that is fit for purpose, robust and yet does not take too long to put together - and also your experience of having to identify / resolve common bugs.
You did not mention anything about not using any external command.
We can do this easily on machines that have the bc command. You can add any number of digits:
$ echo "99999999999999999999999999999999+1" | bc
100000000000000000000000000000000
$
We call this bc from the C program. We need to construct the right command line as
echo "n1+n2" | bc
and then use popen to read its result. Below is the function to do that. The code lacks many error checking.
char* find_sum(char* a, char* b) {
int l1 = strlen(a),l2 = strlen(b);
int cmdLen = l1 + l2 + 30; // 30 to accomodate echo,bc and stuff.
char *cmd = malloc(cmdLen);
snprintf(cmd,cmdLen,"echo \"%s+%s\"|bc",a,b);
FILE *fp = popen(cmd, "r");
int max = (l1 > l2) ? l1:l2;
max += 2; // one for additional digit, one for null.
char *result = malloc(max);
fgets(result, max, fp);
return result;
}
Working link
The answer is probably that you have to ask what is returned? Is this a memory allocated string that should be freed by the user or is this a static memory location that is overwritten the next time the function is called?
char* find_sum(char* a, char* b) {
static char buf[MAX_STRING];
...
return buf;
}
or
char* find_sum(char* a, char* b) {
char *buf = malloc(MAX_STRING*sizeof(char));
...
return buf;
}
Giving this answer shows the interviewer that you know more about C than just making an algorithm. (As a side-node: It also shows why a language like java shines in these situations as the garbage collections takes care of freeing the buffer).
Just remember how you did addition in the second grade on the paper.
#include <stdio.h>
#include <string.h>
char *sum(char *a,char *b);
int main()
{
char a[] = "100";
char b[] = "300";
char *c;
c = sum(a,b);
printf("%s",c);
}
char *sum(char *a,char *b)
{
int x,y,z,z2,zLen;
char *result;
x = atoi(a);
y = atoi(b);
z = x + y;
z2 = z;
/* Determine the length of the string now! */
for(zLen = 1; z > 0 || z < 0; zLen++)
z/=10;
result = (char *)malloc(zLen*sizeof(char)+1);
sprintf(result,"%d\0",z2);
return result;
}
Quick and dirty implimentation. Note that I'm not freeing the memory, which is not "ideal". Will fetch you extra brownie points for mentioning that there are no error checks happening here, and no freeing of memory, which is far from ideal in practical situations.
Online Version of Code
Several of the answers mention the use of atoi & itoa functions.
atoi returns int. Your numbers may not fit into an integer data type.
You may try to alleviate the problem (not completely though) using atol, which return a long int, or atoll, which returns a long long int.
Also, itoa is not a standard library function, and hence may not be available on all systems.
Here's another approach. Nothe that I don't like the prototype for find_sum. I'd very much prefer it to be
char *find_sum(char *dst, size_t len, const char *a, const char *b);
letting the caller be responsible for managing resources.
a and b are strings composed of 1 or more digits (and digits only); the result should be freed by caller. Calling find_sum with invalid inputs causes UB :-)
char *find_sum(char *a, char *b) {
char *res;
int alen, blen, rlen;
int carry;
alen = strlen(a);
blen = strlen(b);
rlen = 1 + ((alen > blen) ? alen : blen);
res = malloc(1 + rlen);
if (res) {
int oldlen = rlen;
res[rlen] = 0;
carry = 0;
while (rlen) {
int tmp;
if (alen && blen) tmp = a[--alen] - '0' + b[--blen] - '0';
else if (alen) tmp = a[--alen] - '0';
else if (blen) tmp = b[--blen] - '0';
else tmp = 0;
tmp += carry;
res[--rlen] = '0' + tmp % 10;
carry = tmp / 10;
}
if (res[0] == '0') memmove(res, res+1, oldlen);
}
return res;
}
There's a working version of the function at ideone ( http://ideone.com/O2jrx ).
itoa(atoi(a) + atoi(b), t, 10); if you want to be lazy, where t is a char[MAX_NUMBER_OF_DIGITS].
The real question regards the output array, as mentioned by other users.