printing int array as string - c

I am trying to print int array with %s. But it is not working. Any ideas why?
#include<stdio.h>
main() {
int a[8];
a[0]='a';
a[1]='r';
a[2]='i';
a[3]='g';
a[4]='a';
a[5]='t';
a[6]='o';
a[7] = '\0';
printf("%s", a);
}
It prints just a.
I tried with short as well, but it also does not work.

This is because you are trying to print a int array, where each element has a size of 4 byte (4 chars, on 32bit machines at least). printf() interprets it as char array so the first element looks like:
'a' \0 \0 \0
to printf(). As printf() stops at the first \0 it finds, it only prints the 'a'.
Use a char array instead.

Think about the way integers are represented - use a debugger if you must. Looking at the memory you will see plenty of 0 bytes, and %s stops when it reaches a 0 byte.
It prints just a.
That's why it prints just a. Afterwards it encounters a 0 byte and it stops.

Because you declared a as an integer, so those signle characters you initialized would result in an error. You must change it to a char variable. However to save time, just make the variable a pointer using the asterisk character, which then allows you to make a single string using double quotes.

int a[8] means array of 8 ints or 8*(4 bytes) - Say 32 bit architecture
a[0] = 'a' stores in the first int index as 'a''\0''\0''\0'
a[1] = 'r' as 'r''\0''\0''\0' and so on . . .
%s represents any C-style string ie. any string followed by a '\0' character
So
printf("%s", a);
searches for trailing '\0' character and just prints "a" assuming it is the entire string

Related

How does a null character behave in a char array in C?

I tried to reverse this char array with null characters in the middle and the end, without using string length. (original code)
#include <stdio.h>
#include <stdlib.h>
int main()
{
char string[4] ={'c', '\0', 's', '\0'};
printf("What do we love?\n");
printf("Yes, we love:");
for(int i=3; i>=0; i--){
printf("%d", string[i]);
}
return 0;
}
I expected the output to display nothing. But I got the reverse of the array with whitespaces at the places where I’m guessing are the null characters? (output)
Bcoz I have tried using %d too instead of %c and found that those spaces apparently do have the ascii value of 0. (code with slight change + output + ascii table)
So, does this mean that a loop will not always treat a null character in a char array as an indicator of termination? Does this also mean null characters, which automatically get appended on the empty spaces of a char array actually, get printed as spaces in display, but we just say that it prints nothing in the output after it encounters null character only coz we see 'nothing' on display with most codes?
A null byte is used in a char array to designate the end of a string. Functions that operate on strings such as strcpy, strcmp, and the %s format specifier for printf, will look for a null byte to find the end of a string.
You're not treating string as a string, but as just an array of char. So it doesn't matter whether or not a particular element of the array has the value 0 as you're not treating that value as special in any way. You're just printing the decimal value of each of the elements of the array.

Unexplainable behaviour when printing out strings in C

The following code works as expected and outputs ABC:
#include <stdio.h>
void printString (char toPrint [100]);
int main()
{
char hello [100];
hello[0] = 'A';
hello[1] = 'B';
hello[2] = 'C';
hello[3] = '\0';
printString(hello);
}
void printString (char toPrint [100])
{
int i = 0;
while (toPrint[i] != '\0')
{
printf("%c", toPrint[i]);
++i;
}
}
But if I remove the line that adds the null-character
hallo[3] = '\0';
I get random output like wBCÇL, ╗BCÄL, ┬BCNL etc.
Why is that so? What I expected is the loop in printString() to run forever because it doesn't run into a '\0', but what happend to 'A', 'B' and 'C'? Why do B and C still show up in the output but A is replaced by some random character?
You declaration of hello leaves it uninitialized and filled with random bytes
int main()
{
char hello [100];
...
}
If you want zero initialized array use
int main()
{
char hello [100] = {0};
...
}
There must have been, by pure chance, the value for \r somewhere in the memory cells following those of my array hello. That's why my character 'A' was overwritten.
On other machines, "ABC" was ouput as expected, followed by random characters.
Initializing the array with 0s, purposely omitted here, of course solves the problem.
edit:
I let the code print out each character in binary and toPrint[5] was indeed 00001101 which is ASCII for \r (carriage return).
When you declare an automatic like char hello [100];, the first thing to understand is that the 100 bytes can contain just about anything. You must assign values to each byte explicitly to do / have something meaningful.
You are terminating you loop when you find the \0 a.k.a the NUL character. Now, if you comment out the instruction which puts the \0 after the character c, your loop runs until you actually find \0.
Your array might contain \0 at some point or it might not. There are chances you might go beyond the 100 bytes still looking for a \0 and invoke undefined behaviour. You also invoke UB when you try to work with an unassigned piece of memory.

Array showing random characters at the end

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);
}

Undefined behavior of a program

