C string setting character array to argv[1] - c

if I have a program as follows:
int main(int argc, char** argv) {
char s[32] = argv[1];
printf("entered char is %s\n", s);
}
Why do I get an error: array initializer must be an initializer list or string literal, during compile time?
Isn't argv[1] a string and isn't is legal to do
char s[32] = "A test string"

You can't initialize an array using a pointer like that. Instead you have to copy the string after declaration:
char s[32];
strcpy(s, argv[1]);
Note that you should really check if at least one argument is provided before doing that (by checking argc). Also note that unless you want to modify the string provided in the argument, there's really no need to keep a second copy of the string.
Oh and you might want to use strncpy instead of plain strcpy, to avoid a possible buffer overflow situation. Remember that strncpy will not terminate the string if the source is to long, so you need to do it explicitly.

Expression char s[32] = argv[1]; causes error because by doing s=argv[1] you are trying to change base address of s, which is not possible as s is constant pointer.
Use strcpy() to copy argv[1] into s
char s[32];
strcpy(s,argv[1]);

Asking a question like this means - you are not aware of certain rules. In C, there are a few possible ways you can initialize an array. And the compiler told you about that when it saw it violating the rule. It says it must be string literal or initializer list. The one you provided is not any of this. It is simply a pointer and you can't initialize an array by putting it in the right side of the = assignment operator.
char s[]="hello";
char s[]={'h','e','\0'};
Select one as shown above. First is using literal and second using initializer list. In your case you can't use any of these - what's the way? strcpy at your rescue. Before you use like the other answer showed make sure buffer is big enough to hold stuff you copy.

Related

String not assignable to char array in C

Hello I am very new to C and I have a simple question. Why does the second method of assigning a string to char name2[] not work? It causes a compilation error saying "Array type 'char[20]' is not assignable".
int main() {
char name[20] = "Alex";
char name2[20];
name2 = "Alex"; //error!
}
Why does the second method of assigning a string to char name2[] not work? It causes a compilation error saying "Array type 'char[20]' is not assignable".
There is no "second method" presented. This ...
char name[20] = "Alex";
... does not demonstrate an assignment, but rather an initialization. The = within is not functioning as the assignment operator, but rather as part of the syntax for specifying the initial value that name will take. And yes, this is a common source of confusion for newcomers to C.
On the other side, it is not possible to assign to whole arrays in C (this also is a common source of confusion for newcomers). This is the reason for the compilation error. You can copy the contents of one array into another with, for example, strcpy() or memcpy(), but there are almost no operators that accept arrays as operands. C arrays have more surprises to offer you, too, but I won't spoil them.
Once you understand C's idiosyncratic treatment of arrays, I think you'll see that it's internally consistent. Until then, however, you would do well to be alert whenever you see or use an array.
Arrays do not have the assignment operator. Instead you need to copy the string from one array to another like
#include <string.h>
//...
strcpy( name2, name );
Or just to copy the string literal using the same function strcpy
strcpy( name2, "Alex" );
On the other hand, you can assign the address of the string literal to a pointer like
char *name2;
name2 = "Alex";
In this case you may not change the string literal using the pointer.
Assuming you want to define a different string, and not just copy the previous one (assuming you used the same name as an example), you can use the scanf command:
#include <stdio.h>
int main()
{
char name[20] = "alex";
char name2[20];
printf("Type the name: \n");
scanf("%s", name2);
printf("name is %s. name2 is %s",name, name2);
return 0;
}
In this case it will be required an user input (you will need to write the name on the terminal).

Why we didn't use * during dereferencing the pointer?

In the below code, we get a pointer from strdup(source) and we store it in a pointer named target.
Now, when we print the string using pointer, we don't add * at the beginning of the pointer: why is it so? As I studied whenever we want to dereference any pointer we use *pointer_name. If we add * in the below code, we get an error.
I am very beginner, so pls ans in easy words.
#include<stdio.h>
#include<string.h>
int main()
{
char source[] = "Programming";
char* target = strdup(source);
printf("%s\n",target);
return 0;
}
printf expects a char pointer in the place of the %s specifier.
https://en.cppreference.com/w/c/io/fprintf
char* target = strdup(source);
printf("%s\n",target);
Why we don't use *target in the code above?
The explanation is quite simple, as already stated in previous answers: target has type char pointer, which is exactly what printf() wants in the above call.
Now, printf() is a little complicated because its semantic is not simple - basically it accepts zero or more arguments after the first, of any type (possibly applying promotion). But if we use strdup() again, maybe it is simpler:
char* target2 = strdup(target);
Here, if you wrote strdup(*target), the compiler might warn that you are passing a char instead of a pointer to char.
strdup() returns a char*, hence the char* type of target. target holds a pointer to the first character in an array of chars. printf("%s", string) expects string to be a char*, so there’s no reason to do anything to target; just pass it to printf().
If you dereferenced target, you would get a single char (P in this case). printf() would then complain that you had supplied a character instead of a string (pointer to character). Even worse, the program could compile, and then printf() would try to print the string at address P (0x50), which would result in probably unwanted behaviour.
When working with arrays—a string is a type of array—you rarely want to dereference the array.

How do i determine the length of a string if it's declared as const char *str?

