From what I understand cin.getLine gets the first char(which I think it a pointer) and then gets that the length. I have used it when cin for a char. I have a function that is returning a pointer to the first char in an array. Is there an equivalent to get the rest of the array into a char that I can use the entire array. I explained below what I am trying to do. The function works fine, but if it would help I could post the function.
cmd_str[0]=infile();// get the pointer from a function
cout<<"pp1>";
cout<< "test1"<<endl;
// cin.getline(cmd_str,500);something like this with the array from the function
cout<<cmd_str<<endl; this would print out the entire array
cout<<"test2"<<endl;
length=0;
length= shell(cmd_str);// so I could pass it to this function
You could use a string stream:
char const * p = get_data(); // assume null-terminated
std::istringstream iss(std::string(p));
for (std::string line; std::getline(iss, line); )
{
// process "line"
}
If the character array is not null-terminated but has a given size N, say std::string(p, N) instead.
First, if cmd_str is an array of char and infile returns a pointer to a string, that first assignment will give you an error. It tries to assign a pointer to a single char.
What you seem to want is strncpy:
strncpy(cmd_str, infile() ARRAY_LENGTH - 1);
cmd_str[ARRAY_LENGTH - 1] = '\0';
I make sure to add the string terminator to the array, because if strncpy copies all ARRAY_LENGTH - 1 characters, it will not append the terminator.
If cmd_str is a proper array (i.e. declared like char cmd_str[ARRAY_LENGTH];) then you can use sizeof(cmd_str) - 1 instead of ARRAY_LENGTH - 1 in my example. However, if cmd_str is passed as a pointer to a function, this will not work.
Related
I have a function that has the following signature
void serialize(const string& data)
I have an array of characters with possible null values
const char* serializedString
(so some characters have the value '\0')
I need to call the given function with the given string!
What I do to achieve that is as following:
string messageContents = string(serializedString);
serialize(messageContents.c_str());
The problem is the following. The string assigment ignores all characters occuring after the first '\0' character.
Even If I call size() on the array I get the number of elements before the first '\0'.
P.S. I know the 'real' size of the char array (the whole size of the arrray containing the characters including '\0' characters)
So how do I call the method correctly?
Construct the string with the length so it doesn't only contain the characters up to the first '\0' i.e.
string messageContents = string(serializedString, length);
or simply:
string messageContents(serializedString, length);
And stop calling c_str(), serialize() takes a string so pass it a string:
serialize(messageContents);
Otherwise you'll construct a new string from the const char*, and that will only read up to the first '\0' again.
When you pass char arrays as arguments and try to find the length of the array, it returns the length without the null operator?
For example, if I passed charArray[4] = "aaa" and found the length of this using strlen, the returned value would be 3. Why is this so?
More detailed example below:
#include <iostream>
using namespace std;
int main() {
void function(char[]);
char charArray[4] = "aaa";
function(charArray);
cin.get();
return 0;
}
void function (char *array)
{
size_t index = 0;
index = strlen(array);
std::cout << index; // prints value: 3
}
You are confusing char arrays with the behavior of string literals, c-style strings respectively.
strlen() operates on NUL terminated character arrays and doesn't count the terminating \0 character by definition:
Returns the length of the given null-terminated byte string, that is, the number of characters in a character array whose first element is pointed to by str up to and not including the first null character.
The behavior is undefined if str is not a pointer to a null-terminated byte string.
To get the size of an array use sizeof() like so:
char arr[4] = "abc";
cout << sizeof(arr) << endl;
You should note that the above sample will not give you correct results, as soon the array is decayed to a pointer that is passed to a function:
char arr[4] = "abc";
void func(char* arr)
{
cout << sizeof(arr) << endl; // Prints the size of the pointer variable itself
}
Such functions need to get the array size from an extra parameter:
void func(char* arr, size_t arrsize)
{
// ...
}
If you think of the null as more of an implementation detail, that might help.
If you know std::string at all, you want length() to return the actual length. Every other major language has a string of some sort, and they all have a function to get the length.
Also, you really want strlen(a+b) == strlen(a) + strlen(b), otherwise a lot of operations get a bit more complicated. You only want to count a null once. When you strcat.
strlen does not return the length with the null character because the null character determines where the C string ends in memory.
(ie it is not part of the string, it tells the runtime where the string ends).
See:
https://en.wikipedia.org/wiki/String_%28computer_science%29#Null-terminated
https://en.wikipedia.org/wiki/Null-terminated_string
I'm just starting c++ and am having difficulty understanding const char*. I'm trying to convert the input in the method to string, and then change the strings to add hyphens where I want and ultimately take that string and convert it back to char* to return. So far when I try this it gives me a bus error 10.
char* getHyphen(const char* input){
string vowels [12] = {"A","E","I","O","U","Y","a","e","i","o","u","y"};
//convert char* to string
string a;
int i = 0;
while(input != '\0'){
a += input[i];
input++;
i++;
}
//convert a string to char*
return NULL;
}
A: The std::string class has a constructor that takes a char const*, so you simply create an instance to do your conversion.
B: Instances of std::string have a c_str() member function that returns a char const* that you can use to convert back to char const*.
auto my_cstr = "Hello"; // A
std::string s(my_cstr); // A
// ... modify 's' ...
auto back_to_cstr = s.c_str(); // B
First of all, you don't need all of that code to construct a std::string from the input. You can just use:
string a(input);
As far as returning a new char*, you can use:
return strdup(a.c_str()); // strdup is a non-standard function but it
// can be easily implemented if necessary.
Make sure to deallocate the returned value.
It will be better to just return a std::string so the users of your function don't have to worry about memory allocation/deallocation.
std::string getHyphen(const char* input){
Don't use char*. Use std::string, like all other here are telling you. This will eliminate all such problems.
However, for the sake of completeness and because you want to understand the background, let's analyse what is going on.
while(input != '\0'){
You probably mean:
while(*input != '\0') {
Your code compares the input pointer itself to \0, i.e. it checks for a null-pointer, which is due to the unfortunate automatic conversion from a \0 char. If you tried to compare with, say, 'x' or 'a', then you would get a compilation error instead of runtime crashes.
You want to dereference the pointer via *input to get to the char pointed to.
a += input[i];
input++;
i++;
This will also not work. You increment the input pointer, yet with [i] you advance even further. For example, if input has been incremented three times, then input[3] will be the 7th character of the original array passed into the function, not the 4th one. This eventually results in undefined behaviour when you leave the bounds of the array. Undefined behaviour can also be the "bus error 10" you mention.
Replace with:
a += *input;
input++;
i++;
(Actually, now that i is not used any longer, you can remove it altogether.)
And let me repeat it once again: Do not use char*. Use std::string.
Change your function declaration from
char* getHyphen(const char* input)
to
auto hyphenated( string const& input )
-> string
and avoid all the problems of conversion to char const* and back.
That said, you can construct a std::string from a char_const* as follows:
string( "Blah" )
and you get back a temporary char const* by using the c_str method.
Do note that the result of c_str is only valid as long as the original string instance exists and is not modified. For example, applying c_str to a local string and returning that result, yields Undefined Behavior and is not a good idea. If you absolutely must return a char* or char const*, allocate an array with new and copy the string data over with strcpy, like this: return strcpy( new char[s.length()+1], s.c_str() ), where the +1 is to accomodate a terminating zero-byte.
I have a char array with known size (say 10) and I want to convert it to a strng. The main point is the array is not NULL terminated so this technique that used in the following sample code can not be used.
char arr[ ] = "This is a test";
string str(arr);
I can do this:
char * array=getArray();
string output;
for(int I=0;i<10;i++)
{
output.append(array[I]);
}
or even better one is:
char * array=getArray();
string output;
output.append(10,array);
But is there any better way to do this?
If you don't have a nul-terminated string, but you know its length, you can use either the two iterator constructor:
string str(arr, arr + len);
or the appropriate count constructor:
string str(arr, len);
First of all, "This is a test" is NIL-terminated and the first sample just works - the compiler implicitly stores string literals with zero termination.
If your array really is not NIL-terminated, the third approach will be good while the second is rather inefficient because it appends piecewise. std::string also has a constructor that takes a count: std::string(array, 10).
Okay, so I'm working on a memory editor in c++, I have a list of offsets and if I predefine what to change the offset too (0x68) then it works, but I was wondering if there was a way to convert string, as in, cin >> string, and it would split the string into bytes or char*s so it could use them in the offsets? Sorry if this doesn't make much sense.
The std::string class has two methods that can help you:
c_str(), that returns a \0-terminated char* string (AKA a "C"-style string);
data(), that returns the content of the string in a char const*, but without \0 termination; you have to retrieve the length separately with length() or size().
You can call c_str() to get a raw char array representing the string data as a c string.
You can use data() and memcpy() to copy all the bytes to another address, or access the bytes in the string by indexing the string object...
std::string x;
if (std::cin >> x) // note: read one whitespace-separated token, use getline for lines
{
memcpy(p_dest, x.data(), x.size()); // to copy everything...
// ...or...
p_dest[offset] = x[i]; // copy one character, 0 <= i < x.size()
}