This question already has answers here:
Assigning char array a value in C
(2 answers)
Closed 8 years ago.
i have just started learning C and i am confused on how to write a string into a simple char array in C. i understand that C does not have a string data type, and i read that most websites declare string in one of this way
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
char greeting[] = "Hello";
however what if i have initialized a char array of
char greeting[50];
and i try to give it a string value.
char greeting[50];
greeting = "Zack";
i am given a error, why?
strcpy is designed to copy "strings".
Use as follows:
char greeting[50];
strcpy(greeting, "Zack");
Be aware of potential overruns if the destination isn't big enough.
Use standard function strcpy declared in header <string.h> that to copy a string in a character array
#include <string.h>
//...
char greeting[50];
strcpy( greeting, "Zack" );
There are other functions declared in header <string.h> that also can be used to copy strings in character arrays. For example
memcpy
strncpy
strcat
strncat
An example of using strcat instead of strcpy
#include <string.h>
//...
char greeting[50];
greeting[0] = '\0';
strcat( greeting, "Zack" );
Arrays have no the assignment operator. So the compiler issues an error for this code snippet
char greeting[50];
greeting = "Zack";
But there is a trick when you may assign character arrays. To do that you need to enclose a character array in a structure and use a compound literal. For example. Contrary to arrays structures have the assignment operator that performs member-wise copy of structure.
#include <stdio.h>
#include <string.h>
int main(void)
{
struct A { char greeting[50]; } s;
s = ( struct A) { "Zack" };
puts( s.greeting );
return 0;
}
The output will be
Zack
That this code would be compiled you need a compiler that supports C99.
You use strcpy():
char greeting[50];
strcpy(greeting, "Zack");
This will copy the four characters and the terminating zero into greeting.
Beware that it knows nothing about the available space at greeting, so it's perfectly possible to do the wrong thing.
You're getting an error because you're basically trying to assign a string constant to an array. The array greeting decays to a pointer, but it's a char *const pointer.
You need to use strcpy to copy the literal.
In C, the folowing code will print "foo":
char greeting[50];
if(greeting == &greeting[0]){
printf("foo");
}
else{
printf("bar");
}
This happens because the variable of the array (greeting) contains a pointer to the first element of it (greeting[0]).
So, if you asign:
greeting = "Zack";
You are saying: Let greeting have the address of where the literal string "Zack" is in the memory.
As changing the address of a array is not allowed, you get an error.
Related
Generally, you can initialize a pointer with any string literals like char *str = "Hello". I think this means "Hello" returns the address of 'H'. However, the below isn't allowed.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char name[64];
} Student;
Student initialization(char *str) {
//Student tmp = {}; strcpy(tmp.name, str) //(*1)This is allowed.
//Student tmp = {"Hello"}; //(*2)This is allowed.
Student tmp = {str}; //(*3)This is not allowed.
return tmp;
}
int main(void) {
(...)
}
Could anyone tell me the reason why (*2) is allowed but (*3) is not allowed? Compiling this code makes the error below.
warning: initialization makes integer from pointer without a cast [-Wint-conversion]
Student tmp = {str};
^
All these cases you are trying to initialize a char array. Now after saying that - we can see it makes thing easier. Just like an char array where if we write down a string literal directly it initializes the char array with the content of the string literal.
But in the second case, the string literal which is basically a char array is converted to a pointer to the first element of it (the fist character of string literal) which is then used to initialize the char array. That will not work. Note that, even if str is a pointer to a char array which is not a literal this won't work. For the same reason as specified. Standard allows initialization from the string literal directly. Not other way round.
From standard 6.7.9p14
An array of character type may be initialized by a character string literal or UTF-8 string literal, optionally enclosed in braces. Successive bytes of the 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.
I know the C language has dynamic length strings whereby it uses the special character null (represented as 0) to terminate a string - rather than maintaining the length.
I have this simple C code that creates a string with the null character in the fifth index:
#include <stdio.h>
#include <stdlib.h>
int main () {
char * s= "sdfsd\0sfdfsd";
printf("%s",s);
s[5]='3';
printf("%s",s);
return 0;
}
Thus, a print of the string will only output up to the fifth index. Then the code changes the character at the fifth index to a '3'. Given my understanding, I assumed it would print the full string with the 3 instead of the null, as such:
sdfsdsdfsd3sfdfsd
but instead it outputs:
sdfsdsdfsd
Can someone explain this?
This program exhibits undefined behavior because you modify a read-only string literal. char* s = "..." makes s point to constant memory; C++ actually disallows pointing non-const char* to string literals, but in C it's still possible, and we have to be careful (see this SO answer for more details and a C99 standards quote)
Change the assignment line to:
char s[] = "sdfsd\0sfdfsd";
Which creates an array on the stack and copies the string to it, as an initializer. In this case modifying s[5] is valid and you get the result you expect.
String literals can not be changed because the compiler put the string literals into a read-only data-section (but this might vary by underlying platform). The effect of attempting to modify a string literal is undefined.
In your code:
char * s= "sdfsd\0sfdfsd"
Here, s is char pointer pointing to a string "sdfsd\0sfdfsd" stored in read-only memory, making it immutable.
Here you are trying to modify the content of read-only memory:
s[5]='3';
which leads to undefined behavior.
Instead, you can use char[]:
#include <stdio.h>
int main () {
char a[] = "sdfsd\0sfdfsd";
char * s = a;
printf("%s",s);
s[5]='3';
printf("%s\n",s);
return 0;
}
This operation has failed:
s[5] = 3;
You're trying to change a string literal, which is always read-only. My testing shows the program exited with segfault:
Segmentation fault (core dumped)
You should store it in an array (or allocated memory) before any attempts to change it:
char s[] = "sdfsd\0sfdfsd";
With the above change, the program works as intended.
#include <stdio.h>
int main(){
char x[10] = "aa\0a";
x[2] = '1';
puts(x);
printf("\n\n\nPress any key to exit...");
getch();
return 0;
}
Output: aa1a
I have to read a string, to concatenate with another and print the result
I tried this code:
int main(){
char s= "StackOverflow ";
char ss[100];
fgets(ss,100,stdin);
// i know i can use strcat but i don't want it here
printf("%s%s",s,ss);
return 0;
}
the ss is "is the best site for learning things!"
Some help?
First of all, you have to make your program compilable, as compilation gives some errors.
1.) s must be defined as char *s or char s[] because char s only allows one character to be stored there, and not an array. char *s declares a pointer to the string literal and char s[] declares an array of characters of as many as present in the string literal and initializes it with the characters of the specified string literal.
2.) stdin is a global variable of type FILE * (actually it isn't but it behaves as) that represent the standard input. If you don't declare it, the compiler doesn't know where the stdin identifier came from, so it issues an error. The way to eliminate this second error is to #include <stdio.h> which has a definition for it and makes the compiler happy.
Once you do these two steps, your program is:
#include <stdio.h>
int main(){
char s[]= "StackOverflow ";
char ss[100];
fgets(ss,100,stdin);
// i know i can use strcat but i don't want it here
printf("%s%s",s,ss);
return 0;
}
and behaves as you wanted.
I have recently started to code in C and I am having quite a lot of fun with it.
But I ran into a little problem that I have tried all the solutions I could think of but to no success. How can I assign a char* variable to an array?
Example
int main()
{
char* sentence = "Hello World";
//sentence gets altered...
char words[] = sentence;
//code logic here...
return 0;
}
This of course gives me an error. Answer greatly appreciated.
You need to give the array words a length
char words[100]; // For example
The use strncpy to copy the contents
strncpy(words, sentence, 100);
Just in case add a null character if the string sentence is too long
words[99] = 0;
Turn all the compiler warnings on and trust what it says. Your array initializer must be a string literal or an initializer list. As such it needs an explicit size or an initializer. Even if you had explicitly initialized it still wouldn't have been assignable in the way you wrote.
words = sentence;
Please consult this SO post with quotation from the C standard.
As of:
How To Assign char* to an Array variable ?
You can do it by populating your "array variable" with the content of string literal pointed to by char *, but you have to give it an explicit length before you can do it by copying. Don't forget to #include <string.h>
char* sentence = "Hello World";
char words[32]; //explicit length
strcpy (words, sentence);
printf ("%s\n", words);
Or in this way:
char* sentence = "Hello World";
char words[32];
size_t len = strlen(sentence) + 1;
strncpy (words, sentence, (len < 32 ? len : 31));
if (len >= 32) words[31] = '\0';
printf ("%s\n", words);
BTW, your main() should return an int.
I think you can do it with strcpy :
#include <memory.h>
#include <stdio.h>
int main()
{
char* sentence = "Hello World";
char words[12];
//sentence gets altered...
strcpy(words, sentence);
//code logic here...
printf("%s", words);
return 0;
}
..if I didn't misunderstand. The above code will copy the string into the char array.
How To assign char* to an Array variable?
The code below may be useful for some occasions since it does not require copying a string or knowing its length.
char* sentence0 = "Hello World";
char* sentence1 = "Hello Tom!";
char *words[10]; // char *words[10] array can hold char * pointers to 10 strings
words[0] = sentence0;
words[1] = sentence1;
printf("sentence0= %s\n",words[0]);
printf("sentence1= %s\n",words[1]);
Output
sentence0= Hello World
sentence1= Hello Tom!
The statement
char* sentence = "Hello World";
Sets the pointer sentence to point to read-only memory where the character sequence "Hello World\0" is stored.
words is an array and not a pointer, you cannot make an array "point" anywhere since it is a
fixed address in memory, you can only copy things to and from it.
char words[] = sentence; // error
instead declare an array with a size then copy the contents of what sentence points to
char* sentence = "Hello World";
char words[32];
strcpy_s(words, sizeof(word), sentence); // C11 or use strcpy/strncpy instead
The string is now duplicated, sentence is still pointing to the original "Hello World\0" and the words
array contains a copy of that string. The array's content can be modified.
Among other answers I'll try to explain logic behind arrays without defined size. They were introduced just for convenience (if compiler can calculate number of elements - it can do it for you). Creating array without size is impossible.
In your example you try to use pointer (char *) as array initialiser. It is not possible because compiler doesn't know number of elements stayed behind your pointer and can really initialise the array.
Standard statement behind the logic is:
6.7.8 Initialization
...
22 If an array of unknown size is initialized, its size is determined
by the largest indexed element with an explicit initializer. At the
end of its initializer list, the array no longer has incomplete type.
I guess you want to do the following:
#include <stdio.h>
#include <string.h>
int main()
{
char* sentence = "Hello World";
//sentence gets altered...
char *words = sentence;
printf("%s",words);
//code logic here...
return 0;
}
I was writing code to reinforce my knowledge, I got segmentation fault. So, I also got that I have to restock(completing imperfect knowledge) on my knowledge. The problem is about strtok(). When I run the first code there is no problem, but in second, I get segmantation fault. What is my "imperfect knowledge" ? Thank you for your appreciated answers.
First code
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "team_name=fenerbahce";
char *token;
token = strtok(str,"=");
while(token != NULL)
{
printf("%s\n",token);
token = strtok(NULL,"=");
}
return 0;
}
Second code
#include <stdio.h>
#include <string.h>
int main() {
char *str= "team_name=fenerbahce";
char *token;
token = strtok(str,"=");
while(token != NULL)
{
printf("%s\n",token);
token = strtok(NULL,"=");
}
return 0;
}
From strtok -
This function is destructive: it writes the '\0' characters in the elements of the string str. In particular, a string literal cannot be used as the first argument of strtok.
And in the second case, str is a string literal which resides in read only memory. Any attempt to modify string literals lead to undefined behavior.
You see string literals are the strings you write in "". For every such string, no-matter where it is used, automatically a global space is alloacted to store it. When you assign it to an array - you copy it's content into a new memory, that of the array. Otherwise you just store a pointer to it's global memory storage.
So this:
int main()
{
const char *str= "team_name=fenerbahce";
}
Is equal to:
const char __unnamed_string[] { 't', 'e', /*...*/, '\0' };
int main()
{
const char *str= __unnamed_string;
}
And when assigning the string to array, like this:
int main()
{
char str[] = "team_name=fenerbahce";
}
To this:
const char __unnamed_string[] { 't', 'e', /*...*/, '\0' };
int main()
{
char str[sizeof(__unnamed_string) / sizeof(char)];
for(size_t i(0); i < sizeof(__unnamed_string) / sizeof(char); ++i)
str[i] = __unnamed_string[i];
}
As you can see there is a difference. In the first case you're just storing a single pointer and in the second - you're copying the whole string into local.
Note: String literals are un-editable so you should store their address at a constant.
In N4296 - § 2.13.5 .8 states:
Ordinary string literals and UTF-8 string literals are also referred
to as narrow string literals. A narrow string literal has type “array
of n const char”, where n is the size of the string as defined below,
and has static storage duration
The reason behind this decision is probably because this way, such arrays can be stored in read-only segments and thus optimize the program somehow. For more info about this decision see.
Note1:
In N4296 - § 2.13.5 .16 states:
Evaluating a string-literal results in a string literal object with
static storage duration, initialized from the given characters as
specified above.
Which means exactly what I said - for every string-literal an unnamed global object is created with their content.
char *str= "team_name=fenerbahce";
char str[]= "team_name=fenerbahce";
The "imperfect" knowledge is about the difference between arrays and pointers! It's about the memory you cannot modify when you create a string using a pointer.
When you create a string you allocate some memory that will store those values (the characters of the string). In the next lines I will refer to this when I'll talk about the "memory allocated at the start".
When you create a string using an array you will create an array that will contain the same characters as the ones of the string. So you will allocate more memory.
When you create a string using a pointer you will point to the address of memory that contains that string (the one allocated at the start).
You have to assume that the memory created at the start is not writable (that's why you'll have undefined behavior, which means segmentation fault most of the times so don't do it).
Instead, when you create the array, that memory will be writable! That's why you can modify with a command like strtok only in this case