Since a string literal can be initialized like
char myString [] = "somestring";
it seems logical to be able to use a function like
int stringLength ( char * str )
{
char * c2 = str;
while (*c2++);
return (c2-str);
}
and call it like
printf("%d",stringLength("somestring"));
However, I get an error when I do that.
Is there some way I can "cast" "something" into something proper to input into the function, or do I always have use an extra line like
char str [] = "somestring";
printf("%d",stringLength(str));
or is there something else I should be doing altogether?
char myString [] = "somestring";
creates an array of characters that are modifiable.
When you use
printf("%d",stringLength("somestring"));
it is analogous to:
char const* temp = "somestring";
printf("%d",stringLength(temp));
That's why the compiler does not like it.
You can change the function to use a char const* as argument to be able to use that.
int stringLength ( char const* str )
{
char const* c2 = str;
while (*c2++);
return (c2-str);
}
You know that your function "stringLength" will never mutate/change the contents of the string right so make that function so
int somefunc(const char* ptr)
{
const char* base=ptr;
while(*(ptr++));
return (ptr-base);
}
int main()
{
printf("%d",somefunc("HELLO"));
return 0;
}
Related
Can anyone please help me? I need to remove the first character from a const char * in C.
For example, const char * contents contains a 'x' character as the first character in the array. I need to detect and eliminate this character, modifying the original variable after its been "sanitized".
Can anyone suggest how to achieve it? I'm completely new to C (though I know Java), and just can't seem to figure it out.
Note: I already referred to these, and still not able to figure out:
How to remove first character from C-string? - this tell how to remove when the input is char * contents
AND
Difference between char* and const char*?
it mentions that const char* is a mutable pointer but points to immutable character/string
What I tried below it works, but why it works?(it should not able to modify the immutable char array contents value "xup")
#include <stdio.h>
int main()
{
char input[4] = "xup";
removeLeadingX(input);
return 0;
}
int removeLeadingX(const char * contents)
{
//this if condition is something I have to add
//can't modify other code (ex: the method receives const char * only)
if(contents[0] == 'x'){
contents++;
}
printf(contents);//up - why immutable string "xup" updated to "up"?
return 0;
}
You can't remove anything from the const char object.
You need to make a copy of the string and then modify and use the copy
const char *original = "Hello world!";
char *copy = strdup(original);
copy[strlen(copy) - 1] = 0; //removing `!`
You can modify the pointer to reference other element of the string. But you lose the original pointer and actually do not remove anything from the string.
const char *original = "Hello world!";
original = strchr(original, 'w');
printf("%s\n", original);
What I tried below it works, but why it works?(it should not able to
modify the immutable char array contents)
In your example you modify the pointer not the object referenced by the pointer. It is OK.
If you declare this function as
void removeLeadingX(const char * const contents)
the pointer will also be const and your code will not compile.
Do you need to remove the leading character, or simply ignore it.
Here's an example of what the function is doing (simply changing the pointer)
int main() {
char input[4] = "xup";
char *p = input;
printf( "advance\n" );
p = p + 1;
printf( "input: '%s'\n", input );
printf( "p: '%s'\n", p );
printf( "retreat\n" );
p = p - 1;
printf( "input: '%s'\n", input );
printf( "p: '%s'\n", p );
printf( "nothing has been removed or shifted except the pointer 'p'\n" );
return 0;
}
Output:
advance
input: 'xup'
p: 'up'
retreat
input: 'xup'
p: 'xup'
nothing has been removed or shifted except the pointer 'p'
The function declaration int removeLeadingX(const char * contents) doesn't make any sense. Either the function should modify the passed string "in place", in which case the function should be:
void removeLeadingX (char* contents)
Or the function should store a modified copy of the original (immutable) string somewhere, in which case the function could be:
void removeLeadingX (char* new_str, const char* old_str)
These could be implemented as:
void removeLeadingX (char* contents)
{
if(contents[0]) == 'x')
memmove(&contents[0], &contents[1], 1);
}
Or:
void removeLeadingX (char* new_str, const char* old_str)
{
if(old_str[0] == 'x')
{
// assuming new_str points at a caller-allocated array:
strcpy(new_str, &old_str[1]);
}
}
Considering that the original object in main is not const, you can modify the array using a dirty trick to avoid warnings:
#include <stdio.h>
#include <string.h>
int removeLeadingX(const char *contents)
{
if (contents[0] == 'x')
{
union {const char *constant; char *not_constant;} dummy = {contents};
memmove(dummy.not_constant, contents + 1, strlen(contents));
}
printf("%s\n", contents);
return 0;
}
int main(void)
{
char input[4] = "xup";
removeLeadingX(input);
return 0;
}
Looking at this code from The Evils of Arduino Strings
void PrintString(const char *str) {
const char *p;
p = str;
while (*p) {
Serial.print(*p);
p++;
}
}
I was looking at reducing/compacting it. Firstly, this seems to be equivalent:
void PrintString(const char *str) {
const char *p;
p = str;
while (*p)
Serial.print(*p++);
}
Now, looking at the first two lines, how can I combine the following two lines, is it possible?
const char *p;
p = str;
Can I do this?
const char *p = str;
This would seem likely but looks unbalanced, in that there is a lack of an asterisk on the right hand side. I tried it and it seems to work but I was wondering whether it was correct, and worried that I would end up with some hard-to-track-down run-time error later on, further down the line.
However, this line below is clearly wrong (as it would change the pointer p to point to a location given by the value of the first character of the C string str):
const char *p = *str;
This is obfuscation. The original code is perfectly clear, there is no need to change anything. Your changes make it less readable.
What you can do to increase readability slightly, and this is a cosmetic change, is to use a for loop instead:
void PrintString (const char *str)
{
for(const char* p=str; *p != '\0'; p++)
{
Serial.print(*p);
}
}
Alternatively:
void PrintString (const char *str)
{
for(size_t i=0; str[i] != '\0'; i++)
{
Serial.print(str[i]);
}
}
const char *p = str;
This would seem likely but looks unbalanced, in that there is a lack of an asterisk on the right hand side.
If you separated the elements of the above snippet correctly it would not look "unbalanced" at all:
const char* is the type (a pointer to const characters)
p and str are the variables, both pointer (to const char)
You could write the above using some unconventional layout like this:
const char * /* Note the lack of a semicolon */
p = str;
The above code ends up with p being defined as a pointer to char and carrying the value of str.
You get same "result" for the below code
const char *p;
p = str;
Note that the former is called "initialisation", whereas the latter is called "assignment".
You can omit the use of the p pointer, use directly the str pointer argument, since it is a copy of the pointer to the constant content.
The changes made on str pointer don't affect the pointer used when calling the function, since the pointer is passed by value.
void PrintString(const char *str) {
while (*str) Serial.print(*str++);
}
How about replacing the while with for. Here's my take:
void PrintString(const char *str)
{
for(const char* p = str; *p; p++)
Serial.print(*p);
}
I think this could work, too:
void PrintString(const char *str) {
for(const char* p = str; *p; Serial.print(*(++p)))
;
}
As others have pointed out, we can replace p with str, since str is a local copy, just like any other variable passed as function argument.
void PrintString(const char* str) {
for( ; *str; Serial.print(*(++str)))
;
}
I need an entire string to be one char of another string.
const char *const_string = "FOOBAR";
char *character_string = malloc(1024);
// character_string = const_string[3];
How can I make the last (commented) line work?
It seems you mean the following
void do_something(char *str, int idx)
{
str[0] = glob_str[idx];
str[1] = '\0';
}
You can add a check to the function that the index is not outside the string literal pointed to by glob_str.
Given
char *glob_str = "test test"; // glob_str is literal string and cannot be modified
then
glob_str[0] = val; // modification won't work
You need to change to
char glob_str[] = "test test";
See this question
How would I append a char to string that has no initial value in the following method I've started:
void append(char a) {
const char *str;
char *ret = malloc (strlen(str)+2);
strncpy(str,strlen(str),ret);
ret[strlen(str)-2] = a;
ret[strlen(str)-1] = 0;
printf("%s", str);
}
I've tried a few different answers to other questions but none have worked, please help.
Since the pointer str is not initialized, you can't add characters to what it points at. What makes sense depends on what you're going to do next. Since you don't return a value from the function, you can't access the string to which a is appended unless append calls some other function.
char *str; is not a string. It is a mnemonic that says that *str will give you a value which is supposedly a character.
str is a pointer that points at random. Make it point to an allocated bunch of memory first.
Do something like- str = malloc(100); and then do a *(str+1) = a and then a *(str+2) = '\0' to NULL terminate the string.
how about something like:
char * append(char a, const char * str)
{
char *ret = malloc (strlen(str)+2);
strncpy(str,strlen(str),ret);
ret[strlen(str)-2] = a;
ret[strlen(str)-1] = 0;
return ret;
}
I have a simple C function which I declare as:
int strLen(const char* str_)
{
str_ = (char*) 0;
return 0;
}
I was very surprised that that compiles! Why is that?
Whereas this onedoesn't compile (which makes sense):
int str(const int i_)
{
i_ = 0;
return 0;
}
Because const char* str_ says that str_ is a pointer to const characters.
You can change str_ itself, but not what it points to.
int strLen(const char* str_)
{
str_ = (char*) 0; /* allowed */
str_[0] = '\0'; /* not allowed */
return 0;
}
In the first one, you are changing what the pointer str_ points to; the pointer str_ is not const; it just points to const data. You can make the pointer const as follows:
int strLen(const char* const str_)
This follows the conventions of C declarations,
char *str;
means that *str will give you a char (or in other words, str is a pointer-to-a-char). Similarly,
const char *str;
means that *str will give you a const char, or in other words, str is a pointer-to-a-constant-char. So, you are not allowed to change *str, but you may change str.
If you want to make str itself const, use the following syntax:
char *const str;