I wanted to test things out with arrays on C as I'm just starting to learn the language. Here is my code:
#include <stdio.h>
main(){
int i,t;
char orig[5];
for(i=0;i<=4;i++){
orig[i] = '.';
}
printf("%s\n", orig);
}
Here is my output:
.....�
It is exactly that. What are those mysterious characters? What have i done wrong?
%s with printf() expects a pointer to a string, that is, pointer to the initial element of a null terminated character array. Your array is not null terminated.
Thus, in search of the terminating null character, printf() goes out of bound, and subsequently, invokes undefined behavior.
You have to null-terminate your array, if you want that to be used as a string.
Quote: C11, chapter §7.21.6.1, (emphasis mine)
s
If no l length modifier is present, the argument shall be a pointer to the initial element of an array of character type.280) Characters from the array are
written up to (but not including) the terminating null character. If the
precision is specified, no more than that many bytes are written. If the
precision is not specified or is greater than the size of the array, the array shall
contain a null character.
Quick solution:
Increase the array size by 1, char orig[6];.
Add a null -terminator in the end. After the loop body, add orig[i] = '\0';
And then, print the result.
char orig[5];//creates an array of 5 char. (with indices ranging from 0 to 4)
|?|?|?|0|0|0|0|0|?|?|?|?|
| ^memory you do not own (your mysterious characters)
^start of orig
for(i=0;i<=4;i++){ //attempts to populate array with '.'
orig[i] = '.';
|?|?|?|.|.|.|.|.|?|?|?|?|
| ^memory you do not own (your mysterious characters)
^start of orig
This results in a non null terminated char array, which will invoke undefined behavior if used in a function that expects a C string. C strings must contain enough space to allow for null termination. Change your declaration to the following to accommodate.
char orig[6];
Then add the null termination to the end of your loop:
...
for(i=0;i<=4;i++){
orig[i] = '.';
}
orig[i] = 0;
Resulting in:
|?|?|?|.|.|.|.|.|0|?|?|?|
| ^memory you do not own
^start of orig
Note: Because the null termination results in a C string, the function using it knows how to interpret its contents (i.e. no undefined behavior), and your mysterious characters are held at bay.
There is a difference between an array and a character array. You can consider a character array is an special case of array in which each element is of type char in C and the array should be ended (terminated) by a character null (ASCII value 0).
%s format specifier with printf() expects a pointer to a character array which is terminated by a null character. Your array is not null terminated and hence, printf function goes beyond 5 characters assigned by you and prints garbage values present after your 5th character ('.').
To solve your issues, you need to statically allocate the character array of size one more than the characters you want to store. In your case, a character array of size 6 will work.
#include <stdio.h>
int main(){
int i,t;
char orig[6]; // If you want to store 5 characters, allocate an array of size 6 to store null character at last position.
for (i=0; i<=4; i++) {
orig[i] = '.';
}
orig[5] = '\0';
printf("%s\n", orig);
}
There is a reason to waste one extra character space for the null character. The reason being whenever you pass any array to a function, then only pointer to first element is passed to the function (pushed in function's stack). This makes for a function impossible to determine the end of the array (means operators like sizeof won't work inside the function and sizeof will return the size of the pointer in your machine). That is the reason, functions like memcpy, memset takes an additional function arguments which mentions the array sizes (or the length upto which you want to operate).
However, using character array, function can determine the size of the array by looking for a special character (null character).
You need to add a NUL character (\0) at the end of your string.
#include <stdio.h>
main()
{
int i,t;
char orig[6];
for(i=0;i<=4;i++){
orig[i] = '.';
}
orig[i] = '\0';
printf("%s\n", orig);
}
If you do not know what \0 is, I strongly recommand you to check the ascii table (https://www.asciitable.com/).
Good luck
prinftf takes starting pointer of any memory location, array in this case and print till it encounter a \0 character. These type of strings are called as null terminated strings.
So please add a \0 at the end and put in characters till (size of array - 2) like this :
main(){
int i,t;
char orig[5];
for(i=0;i<4;i++){ //less then size of array -1
orig[i] = '.';
}
orig[i] = '\0'
printf("%s\n", orig);
}
Related
I'm trying to add (well, append really) the letters in the alphabet to an empty char array. However, I appear to run into some sort of pointer issue I don't understand, as my array contains only the last character. I tried moving the letter char outside of the for loop, but the compiler didn't like that. I also looked on here about how to create a list of all alphabetical chars, and one of the better answers was to type them all in 1 at a time. However, my problem means I don't fully understand for loops and pointers in C, and I want to.
#include <stdio.h>
int main(void) {
char *empty_list[26];
for (int i = 0; i < 26; i++){
char letter = i + 65;
empty_list[i] = &letter;
}
printf("%s", *empty_list);
return 0;
}
The main problem is your declaration:
char *empty_list[26];
defines an array of 26 pointers to characters. In your current code you assign each element in the array the address of the variable letter. Since that is out of scope when you print it is luck that it prints out the last one, it could equally have printed out garbage or crashed if the code between was complex. It could also have printed out additional garbage after the letter with what you already have since there is no way of knowing whether there is a string terminating character (\0) after the letter. In your existing code printf("%s", *empty_list); prints the first pointer from the array as a null terminated string, which if you ignore the loss of scope and assume the memory contents are still around, will be the last value from the loop since all pointers in your array point to the memory that letter was stored at and that memory has the last value from the loop.
If your intention was to create an array with the letters then it should be:
char empty_list[27];
It needs to be 27 as you need to leave space for the string terminating character at the end. One way to fill that in would be to use:
empty_list[26] = '\0';
after the end of your for loop and before you print the contents of the array (do not include the asterisk here - because it is an array the compiler will automatically take the address of the first element):
printf("%s", empty_list);
As brothir mentioned in the comments when you assign the value of the letter to the element in the array it should be without the ampersand:
empty_list[i] = letter;
There are a few things wrong with your code.
Firstly, the type of empty_list is presently an array of pointers to char, when it really should be an array of char, since your intent is to print it out as if it were the latter in the call to printf after your loop. char empty_list[26]; is the correct declaration.
Secondly, in your loop, you assign &letter when all you need is letter. Heck, you don't even need the intermediate variable letter. Just empty_list[i] = i + 'A'; will suffice.
Lastly, you are passing empty_list to printf to satisfy a format specifier %s, which expects a null-terminated string. What you need to do is add another element to empty_list and set that to zero:
char empty_list[27];
// populated 0..25 with 'A'..'Z' in your code...
empty_list[26] = '\0';
printf("%s\n", empty_list);
// Output: ABC...Z
With the above help (much appreciated), my working code to create an array of letters in C is below:
#include <stdio.h>
int main(void) {
// create an array with 1 extra space for null terminator
char empty_list[27];
// add null terminator so string knows when it's finished.
empty_list[26] = '\0';
for (int i = 0; i < 26; i++){
// add 65 to get ASCII value for 'A'
char letter = A + i;
// insert each char into the array sequentially
empty_list[i] = letter;
}
printf("%s", empty_list);
return 0;
}
#include<stdio.h>
#include<string.h>
void terminateString(char *str){
str[3] = 0;
printf("string after termination is:%s\n",str);
}
int main(){
char str[]="abababcdfef";
terminateString(str);
return 0;
}
Output:
string after termination is:aba
We are only assigning element at index '3' to 0, but why are all characters after that index are ignored? Can someone please explain this behavior?
We are only assigning element at index '3' to 0, but why do all
characters after that index are ignored? Can someone please explain
this behavior?
The convention with a zero-terminated string is that the 0 byte is what indicates the end of the string. So when printf() encounters the zero-byte at position 3, it stops printing.
The ISO C standard defines a string as follows (see, for example, C11 7.1.1 Definition of terms), emphasis is mine:
A string is a contiguous sequence of characters terminated by and including the first null character.
Hence, when you have the character sequence abababcdfef\0, that is indeed a string.
However, when you put a null at offset 3, the string is not aba\0abcdfef\0 but, by virtue of the fact it's only a string up to and including the first null, it is aba\0.
C-string is Null-terminated string. With null-terminated it means "a null character terminates (indicates the end of) the string".
A null character is a character with all its bits set to 0, or \0, presented in memory as 0x00.
When you set str[3] = 0 you're changing str[3] to the terminator token, so when printf reads the terminator, it thinks the string is end and only prints "aba".
What you are demonstrating is the difference in c++ between strings and char arrays. Strings are a sequence of characters that continue up to and including the first null character. A character array is a memory allocation unit. A string might not use the entire character array allocated for it (indeed it is possible that it may even exceed the bounds of the containing array). If you want to diagnostically print an array rather than a string, you would need to iterate over the array in a loop. See below:
#include<stdio.h>
#include<string.h>
void terminateString(char *str){
str[3] = 0;
printf("string after termination is:%s\n",str);
}
int main(){
char str[]="abababcdfef";
terminateString(str);
for (int i = 0; i < sizeof(str)/sizeof(str[0]); i++) {
(str[i] != 0) ? printf("%c ", str[i]) : printf("\\0 ");
}
printf("\n");
return 0;
}
// OUTPUT
// string after termination is:aba
// a b a \0 a b c d f e f \0
c/c++ doesn't really distinguish between 0, '\0', and NULL, they're all just 0 in memory. c style strings are a sequence of characters that end with '\0', so every function that works with them ends after it finds this char. When you assign str[3]=0; it's the same as str[3]='\0'; i.e. stop the string after 3 chars. If you want the letter 0, do str[3]='0';, where the single quotes let the compiler know you want the character 0, ascii 48
Edit:
Note that NULL is a macro that evaluates to 0, not the same as nullptr
apparently starting with C++11 NULL can evaluate to nullptr, in C or C++98, it is 0
http://www.cplusplus.com/reference/cstring/NULL/
In the following code, fizz prints correctly, but buzz does not. What is wrong with using a char array here or in what way am I using it wrong?
#include <stdio.h>
int main() {
int i;
char *fizz = "fizz";
char buzz[4] = "buzz";
for(i = 1; i <= 100; i++) {
if(!((i %3 == 0) || (i%5 == 0)))
printf("%d", i);
if(i%3 == 0)
printf("%s", fizz);
if(i%5 == 0)
printf("%s", buzz);
printf("\n");
}
}
Neither string is actually four bytes long. C strings are NUL-terminated, so they're always their length in characters plus one for the '\0' character. Therefore, you should change the declaration of buzz as follows:
char buzz[5] = "buzz";
However, also note that explicitly declaring the variable's length when initializing with a string literal is not required. You can just leave out the number, and it will work fine.
char buzz[] = "buzz";
The %s specifier prints a string. A string is a series of characters followed by a null-terminator. To put it another way, you tell printf where your characters start, and printf keeps printing until it encounters a null terminator.
The "buzz" expression is a null-terminated string, however you shoe-horned it into char buzz[4] so the null terminator didn't fit. The result is that the buzz array does not contain a null terminator, and so printf reads off the end of the string, causing undefined behaviour. To fix this write:
char buzz[] = "buzz";
which will include a null terminator and allocate the right amount of space.
You have declared the size of the buzz array as 4 and including \0 the size of the string is 5. so you have to change the size of the buzz array as 5 or don't mention the size.
char buzz[5] = "buzz";
because buzz is not a pointer variable, if the buzz is a pointer variable it will allocate the memory according to the string, so there is no need to specify the size.
As buzz is a array you have to mention the size correctly.
And while printing we use %s , %s will print the string till the \0 character occurs.
In the buzz string there is no \0 character, this is the problem.
buzz contains 4 character, it has no space reserved for the null character, therefore it cannot be printed correctly with %s. %s specifies that a null terminated string to be printed and it cannot work correctly if the string is not null terminated.
Change your initialization to char buzz[] = "buzz"
Anyone know why printf concatenates these two variables when outputting, but only if the length of the string is not specified?
#include <stdio.h>
int main(){
char myname[3] = "tim";
char myage[3] = "ten";
printf("myname is:%s \n", myname);
printf("myage is:%s \n", myage);
}
myname is:tim
myage is:tentim
...But when I don't specify the length of the strings it seems to work as I had expected, without printing both variables.
#include <stdio.h>
int main(){
char myname[] = "tim";
char myage[] = "ten";
printf("myname is:%s \n", myname);
printf("myage is:%s \n", myage);
}
myname is:tim
myage is:ten
You declare the array to have size 3 but you try to store 4 elements in it. Since there is enough memory for only 3 elements there is no memory left for the last element(the string null terminator \0), this leaves your character array without a null terminator.
Note that character arrays in c are expected to be null terminated so that you can print them using printf. This is because printf simply walks through the character array till it encounters a \0. In your first example since the array was never \0 terminated what you end up getting is Undefined behavior.(Practically, pintf will keep printing till it encounters a \0 and in the process reading beyond the bounds of memory allocated to the array)
In second case since you do not specify the size by yourself the appropriate size is chosen depending on the number of elements specified in the string i.e: 4 and the \0 terminate is in place.
You are not leaving enough room in your array for the null terminator. In C, when you initialize a char array with a string of the exact same length, the null terminator is dropped.
char myname[3] = "tim"; // equivalent to char myname[3] = {'t','i','m'};
char myage[3] = "ten"; // equivalent to char myage[3] = {'t','e','n'};
Without the null terminator, the printf function doesn't know when to stop printing your string, so it keeps going to the next memory location after your myage array, which just happens to be the storage for your myname array. The stack probably looks like this:
t <- beginning of myage
e
n
t <- beginning of myname
i
m
\0 <- a null terminator, by coincindence.
The fact that you don't get other garbage after the name is just a coincidence. Anything might be stored after your myname array, but in your case it was a null character, so printf stopped printing.
If you don't specify a size for your array, then a size is chosen that is one greater than the length of the string so that the null terminator can be stored:
char myname[] = "tim"; // equivalent to myname[4] = {'t','i','m','\0'};
char myage[] = "ten"; // equivalent to myage[4] = {'t','e','n','\0'};
Now your null terminators are put in place explicitly, and your stack looks like this:
t <- beginning of myage
e
n
\0 <- explicit null terminator
t <- beginning of myname
i
m
\0 <- explicit null terminator.
Now the printf function knows exactly when to stop printing.
The %s directive corresponds to an argument that points to a string. A string is a sequence of characters that ends at the first '\0'. However, you aren't giving the arrays in the first example enough space for a '\0', so those arrays don't contain strings.
printf thinks that a string exists, and continues printing characters until it comes to that '\0' character which belongs at the end of a string. As previously stated, there is no '\0' character because there isn't space for one. Your code causes printf to access bytes outside of the bounds of your arrays, which is undefined behaviour.
The myname[3] and myage[3] suppose to have a place for terminating \0. Thus, you can actually store only 2 symbols in each array.
In the second case compiler automatically sets size equal to 4 that is enough to store the strings.
I have a string I composed using memcpy() that (when expanded) looks like this:
char* str = "AAAA\x00\x00\x00...\x11\x11\x11\x11\x00\x00...";
I would like to print every character in the string, and if the character is null, print out "(null)" as a substitute for '\0'.
If I use a function like puts() or printf() it will just end at the first null and print out
AAAA
So how can I get it to print out the actual word "(null)" without it interpreting it as the end of the string?
You have to do that mapping yourself. If you want to, that is. In C, strings are null-terminated. So, if you use a formatted output function such as printf or puts and ask it to print a string (via the format specifier %s) it'd stop printing str as soon as it hits the first null. There is no null word in C. If you know exactly how many characters you have in str you might as well loop over them and print the characters out individually, substituting the 0 by your chosen mnemonic.
The draft says 7.21.6.1/8:
p The argument shall be a pointer to void. The value of the pointer is
converted to a sequence of printing characters, in an
implementation-defined manner.
However, the following:
$ cat null.c
#include <stdio.h>
int main() {
printf("%p\n", (void *)0);
}
produces:
00000000
on both gcc 4.6 and clang 3.2.
However, on digging deeper:
$ cat null.c
#include <stdio.h>
int main() {
printf("%s\n", (void *)0);
}
does indeed produce the desired output:
(null)
on both gcc and clang.
Note that the standard does not mandate this:
s If no l length modifier is present, the argument shall be a pointer
to the initial element of an array of character type.280) Characters
from the array are written up to (but not including) the terminating
null character. If the precision is specified, no more than that many
bytes are written. If the precision is not specified or is greater
than the size of the array, the array shall contain a null character.
Relying on this behavior may lead to surprises!
Instead of printing the string with %s , you will have to come up with a for loop that checks a condition whther a given char in your char array is a \0 and then print the NULL
From C++ Reference on puts() (emphasis mine):
Writes the C string pointed by str to stdout and appends a newline
character ('\n'). The function begins copying from the address
specified (str) until it reaches the terminating null character
('\0'). This final null-character is not copied to stdout.
To process data such as you have, you'll need to know the length. From there, you can simply loop across the characters:
/* ugly example */
char* str = "AAAA\x00\x00\x00...\x11\x11\x11\x11\x00\x00...";
int len = ...; /* get the len somehow or know ahead of time */
for(int i = 0; i < len; ++i) {
if('\0' == str[i]) {
printf(" (null) ");
} else {
printf(" %c ", str[i]);
}
}
One of the key cornerstones of C is strings are terminated by '\0'. Everyone lives by that rule. so I suggest you not think of your string as a string but as an array of characters.
If you traverse the array and test for '\0', you can print "(null)" out in place of the character. Here is an example. Please note, your char * str was created either as a char array or on the stack using malloc. This code needs to know the actual buffer size.
char* str = "AAAA\x00\x00\x00...\x11\x11\x11\x11\x00\x00...";
int iStrSz = <str's actual buffer size>
int idx;
for(idx=0; idx<iStrSz; idx++)
{
if('\0' == *(str + idx)
{
sprintf("%s", "(null)");
}
else
{
putchar(*(str + idx));
}
}
printf("%s", "\n");