I have the following function structure
int function(const char *str)
{
return 0;
}
I never could fully understand why people use char *str rather than simply string str. So I am guessing this basically means that the argument is the pointer to the first character of the string. How do I determine the length of the string str given that argument?
What I've tried is to iterate through str, if I hit a NULL or "" or '', then that will be the end of it. However, none of these types are compatible for comparison. Please give me some clue regarding this. Thx!
Jamesdlin's answer is good, but to answer your question about comparisons, you would use '\0', IE:
char* a = "a";
int size = 0;
while (a[size] != '\0')
size++;
NULL is a pointer macro, "" is an empty character array (Though it has an implicit '\0', so you could theoretically do strcmp(a, "");), and '' is just an empty character, I'm not sure that it's even a valid statement.
Also, std::string is a C++ class and does not exist in the C standard library.
In C, strings are typically NUL-terminated. For NUL-terminated strings, you can simply call strlen(str).
I never could fully understand why people use char *str rather than simply string str.
There is no string type in C. You could add a typedef:
typedef char* string;
But adding typedefs for pointer types is generally a bad idea (because now you need a separate typedef for const char*; const string would not be the same thing).
And while doing so might seem like a good idea, in practice it will obscure your code since char*/const char* for strings is the norm.
You are almost correct, char *str is a pointer to the first character of a char array, but C has no predefined string type - it's just a zero-terminated char array. Instead of trying to write a function (although it would be a good student exercise), just call the library function in <string.h> with strlen (str); which takes a pointer to the character array. You don't pass *str or &str but just str if it is a declared array variable. If memory was allocated dynamically, you pass the allocated pointer, so if the pointer was declared as char *memstr you pass it as memstr. As others have said, it's best not to try to define a string, better to understand how the char array works.

Convert struct field to unsigned char string

I'm on an embedded system so do not have access to a most of the standard library. I have a struct which contains char values.
I have a simple print function which simply outputs an unsigned char string to an attached screen. It does not support format specifiers like printf does.
This is the struct:
typedef struct my_options{
char test;
} my_options;
And this is where I'm trying to output the value:
struct my_options options;
print(options.test); //Here I get "implicit conversion of int to ptr"
How do I achieve this?
Create a char array to hold your char and then print it:
char wrapper[2];
wrapper[0] = options.test;
wrapper[1] = '\0';
print(wrapper);
Create a temporary 2-character long string that has the character to print, and then the terminator. Then pass that string to your print() function:
void print_options(const struct my_options *opt)
{
char tmp[] = { opt->test, '\0' };
print(tmp);
}
your member test if of the type char, where the print function expects an argument of the type const char * (assuming the const bit here, but that's what I'd expect, this as an asside). Passing the address of test then would seem like the appropriate solution, but is it?
No, of course it isn't. There is no absolute guarantee that the next byte after test will be '\0' (a string terminating char). What you, then, ought to do is create a wrapper string:
char char_wrapper[2] = {};//initializes according to standard
//but as Lundin pointed out, self-documenting code is important:
char_wrapper[0] = options.test;?
char_wrapper[1] = '\0';//explicit, so it's clear what this code does
print(char_wrapper);
That should work just fine.
You can, of course, write this as a one-liner:
char char_wrapper[2] = {options.test, '\0'};//same as before, only in 1 statement
print(char_wrapper);//print "string"
That should do it, really. You don't even have to explicitly write the terminating char, since the standard specifically states:
An array of character type may be initialized by a character string literal, optionally
enclosed in braces. Successive characters of the character string literal (including the
terminating null character if there is room or if the array is of unknown size) initialize the
elements of the array.
6.7.8 Initialization cf p. 138, semantics, point 14
Be that as it may, I'd still prefer to browse the web, or just set about writing your own minor implementation of printf so you can use format specifiers. Heck, it's one of the first exercises in the K&R book, and there's tons of solutions floating about on the net. check those out, and adapt them to your specific needs.
Or, perhaps define print to accept a size_t argument, to specify how many chars you want to pass to the output stream. and call it like so print(options.test, 1);
print is looking for a char*. You are passing an char which can also be represented as an int. Thus, the function is trying to implicitly convert an int to a pointer as it is telling you.
char ptr[2];
ptr[0] = options.test;
ptr[1] = '\0';
Would wrap the char into a char array, which in C will decay into a pointer when you pass it to a function.

How to change a character in a string using pointers?

im having troubles with this code
int main() {
char *My_St = "abcdef";
*(My_St+1)='+';
printf("%s\n",My_St);
return 0;
}
i built this code and has no errors, but when i try to run it, it throws a segmentation fault, could someone tell what's wrong
You can't because you are trying to modify const data.
change it to:
char My_St[] = "abcdef";
Then you will be able to change it.
Think about what you were doing, you were declaring a pointer that pointed to "abcdef". It IS a pointer, not an array of chars. "abcdef" lives in the farm, I mean, in the .text area of your program and that is immutable.
When you do it the way I've shown, you are telling the compiler: i'm declaring this array, that will have as many chars as are needed to accommodate "abcdef" and also, as you are there, copy "abcdef" to it.
You provided a hint to the compiler by declaring My_St with type char *. Assigning a string literal to this pointer essentially makes it a const char * because a string literal cannot be modified, meaning the memory location is read-only. Writing to that read-only memory location is what is producing your segfault. Change it from char *My_St to char My_St[] to get it working.
char *My_St refers to constant memory, most likely. You will need to dynamically allocate your string and then fill it (using strcpy).
char *str = malloc(7);
strcpy(str, "abcdef");
Or
char *str = strdup("abcdef");
And then it is safe to modify str.
The basics are correct, however your character string is (behind the scenes) constant and can't be modified. You'd have to define a array of chars (e.g. char[20]), copy the string into it and then modify the character.
To be 100% correct you'd have to write const char *My_St = "abcdef"; which makes it clearer that you can't do what you're trying to do.

Resources