Supply maximum string length to a function - c++

When defining a function which has a char array as one of its arguments, is it recommended to always pass the maximum array length as well as an extra argument? For example:
int somefunction(char* inputarray, int maxsizeofarray)

C-style strings are usually terminated by the \0 character. Most, if not all, of the functions from the standard library, such as strcpy or strcmp expect (and honor!) this convention. I'd suggest that any new function you write adhere to the same convention.
Having said that, in C++ (as opposed to C), I wouldn't use char* at all. Instead, I'd use the standard std::string class.

It totally depends on the function.Example, when you are traversing char array from last element to first element, in that case,it is wise to pass the size. But in C only.In C++, you have std::string .

It's normal to pass the array size when the function is writing to the array, or when it's problematic for the function to determine the size thereof (because it's not necessarily following a convention such as having a NUL terminator). For example:
int read(char* buffer, size_t n);
char *strncat(char *dest, const char *src, size_t n);
struct BinaryBlob
{
BinaryBlob(const char* buffer, size_t n);
...
};

Related

how character pointer could be used to point a string in c++?

First of all I am beginner in C++. I was trying to learn about type casting in C++ with strings and character pointer. Is it possible to point a string with a character pointer?
int main() {
string data="LetsTry";
cout<<(&data)<<"\n";
cout<<data<<"\n"<<"size "<<sizeof(data)<<"\n";
//char *ptr = static_cast<char*>(data);
//char *ptr=(char*)data;
char *ptr = reinterpret_cast<char*>(&data);
cout<<(ptr)<<"\n";
cout<<*ptr;
}
The above code yields outcome as below:
0x7ffea4a06150
LetsTry
size 32
`a���
`
I understand as ptr should output the address 0x7ffea4a06150
Historically, in C language strings were just a memory areas filled with characters. Consequently, when a string was passed to a function, it was passed as a pointer to its very first character, of type char *, for mutable strings, or char const *, if the function had no intent to modify string's contents. Such strings were delimited with a zero-character ((char)0 a.k.a. '\0') at the end, so for a string of length 3 you had to allocate at least four bytes of memory (three characters of the string itself plus the zero terminator); and if you only had a pointer to a string's start, to know the size of the string you'd have to iterate it to find how far is the zero-char (the standard function strlen did it). Some standard functions accepted en extra parameter for a string size if you knew it in advance (those starting with strn or, more primitive and effective, those starting with mem), others did not. To concatenate two strings you first had to allocate a sufficient buffer to contain the result etc.
The standard functions that process char pointers can still be found in STL, under the <cstring> header: https://en.cppreference.com/w/cpp/header/cstring, and std::string has synonymous methods c_str() and data() that return char pointers to its contents, should you need it.
When you write a program in C++, its main function has the header of int main(int argc, char *argv[]), where argv is the array of char pointers that contains any command-line arguments your program was run with.
Ineffective as it is, this scheme could still be regarded as an advantage over strings of limited capacity or plain fixed-size character arrays, for instance in mid-nineties, when Borland introduced the PChar type in Turbo Pascal and added a unit that exported Pascal implementations of functions from C's string.h.
std::string and const char* are different types, reinterpret_cast<char*>(&data) means reinterpret the bits located at &data as const char*, which is not we want in this case.
so assuming we have type A and type B:
A a;
B b;
the following are conversion:
a = (A)b; //c sytle
// and
a = A(b);
// and
a = static_cast<A>(b); //c++ style
the following are bit reinterpretation:
a = *(A*)&b; //c style
// and
a = *reinterpret_cast<A*>(&b); //c++ style
finally, this should works:
int main() {
string data = "LetsTry";
const char *ptr = data.c_str();
cout<< ptr << "\n";
}
bit reinterpretation is sometimes used, like when doing bit manipulation of a floating point number, but there are some rules to follow like this one What is the strict aliasing rule?
also note that cout << ptr << "\n"; is a specially case because feeds a pointer to std::cout usually output the address that pointer points to, but std::cout treats char* specially so that it output the content of that char array instead
In C++, string is class and what you doing is creating a string object. So, to use are char * you need to convert it using c_str()
You can refer below code:
std::string data = "LetsTry";
// declaring character array
char * cstr = new char [data.length()+1];
// copying the contents of the
// string to char array
std::strcpy (cstr, data.c_str());
Now, you can get use char * to point your data.

How to avoid providing length along with char*?

There is a function which sends data to the server:
int send(
_In_ SOCKET s,
_In_ const char *buf,
_In_ int len,
_In_ int flags
);
Providing length seems to me a little bit weird. I need to write a function, sending a line to the server and wrapping this one such that we don't have to provide length explicitly. I'm a Java-developer and in Java we could just invoke String::length() method, but now we're not in Java. How can I do that, unless providing length as a template parameter? For instance:
void sendLine(SOCKET s, const char *buf)
{
}
Is it possible to implement such a function?
Use std string:
void sendLine(SOCKET s, const std::string& buf) {
send (s, buf.c_str(), buf.size()+1, 0); //+1 will also transmit terminating \0.
}
On a side note: your wrapper function ignores the return value and doesn't take any flags.
you can retrieve the length of C-string by using strlen(const char*) function.
make sure all the strings are null terminated and keep in mind that null-termination (the length grows by 1)
Edit: My answer originally only mentioned std::string. I've now also added std::vector<char> to account for situations where send is not used for strictly textual data.
First of all, you absolutely need a C++ book. You are looking for either the std::string class or for std::vector<char>, both of which are fundamental elements of the language.
Your question is a bit like asking, in Java, how to avoid char[] because you never heard of java.lang.String, or how to avoid arrays in general because you never heard of java.util.ArrayList.
For the first part of this answer, let's assume you are dealing with just text output here, i.e. with output where a char is really meant to be a text character. That's the std::string use case.
Providing lenght seems to me a little bit wierd.
That's the way strings work in C. A C string is really a pointer to a memory location where characters are stored. Normally, C strings are null-terminated. This means that the last character stored for the string is '\0'. It means "the string stops here, and if you move further, you enter illegal territory".
Here is a C-style example:
#include <string.h>
#include <stdio.h>
void f(char const* s)
{
int l = strlen(s); // l = 3
printf(s); // prints "foo"
}
int main()
{
char* test = new char[4]; // avoid new[] in real programs
test[0] = 'f';
test[1] = 'o';
test[2] = 'o';
test[3] = '\0';
f(test);
delete[] test;
}
strlen just counts all characters at the specified position in memory until it finds '\0'. printf just writes all characters at the specified position in memory until it finds '\0'.
So far, so good. Now what happens if someone forgets about the null terminator?
char* test = new char[3]; // don't do this at home, please
test[0] = 'f';
test[1] = 'o';
test[2] = 'o';
f(test); // uh-oh, there is no null terminator...
The result will be undefined behaviour. strlen will keep looking for '\0'. So will printf. The functions will try to read memory they are not supposed to. The program is allowed to do anything, including crashing. The evil thing is that most likely, nothing will happen for a while because a '\0' just happens to be stored there in memory, until one day you are not so lucky anymore.
That's why C functions are sometimes made safer by requiring you to explicitly specify the number of characters. Your send is such a function. It works fine even without null-terminated strings.
So much for C strings. And now please don't use them in your C++ code. Use std::string. It is designed to be compatible with C functions by providing the c_str() member function, which returns a null-terminated char const * pointing to the contents of the string, and it of course has a size() member function to tell you the number of characters without the null-terminated character (e.g. for a std::string representing the word "foo", size() would be 3, not 4, and 3 is also what a C function like yours would probably expect, but you have to look at the documentation of the function to find out whether it needs the number of visible characters or number of elements in memory).
In fact, with std::string you can just forget about the whole null-termination business. Everything is nicely automated. std::string is exactly as easy and safe to use as java.lang.String.
Your sendLine should thus become:
void sendLine(SOCKET s, std::string const& line)
{
send(s, line.c_str(), line.size());
}
(Passing a std::string by const& is the normal way of passing big objects in C++. It's just for performance, but it's such a widely-used convention that your code would look strange if you just passed std::string.)
How can I do that, unless providing lenght as a template parameter?
This is a misunderstanding of how templates work. With a template, the length would have to be known at compile time. That's certainly not what you intended.
Now, for the second part of the answer, perhaps you aren't really dealing with text here. It's unlikely, as the name "sendLine" in your example sounds very much like text, but perhaps you are dealing with raw data, and a char in your output does not represent a text character but just a value to be interpreted as something completely different, such as the contents of an image file.
In that case, std::string is a poor choice. Your output could contain '\0' characters that do not have the meaning of "data ends here", but which are part of the normal contents. In other words, you don't really have strings anymore, you have a range of char elements in which '\0' has no special meaning.
For this situation, C++ offers the std::vector template, which you can use as std::vector<char>. It is also designed to be usable with C functions by providing a member function that returns a char pointer. Here's an example:
void sendLine(SOCKET s, std::vector<char> const& data)
{
send(s, &data[0], data.size());
}
(The unusual &data[0] syntax means "pointer to the first element of the encapsulated data. C++11 has nicer-to-read ways of doing this, but &data[0] also works in older versions of C++.)
Things to keep in mind:
std::string is like String in Java.
std::vector is like ArrayList in Java.
std::string is for a range of char with the meaning of text, std::vector<char> is for a range of char with the meaning of raw data.
std::string and std::vector are designed to work together with C APIs.
Do not use new[] in C++.
Understand the null termination of C strings.

Finding the length of a character array in c++ [duplicate]

This question already has answers here:
How do I use arrays in C++?
(5 answers)
Closed 8 years ago.
I have an character array of the form
char x[]='asdasdadsadasdas';
int p = sizeof(x)/sizeof(*x)
gives me correct result but when I pass this as an argument in another function like
void X(char* a)
int i = sizeof(a)/sizeof(*a)
and I call it
X(x)
p and i are not equal.How is it possible ?
When the char array gets passed to a function accepting a char*, the array is said to 'decay' to a pointer. This conversion is automatic, and the length information which was previously statically available to the compiler is lost.
Possible solutions are:
Pass the size of the array as an additional parameter.
Make the char-Array 0-terminated (i.e., a string literal) and use strlen. This is the common ways of operating on strings in C and C++. However, this introduces runtime cost which is not strictly necessary. However it provides some convenience (same API for statically and dynamically sized strings) and error resilience (the length is always correct).
Use templates to capture the length of the array. This is explained here..
void X(char* a)
int i = sizeof(a)/sizeof(*a)
Here, a is a pointer and *a is a char. So sizeof(a) won't return the size of the array, but the size of the pointer to the first element in the array.
In order to find the length of the string (which isn't the same as "the size of the array"), you have a few options.
One, don't use a char* at all, but a std::string (may create a temporary):
void X (const std::string& s)
{
size_t i = s.length();
}
Two, scan the string for the null-terminator (linear complexity):
void X (const char* p)
{
size_t i = strlen (p);
}
Three, use a template (needlessly complex code):
template <size_t N> void X (const char (&arr)[N])
{
size_t i = N;
}
Each of the above has it's own set of cons. But this is all best avoided if you take a broader look at your program and see where you can make improvements. Here's one that stands out to me:
char x[]='asdasdadsadasdas';
C-style arrays present their own problems and are best avoided altogether. Instead of using a C-style array, use a tool from the StdLib designed for just this problem:
std::string x = "asdasdadsadasdas";
sizeof(char *)
Gives you the size of a pointer. Eight bytes on my system.
char x[] = "fred";
sizeof(x);
Returns 5. The size of the string with the null termination.
void x(char * c) {
sizeof (*c);
}
Returns the size of a a char.
This is true no matter what the length or original type of the array is passed to void x(). Note that sizeof() is evaluated at compile time. At compile time the compiler cannot normally know what length of array it's been passed. For a run-time evaluation of string length, as said above, use strlen if you actually want the strings length in characters. (Or a template - but that's probably a more unusual solution).

Delphi function and equivalent in C++

Old library was written in Delphi. Now I'm trying to write library in c++.
Below there is function in Delphi's library:
function MyFunction(Path:string; Options:PInteger; var Data: array of Byte):Integer; stdcall;
How should this function look in C++? Is below declariation right?
int __stdcall MyFunction(char* Path, int* Options, char* Data);
The big problem is the buffer. Your Delphi function passes an open array. This is implemented by passing both the array length, and the pointer to the first element. Your C++ translation does not do that. You'll need to pass an extra parameter specifying the length of the array.
Since you can expect that the function will not modify Path you would likely declare the first parameter as const char*.
So, the function would then look like this:
int __stdcall MyFunction(const char* Path, int* Options, size_t len, char* Data);
Now, if you are expecting that the function is to be binary interchangeable with the original C++ version you have a problem. You'd need to match the internal implementation of a Delphi open array. You can do that. The function would become:
int __stdcall MyFunction(const char* Path, int* Options, char* Data, int high);
Note that the length parameter appears after the pointer to the first element, and is named high. That's because a Delphi open array receives high(A) rather than Length(A).
You really must get out of the habit of passing Delphi specific types across interop boundaries.
Of course, I'm assuming here that you are still creating a library for interop and this function is at the interop boundary. If the function is internal then the declaration would perhaps be:
void MyFunction(const std::string &path, int &options,
const std::vector<char> &data);
There's no need for a return value since errors can be signalled with exceptions. Strings are stored in std::string, and a byte array in C++ is std::vector<char>.

How to pass a vector of strings to execv

I have found that the easiest way to build my program argument list is as a vector of strings. However, execv expects an array of chars for the second argument. What's the easiest way to get it to accept of vector of strings?
execv() accepts only an array of string pointers. There is no way to get it to accept anything else. It is a standard interface, callable from every hosted language, not just C++.
I have tested compiling this:
std::vector<string> vector;
const char *programname = "abc";
const char **argv = new const char* [vector.size()+2]; // extra room for program name and sentinel
argv [0] = programname; // by convention, argv[0] is program name
for (int j = 0; j < vector.size()+1; ++j) // copy args
argv [j+1] = vector[j] .c_str();
argv [vector.size()+1] = NULL; // end of arguments sentinel is NULL
execv (programname, (char **)argv);
The prototype for execv is:
int execv(const char *path, char *const argv[]);
That means the argument list is an array of pointers to null-terminated c strings.
You have vector<string>. Find out the size of that vector and make an array of pointers to char. Then loop through the vector and for each string in the vector set the corresponding element of the array to point to it.
I stumbled over the same problem a while ago.
I ended up building the argument list in a std::basic_string<char const*>. Then I called the c_str() method and did a const_cast<char* const*> on the result to obtain the list in a format that execv accepts.
For composed arguments, I newed strings (ordinary strings made of ordinary chars ;) ), took their c_str() and let them leak.
The const_cast is necessary to remove an additional const as the c_str() method of the given string type returns a char const* const* iirc. Typing this, I think I could have used std::basic_string<char*> but I guess I had a reason...
I am well aware that the const-casting and memory leaking looks a bit rude and is indeed bad practise, but since execv replaces the whole process it won't matter anyway.
Yes, it can be done pretty cleanly by taking advantage of the internal array that vectors use. Best to not use C++ strings in the vector, and const_cast string literals and string.c_str()'s to char*.
This will work, since the standard guarantees its elements are stored contiguously (see https://stackoverflow.com/a/2923290/383983)
#include <unistd.h>
#include <vector>
using std::vector;
int main() {
vector<const char*> command;
// do a push_back for the command, then each of the arguments
command.push_back("echo");
command.push_back("testing");
command.push_back("1");
command.push_back("2");
command.push_back("3");
// push NULL to the end of the vector (execvp expects NULL as last element)
command.push_back(NULL);
// pass the vector's internal array to execvp
execvp(command[0], const_cast<char* const*>(command.data()));
return 1;
}
Code adapted from: How to pass a vector to execvp
Do a const_cast to avoid the "deprecated conversion from string constant to 'char*'". String literals are implemented as const char* in C++. const_cast is the safest form of cast here, as it only removes the const and does not do any other funny business. execvp() will not edit the values anyway.
If you want to avoid all casts, you have to complicate this code by copying all the values to char* types not really worth it.
Although if the number of arguments you want to pass to execv/execl is known, it's easier to write this in C.
You can't change the how execv works (not easily anyway), but you could overload the function name with one that works the way you want it to:
int execv(const string& path, const vector<string>& argv) {
vector<const char*> av;
for (const string& a : argv) {
av.push_back(a.c_str());
av.push_back(0);
return execv(path.c_str(), &av[0]);
}
Of course, this may cause some confusion. You would be better off giving it a name other than execv().
NB: I just typed this in off the top of my head. It may not work. It may not even compile ;-)