I am trying to write my own string class for an assignment, and I was wondering how I should treat the argument of "".
For example, if there is a call of:
s = myString("")
what is the length, and what are the contents of the char* holding the data in my 'myString' class?
The char * passed to you will be a pointer to an "null" terminated list of char's which, most likely, will be a single, immutable char whose value is 0 (or "null").
For example...
const char* s = "";
char value = *s;
int length = strlen(s);
... should result in...
s == [compiler defined]
!value == true
length == 0
Related
As I know, if we declare char* in our program then it gives memory from read-only area, so we are not able to change a char at any position in the array.
char *ch = "sitaram";
ch[2] = 'y';
The above code will not run properly, as we are changing read-only memory.
One approach is we can declare our char array as
char ch[] = "sitaram";
and then we can change a value at an index.
Is there any way where I can change a char value at any index in a char*?
Use the modern C++ approach for mutable string values
std::string str{"sitaram"};
str[2] = 'y';
String literals (i.e. values enclosed in "") are by default of type const char[n] (where n is the length of the string literal +1 for the null character) in C++ and because of that they are immutable, any attempt to modify them results in undefined behavior.
When you say:
char *ch = "sitaram";
The compiler does the following:
it allocates the string "sitaram" at program start (static storage duration). This string can be put into read-only memory.
when your program arrives at this line, it allocates the pointer ch, and makes this pointer to point to the statically allocated "sitaram" string.
if you do ch[2] = 'y', then you're trying to modify the 3rd character of the statically allocated string. Usually, you get a crash (because it is in read-only memory)
On the other hand, if you do the following:
char ch[] = "sitaram";
When the program hit this line, it allocates memory for the array ch[] (for 8 chars), then copies the string "sitaram" into this memory. If you do ch[2] = 'y', then you modify this allocated memory, which is perfectly fine to do.
If you want to modify a string with char *, it should point to a memory which is modifiable. For example:
char ch[] = "sitaram";
char *xx = ch;
xx[2] = 'y'; // it is the same as ch[2] = 'y';
Using char arrays:
char text[] = "sitaram";
text[3] = 'o';
char * p = &text[0];
p[4] = 'x';
cout << text;
I want to use mbstowcs_s method but without iostream header. Therefore I cannot use strlen to predict the size of my buffer. The following method has to simply change c-string to wide c-string and return it:
char* changeToWide(char* value)
{
wchar_t* vOut = new wchar_t[strlen(value)+1];
mbstowcs_s(NULL,vOut,strlen(val)+1,val,strlen(val));
return vOut;
}
As soon as i change it to
char* changeToWide(char* value)
{
wchar_t* vOut = new wchar_t[sizeof(value)];
mbstowcs_s(NULL,vOut,sizeof(value),val,sizeof(value)-1);
return vOut;
}
I get wrong results (values are not the same in both arrays). What is the best way to work it out?
I am also open for other ideas how to make that conversion without using strings but pure arrays
Given a char* or const char* you cannot use sizeof() to get the size of the string being pointed by your char* variable. In this case, sizeof() will return you the number of bytes a pointer uses in memory (commonly 4 bytes in 32-bit architectures and 8 bytes in 64-bit architectures).
If you have an array of characters defined as array, you can use sizeof:
char text[] = "test";
auto size = sizeof(text); //will return you 5 because it includes the '\0' character.
But if you have something like this:
char text[] = "test";
const char* ptext = text;
auto size2 = sizeof(ptext); //will return you probably 4 or 8 depending on the architecture you are working on.
Not that I am an expert on this matter, but char to wchar_t conversion being made is seemingly nothing but using a wider space for the exact same bytes, in other words, prefixing each char with some set of zeroes.
I don't know C++ either, just C, but I can derive what it probably would look like in C++ by looking at your code, so here it goes:
wchar_t * changeToWide( char* value )
{
//counts the length of the value-array including the 0
int i = 0;
while ( value[i] != '\0' ) i++;
//allocates enough much memory
wchar_t * vOut = new wchar_t[i];
//assigns values including the 0
i = 0;
while ( ( vOut[i] = 0 | value[i] ) != '\0' ) i++;
return vOut;
}
0 | part looks truly obsolete to me, but I felt like including it, don't really know why...
Is there a function in Phobos for converting a zero-terminated string into a D-string?
So far I've only found the reverse case toStringz.
I need this in the following snippet
// Lookup user name from user id
passwd pw;
passwd* pw_ret;
immutable size_t bufsize = 16384;
char* buf = cast(char*)core.stdc.stdlib.malloc(bufsize);
getpwuid_r(stat.st_uid, &pw, buf, bufsize, &pw_ret);
if (pw_ret != null) {
// TODO: The following loop maybe can be replace by some Phobos function?
size_t n = 0;
string name;
while (pw.pw_name[n] != 0) {
name ~= pw.pw_name[n];
n++;
}
writeln(name);
}
core.stdc.stdlib.free(buf);
which I use to lookup the username from a user id.
I assume UTF-8 compatiblity for now.
There's two easy ways to do it: slice or std.conv.to:
const(char)* foo = c_function();
string s = to!string(foo); // done!
Or you can slice it if you are going to use it temporarily or otherwise know it won't be written to or freed elsewhere:
immutable(char)* foo = c_functon();
string s = foo[0 .. strlen(foo)]; // make sure foo doesn't get freed while you're still using it
If you think it can be freed, you can also copy it by slicing then duping: foo[0..strlen(foo)].dup;
Slicing pointers works the same way in all array cases, not just strings:
int* foo = get_c_array(&c_array_length); // assume this returns the length in a param
int[] foo_a = foo[0 .. c_array_length]; // because you need length to slice
Just slice the original string (no coping). The $ inside [] is translated to str.length. If the zero is not at the end, just replace the "$ - 1" expression with position.
void main() {
auto str = "abc\0";
str.trimLastZero();
write(str);
}
void trimLastZero (ref string str) {
if (str[$ - 1] == 0)
str = str[0 .. $ - 1];
}
You can do the following to strip away the trailing zeros and convert it to a string:
char[256] name;
getNameFromCFunction(name.ptr, 256);
string s = to!string(cast(char*)name); //<-- this is the important bit
If you just pass in name you will convert it to a string but the trailing zeroes will still be there. So you cast it to a char pointer and voila std.conv.to will convert whatever it meets until a '\0' is encountered.
I have a const char* variable which takes values from a function that I have wrote.
When I write this variable to a file many times it writes nothing. So it must be empty or filled in with space.The strange thing is that in the txt file that I write it changes line every time, when it has value or not.Why is that?Does it mean that the returned value from the function has a \n?
how can I check if a value of a const char * is empty or in general how can I check character by character the value in char*?
Since C/C++ pointers can be interpreted as arrays of values the pointers point to, the two ways of checking values of a char* is by applying an indexing operator or by using pointer arithmetics. You can do this:
const char *p = myFunctionReturningConstChar();
for (int i = 0 ; p[i] ; i++) {
if (p[i] == '\n') printf("New line\n");
}
or this:
const char *p = myFunctionReturningConstChar();
while (*p) {
if (*p == '\n') printf("New line\n");
p++;
}
In addition, C++ library provides multiple functions for working with C strings. You may find strlen helpful to check if your pointer points to an empty string.
I'm trying to get integer or bool from database result this way:
bool tblexist = false;
int t_exists = 0;
tblexist = (bool)sqlite3_column_text(chkStmt, 1);
t_exists = atoi(sqlite3_column_text(chkStmt, 1));
... but no one works.
Expected value from sqlite3_column_text(chkStmt, 1) is always 0 or 1.
But I get error message:
invalid conversion from ‘const unsigned char*’ to ‘const char*’
initializing argument 1 of ‘int atoi(const char*)’
||=== Build finished: 2 errors, 0 warnings ===|
How to solve this and get integer or bool on elegant way?
The first line, trying to convert to bool will always return true, as a string pointer will always be "true" if it's not NULL. If you want to use this there are a couple of ways to handle this:
// 1. Dereference pointer to get first character in string
tblexist = (*sqlite3_column_text(chkStmt, 1) != '0');
// 2. Using string comparison
tblexist = (strcmp(sqlite3_column_text(chkStmt, 1), "0") != 0);
For the second, try this instead:
t_exists = atoi((const char *) sqlite3_column_text(chkStmt, 1));
This is because sqlite3_column_text returns the type const unsigned char * but atoi wants const char *.
First of all, the columns are indexed beginning with zero, so unless the query requested two (or more) columns, sqlite3_column_text(..., 1) returns the second column.
Secondly, the function returns a pointer to a character string, so you have to dereference the value from the pointer, and convert the string there:
const char *data = sqlite3_column_text(chkStmt, 0);
int val = atoi (data); // for ascii representation of a number
atoi or similar conversion would be expensive to use.
const unsigned char _TRUE = '1';
const unsigned char* dbDATA = sqlite3_column_text(chkStmt, 1);
bool exists = (_TRUE == dbDATA[0]); //i assume you are expecting "0" or "1" from DB