While writing a program i am filling the entries of a char array with digits. After doing so the length calculated for an array having no zero is correct but for an array starting with zero is zero!
Why is this result coming so!I am not able to interpret my mistake!?
int main()
{
int number_of_terms,no,j,i;
char arr[100];
char c;
scanf("%d",&number_of_terms);
for(i=0;i<number_of_terms;i++)
{
j=0;
while(c!='\n')
{
scanf("%d",&arr[j]);
if(c=getchar()=='\n')
break;
j++;
}
printf("Length is:%d\n",strlen(arr));
}
return 0;
}
for eg if i input my array elements as 4 5
lenght is 2
and if my array elements as 0 5
length is 0..
You are using "%d" in your format specifier, which produces an integer, and you are passing in the address of a character array. This is, exactly like your title says, undefined behaviour. In particular, the value zero will take up 4 of the cells in your string, and will write zero to all of those. Since the character with value zero is the end marker, you get zero length string. However, on another architecture, the second character would probably cause a crash...
If you want to store integers in an array, you should use int arr[...];. If you want to store characters, use "%c".
You are copying the value 0 into the array. This eqals the character '\0' which is used to terminate strings. What you want is to copy the character '0' (has the value 48, see an ascii table).
Change %d to %c to interpret the input has character instead of decimal.
scanf("%c",&arr[j]);
Also your "string" in arr is not zero terminated. After all the characters of your string, you have to end the string with the value 0 (here a decimal is correct). strlen needs it, because it determines the length of the string by traversing the array and counting up until it finds a 0.

why does the string array does not discriminate the numerical values but the integer array doesn't display characters?

I came up through a strange problem where I had a string wherein it displayed all the characters and numerals without any issues. But the same thing was not possible with an integer array. As far as I know string is a NULL terminated character array. So, what makes strings different to display everything without any discrimination.
Any help is appreciated. Thanks!
The way you instruct the compiler to print them makes them different.
When your write
printf("%s", charPtr);
you tell the compiler that it should treat charPtr as a NULL-terminated string. It looks at the memory charPtr points to and interprets each byte as a character, until it reaches a 0.
There's no equivalent for generic array types.
like this?:
#include <stdio.h>
int main(void)
{
int a =1;
int array[] = {1,2,3};
const char c = 'a';
char str[] = "hello";
const char char_a[] ={119,111,114,108,100,0}; //ascii codes for world
printf("this is a int: %d\n",a);
printf("this is a int array: %d, prints only the first element of array\n",*array);
printf("this is a int array: %d, prints only the 2. element of array\n",array[1]);
printf("this is a char: %c\n",c);
printf("this is a char array: %c, print only first element of str\n",*str);
printf("this is a char array: %s, prints to \\0 \n",str);
printf("this is a char array(made from numbers): %s, prints to 0 \n",char_a);
return 0;
}
the options %s tells printf, that it should think about the elements in the array
as chars, and that it should print this until it reach \0.
/* the very answer to the question is at the bottom. A single sentence, huh. */
Since a char string is delimited with a NULL, aka 0 value, printf stops whenever it encounters one. Now let's say we have two arrays, one char and one int, like this:
char char_array[] = { 'a', 'b', 'c', '\0' };
int int_array[] = { 'a', 'b', 'c', '\0' };
now, if we were to try to print those with:
printf("char array: %s\n", char_array);
printf("int array: %s\n", (char*) int_array);
We would get this output:
char array: abc
int array: a
And even if we don't cast int_array as char*, it still does the same (compiler might complain, though). But why so? Let us check the memory that is holding those two arrays. (on little-endian) The char_array holds: 0x00636261
while the int_array holds (separated every 32 bits): 0x00000061 0x00000062 0x00000063 0x00000000
So, what happens is - printf reads a string one char, in other words, one byte at a time. Thus, when reading the int_array, it reads the first byte, that is 0x61 (character 'a'), then jumps to the next byte. But whoops! The next byte 0x00 ( 0x0000 00 61 )! That signals the end of string and it stops.
Now, let us set the values in the int_array to:
int int_array[] = { 0x61616161, 0x62626262, 0x63636363, '\0' };
it now prints int array: aaaabbbbcccc!
Since there are no longer any 0x00 gaps in the values, printf simply prints till it reaches the fourth int that we initialized to zero.
That said, if one wants to print an int array as it was a string, one either has to write a function/wrapper to build a char string holding only the values of the first byte of each int, or one that builds a string with all the 0x00 values diked out.
So, to answer Your question "what makes them different": Since this is C, all of it is just a bunch of bits, aka plain old data. So the only difference is how we treat it. With that, I bet You, if char_array is allocated continuously and is aligned, if You would use char_array as a *((int*) char_array), on little endian, it will give You a value of 6513249 ( 0x00636261 ) =]

Resources