Strings passed to a function not altered by it in the D Language - d

I am a long time C programmer. I have heard about D and have decided to learn it. I like the capabilities it seems to offer. I have come across an issue that has me stumped. I have looked online and haven't found much of an answer. I am trying to pass strings through a function:
module main;
import std.stdio;
import std.string;
int foobar(string s1, string s2)
{
string t1="Hello";
string t2="there";
writeln("t1 = ",t1, " t2 = ", t2);
s1=t1;
s2=t2;
writeln("s1 = ",s1," s2 = ",s2);
return 0;
}
int main(string[] args)
{
string a1;
string a2;
foobar(a1, a2);
writeln("a1 = ",a1," a2 = ",a2);
return 0;
}
The output is as follow:
t1 = Hello t2 = there
s1 = Hello s2 = there
a1 = a2 =
I have tried to search online for an answer can I can't find one. I suspect that I am just not asking the right question. I know I can do this using char strings, but I am trying to do this the "D way". Will somebody point me to a reference that can help with this or tell me the question to ask?
If this has been answered before, I apologize. I probably didn't ask the correct question.
Thank you in advance for your time.
Michael

Add ref to your parameters (e.g., int foobar(ref string s1, ref string s2)). A string is just regular slice to immutable chars so it gets passed around by value. If you want to change the slices they needs to be passed by reference.

Related

How can i fix my eror? i want to overload operator + in array [duplicate]

This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 1 year ago.
I want to overload operator + in array that consider char .I want to print Hello Jack But it has eror in my program . How can I fix it?
class Test
{
private:
char s1, s2;
public:
Test() {}
Test(char a, char b) { s1 = a; s2 = b; }
void Print() { cout << "String1 :" << s1 << "\tString2 :" << s2 << endl; }
Test operator+(const Test& r)
{
Test temp;
temp.s1 = s1 + r.s1;
temp.s2 = s2 + r.s2;
return temp;
}
};
//////////////////////////////////////////////////////////////////////////
int main()
{
char str1[] = "Hello";
char str2[] = " Jack ";
Test t1(str1[]);
Test t2(str2[]);
Test temp;
temp = t1 + t2;
temp.Print();
}
You're defining pretty much everything wrong.
Your +operator overload sums up the two chars that are part of the "Test", but you only ever pass one of the two to separate Test objects.
If you want to use strings, use std::string instead of arrays of chars, unless you have a particular reason to do so, but at this point this is the least of your problems.
friend Test operator+(Test lhs, const Test& rhs) is how you'd define the return of a new object based on the values of two of the same objects.
You'd then have no need for a print function as it would just be put as-is in an iostream once you override that functionality as well, which would really amount to just returning the stored string (string singular, you only need one per object here).
In its current state, I highly doubt your code even compiles as you are passing one argument to an object that only takes none or two.

C: Attempting to copy pointer values into another pointer, getting modifiable lvalue error

I am learning C and am getting stuck. Basically I have 2 arrays declared and I want to copy all of the char values of one array into the other by using pointers. I am taking advantage of the fact that the array name is a pointer to its first element. Could someone please take a look and help? Thank you.
#include<stdio.h>
#include<string.h>
char *mystrcopy(char*p, char*q); //function prototype
int main(void)
{
char s1[20] = "Hello\n";
char s2[20] = "Bye\n";
puts(s1); //print Hello
mystrcopy(s1, s2); //call function using pointers s1 and s2
puts(s1); //I want this to print Bye after function has run
system("pause"); //"press any key to continue...."
return 0;
}
char *mystrcopy(char*s1, char*s2)
{
int i;
for (i = 0; s1 + i; i++) //for loop continues as long as s1+1 not 0
s1 + i = s2 + i; //error says s1 is not a modifiable lvalue
return s1; //I know this could be a void function but I choose not to
}
I thought this would be fine since (s1 + i) is a pointer pointing at the ith element in the array s1, and replacing it with the ith element in s2.
I tried using
*(s1+i) = *(s2+i)
instead, so copying the address of s2 into s1, but I get the same error.
EDIT:
The above code in the for loop actually worked
*(s1+i) = *(s2+i)
I think this didn't work because the loop that kept going. However, thanks everyone for answering my question on modifiable l value.
Something like this will get you started. Notice we have to dereference the char* in the copy. This assumes fixed length strings and so doesn't need to use malloc nor strlen functions from std library. Not ideal but something you can play with to get going.
#include<stdio.h>
#include<string.h>
char *mystrcopy(char* p, char* q); //function prototype
#define LENGTH 20
int main(void){
char s1[LENGTH] = "Hello\n";
char s2[LENGTH] = "Bye\n";
puts(s1); //print Hello
mystrcopy(s1, s2);
puts(s1); //I want this to print Bye after function has run
// system("pause"); //"press any key to continue...."
return 0;
}
char *mystrcopy(char* s1, char* s2)
{
int i;
for (i = 0; i < LENGTH; i++, ++s1, ++s2) //for loop continues as long as s1+1 not 0
*s1 = *s2; //error says s1 is not a modifiable lvalue
return s1; //I know this could be a void function but I choose not to
}
Since s1 is a pointer, then s1 + 1 is also yields a pointer too (just a temporary one whose address has been moved.
If we put some intermediary variables in place, then your loop is effectively going to be equivalent to:
for (i = 0; s1 + i; i++)
{
char* t1 = s1 + i;
char* t2 = s2 + i;
t1 = t2;
}
A major factor to note there is that it's not changing anything in the data being pointed to. It's only assigning the value of one pointer to another.
Now when taking a look back at s1 + 1 = anything, that's trying to assign something to a temporary pointer (not to what the temporary pointer points to). So the compiler complains as a safeguard because trying to assign to a temporary is always a mistake.
So knowing what you really wanted to do (and also noting that the loop condition of s1 + 1 is not reading the value being pointed to, the code needs to be adjusted. For this type of situation, the array-like syntax allowed with pointers is much more convenient that trying to work in terms of incrementing the pointers themselves. Thus you would end up with something like:
for (i = 0; s1[i]; i++)
{
s1[i] = s2[i];
}
As a bonus consideration, your logic copies from s2 to s1 but the loop is conditional on s1. So what is going to happen if initial data in s1 is shorter than what is in s2? Perhaps your loop condition should be in terms of s2.
And a future consideration is what if the arrays pointed to be s1 and s2 aren't the same size. What kinds of problems can occur? Perhaps your function could take an additional parameter that specifies the maximum size of s1.
A final consideration is these kinds of things are where std::string makes it easier and safer than doing it yourself with char arrays.

boost::any with structs and unsigned ints

There are several parts to my question. I have been researching on how/when to use boost::any. I was wondering if it is possible to assign a struct to a boost::any variable.
Example:
struct S {
int x;
};
S s;
s.x = 5;
boost::any var = s;
It would seem to me that this is possible but it leads me to my next question. If this is a valid assignment, then how would I access the data member x? var is not a struct type since it is boost::any.
My next question is not dependent on whether the data member can be accessed or not. The question then is, what if variable a is of type uint8_t.
Example: Edit: as pointed out in the comments, the code below does support uint8_t but it is not printed. See uint8_t can't be printed with cout.
uint8_t a = 10;
boost::any b = a;
std::cout << boost::any_cast<uint8_t>(b);
I found that it is possible to use boost::any_cast but have not found that it supports unsigned types. When I tried using boost::any_cast<uint8_t>() it did not print, but did not throw an error. Is it possible to get the value of a type like uint8_t using boost? If so how?
I will continue reading more documentation of boost::any but if anyone has insight, details, or notes on these questions or the subject, please post as I would love to learn more about how this works. Thanks!
I was wondering if it is possible to assign a struct to a boost::any variable
It is.
How would I access the data member x?
You would access with any_cast<S>(var).x. Continuing your example:
int& the_x_member = any_cast<S>(var).x;
std::cout << "s.x is " << the_x_member << "\n";
What if variable a is of type uint8_t?
It's perfectly possible to assign an unsigned integer type to a boost::any (or std::any, which does the same thing but with somewhat different syntax).
When I tried using boost::any_cast<uint8_t>() it did not print, but did not throw an error.
Wouldn't that "print" a \0 character? So it would look like nothing was printed.
Is it possible to get the value of a type like uint8_t using Boost? If so how?
Just like you'd expect:
uint8_t u = 234;
boost::any ba = u;
std::cout << "u is " << (int) boost::any_cast<uint8_t>(ba) << '\n';
This does indeed work.

Passing a variable to function for reference an array into

I need to call function which contains many cases.
I'd like to pass it a variable which can reference different arrays.
This example demonstrates more clearly what I'm trying to achieve:
void bob(int debut, int fin, string flag){
string arrayflag = "pfhistory_FR_" + flag;
for (i = debut; i < fin; i++){
std::cout << arrayflag[i].DP << endl
}
};
If you want a variable which can reference different array's, you are require a 2D array. A 2D array can be thought of as an array of arrays, and you can index the arrays using a variable.
Roughly speaking C++ is a statically-bound language. This means that objects are resolved at compile time, not run time. As such, what you're trying to do is not possible in C++, but has to be implemented manually. Something like this:
void bob(int debut, int fin, string flag){
auto *arrayflag =
flag == "1" ? prhistory_FR_1 :
flag == "2" ? prhistory_FR_2 :
prhistory_FR_3;
for (i = debut; i < fin; i++){
std::cout << arrayflag[i].DP << endl
}
};
But this has all the markings of XY problem. You probably are asking something completely different, except that you think that this approach is the answer to your real question. But it's not. Whatever you're trying to do, the real answer is most likely something else. You just need to figure out what you're really asking.

What is the equivalent of CPython string concatenation, in C++? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Simple string concatenation
Yesterday, as I'm writing this, someone asked on SO
if i have a string x='wow'
applying the function add in python :
x='wow'
x.add(x)
'wowwow'
how can i do that in C++?
With add (which is non-existent) corrected to __add__ (a standard
method) this is a deep and interesting question, involving both subtle low
level details, high level algorithm complexity considerations, and
even threading!, and yet it’s formulated in a very short and concise way.
I am reposting
the original question
as my own because I did not get a chance to provide a correct
answer before it was deleted, and my efforts at having the original question revived, so
that I could help to increase the general understanding of these issues, failed.
I have changed the original title “select python or C++” to …
What is the equivalent of CPython string concatenation, in C++?
thereby narrowing the question a little.
The general meaning of the code snippet.
The given code snippet
x = 'wow'
x.__add__( x )
has different meanings in Python 2.x and Python 3.x.
In Python 2.x the strings are by default narrow strings, with one byte per encoding unit,
corresponding to C++ char based strings.
In Python 3.x the strings are wide strings, guaranteed to represent Unicode,
corresponding to the in practice usage of C++
wchar_t based strings, and likewise with an unspecified 2 or 4 bytes
per encoding unit.
Disregarding efficiency the __add__ method behaves the same in both main
Python versions, corresponding to the C++ + operator for std::basic_string
(i.e., for std::string and std::wstring), e.g. quoting the CPython 3k
documentation:
object.__add__(self, other)
… to evaluate the expression x + y, where x is an instance of a class that has an __add__() method, x.__add__(y) is called.
So as an example, the CPython 2.7 code
x = 'wow'
y = x.__add__( x )
print y
would normally be written as
x = 'wow'
y = x + x
print y
and corresponds to this C++ code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
auto const x = string( "wow" );
auto const y = x + x;
cout << y << endl;
}
A main difference from the many incorrect answers given for
the original question,
is that the C++ correspondence is an expression, and not an update.
It is perhaps natural to think that the method name __add__ signifies a change
of the string object’s value, an update, but with respect to observable
behavior Python strings are immutable strings. Their values never change, as
far as can be directly observed in Python code. This is the same as in Java and
C#, but very unlike C++’s mutable std::basic_string strings.
The quadratic to linear time optimization in CPython.
CPython 2.4 added
the following
optimization, for narrow strings only:
String concatenations in statements of the form s = s + "abc" and s += "abc"
are now performed more efficiently in certain circumstances. This optimization
won't be present in other Python implementations such as Jython, so you shouldn't
rely on it; using the join() method of strings is still recommended when you
want to efficiently glue a large number of strings together. (Contributed by Armin Rigo.)
It may not sound like much, but where it’s applicable this optimization
reduces a sequence of concatenations from quadratic time O(n2)
to linear time O(n), in the length n of the final result.
First of all the optimization replaces concatenations with updates, e.g. as if
x = x + a
x = x + b
x = x + c
or for that matter
x = x + a + b + c
was replaced with
x += a
x += b
x += c
In the general case there will be many references to the string object that x
refers to, and since Python string objects must appear to be immutable, the first
update assignment cannot change that string object. It therefore, generally, has
to create a completely new string object, and assign that (reference) to x.
At this point x holds the only reference to that object. Which means that the
object can be updated by the update assignment that appends b, because there are
no observers. And likewise for the append of c.
It’s a bit like quantum mechanics: you cannot observe this dirty thing
going on, and it’s never done when there is the possibility of anyone observing
the machinations, but you can infer that it must have been going on by the statistics that
you collect about performance, for linear time is quite different from quadratic time!
How is linear time achieved? Well, with the update the same strategy of buffer
doubling as in C++ std::basic_string can be done, which means that the
existing buffer contents only need to be copied at each buffer reallocation,
and not for each append operation. Which means that the
total cost of copying is at worst linear in the final string size, in the
same way as the sum (representing the costs of copying at each buffer doubling)
1 + 2 + 4 + 8 + … + N is less than 2*N.
Linear time string concatenation expressions in C++.
In order to faithfully reproduce the CPython code snippet in C++,
the final result and expression-nature of the operation be should captured,
and also its performance characteristics should be captured!
A direct translation of CPython __add__ to C++ std::basic_string + fails
to reliably capture the CPython linear time. The C++ + string concatenation
may be optimized by the compiler in the same way as the CPython
optimization. Or not – which then means that one has told a beginner that
the C++ equivalent of a Python linear time operation, is something with quadratic
time – hey, this is what you should use…
For the performance characteristics C++ += is the basic answer, but, this does
not catch the expression nature of the Python code.
The natural answer is a linear time C++ string builder class that translates
a concatenation expression to a series of += updates, so that the Python code
from __future__ import print_function
def foo( s ):
print( s )
a = 'alpha'
b = 'beta'
c = 'charlie'
foo( a + b + c ) # Expr-like linear time string building.
correspond to roughly
#include <string>
#include <sstream>
namespace my {
using std::string;
using std::ostringstream;
template< class Type >
string stringFrom( Type const& v )
{
ostringstream stream;
stream << v;
return stream.str();
}
class StringBuilder
{
private:
string s_;
template< class Type >
static string fastStringFrom( Type const& v )
{
return stringFrom( v );
}
static string const& fastStringFrom( string const& s )
{ return s; }
static char const* fastStringFrom( char const* const s )
{ return s; }
public:
template< class Type >
StringBuilder& operator<<( Type const& v )
{
s_ += fastStringFrom( v );
return *this;
}
string const& str() const { return s_; }
char const* cStr() const { return s_.c_str(); }
operator string const& () const { return str(); }
operator char const* () const { return cStr(); }
};
} // namespace my
#include <iostream>
using namespace std;
typedef my::StringBuilder S;
void foo( string const& s )
{
cout << s << endl;
}
int main()
{
string const a = "alpha";
string const b = "beta";
string const c = "charlie";
foo( S() << a << b << c ); // Expr-like linear time string building.
}