Char array in C yields extra characters than required [duplicate] - arrays

This question already has an answer here:
What are null-terminated strings?
(1 answer)
Closed 7 months ago.
I have this simple program in which I initialize a string with "HELLO". I need the output to be printed as HLOEL, i.e) all the even indexes (0,2,4) followed by the odd ones (1,2). I could not infer what's wrong with my code, but it yields "HLOELHLO" instead of "HLOEL". Could someone explain what is happening here?
#include <stdio.h>
int main() {
int i,loPos=0,hiPos=0;
char *str="HELLO";
char lo[2];
char hi[3];
for(i=0;i<5;i++)
{
if(i%2==0)
{
hi[hiPos++]=str[i];
}
else
{
lo[loPos++]=str[i];
}
}
printf("%s%s",hi,lo);
return 0;
}
Thanks in Advance!

After the for loop, you need to put string terminating 0 bytes to the new strings, and also make sure they habe room for it:
char lo[2+1];
char hi[3+1];
for(...) {
}
hi[hiPos] = '\0';
Lo[loPos] = '\0';
Otherwise any string functions will have buffer overflow, causing undefined behavior. Generally they will keep reading bytes until by chance they encounter byte with value 0. But as always with undefined behavior, even this can cause your program to do anything.

because C style string need extra one char '\0' as its end. With your code,
the memory layout around two arrays maybe looks like:
lo[0], lo[1], hi[0], hi[1], hi[2], something else equal 0,
printf stops when it meets a '\0'
you should declare arrays as:
char lo[3];
char hi[4];
lo[2] = '\0';
hi[3] = '\0';

Related

How does C programs know the size of a string given a pointer to char? [duplicate]

This question already has answers here:
Does printf terminate every string with null character?
(3 answers)
What's the rationale for null terminated strings?
(20 answers)
Closed 24 days ago.
I would like to understand why this code works:
void open_image(const char *filename)
{
char *ImageName = filename;
printf("%s", ImageName);
}
const char image_name[] = "image.jpg";
open_image(image_name);
it prints "image.jpg" as wanted, but I don't know how the program knows the length of the string.
The program knows the size of the string image_name as it is computed during compilation.
But in the open_image function, how does the printf function knows the length of this string as it is only given the pointer ImageName created at runtime?
Thank you.
In C a string (array of char) is always terminated by the "terminator" character '\0', so you can get the length of the array by checking each character until you find it.
Here's a simple solution:
int i = 0;
char ch;
do
{
ch = arr[i];
i++;
} while(ch != '\0');
printf("String length: %d\n", i-1); // This will give the string length
printf("Total length of the array: %d\n", i); // This will give the array full length, including the terminator character.
Probably the best way to get a char array length is to import the string.h library which exposes the strlen() function.
However, it's always useful to learn how things actually work at low-level, especially when learning C). :-)

When does a char* ends with null in c?

I have confusion on char* null-termination so i have decided to make a study of cases i can find. Do these string literals end with a null?
char str1[512]="This is a random string"
char *str2 = strtok(buffer,"\n,") I have found its answer. This ends with null.
fgets(stdin, str3, 512)
scanf("%s",str4)
The code snippet:
char str[5];
for(int i=0; i<5; i++) scanf("%c",&str[i]);
Note 1: I have an assumption that all standard functions in c library that returns a char*, null terminates the string.
Note 2: How do I check if a string is null terminated or not? (I tried this approach but it prints random stuffs imo.)
Edit: Just showing me a way to determine whether a string literal is null-terminated will be enough. I will go through each case and update here for future readers.
Such an example is by no means exhaustive, but it brings some clarity. The answer is actually simple. Any array of characters ending in '\0' is called a string. The programmer independently decides what he needs .
#include<stdio.h>
int main(void)
{
char w[]="mamamia";
int i;
for(i=0;i<sizeof(w);i++)
{
if(w[i]=='\0')
printf("w[%d]==null\n",i);
else
printf("w[%d]== %c \n",i,w[i]);
}
return 0;
}

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.

String terminator issues

If I type in this code, it compiles and runs (I use GCC)
#include<stdio.h>
int main()
{
char sentence[8]="September";
printf("The size of the array is %d \n",sizeof(sentence));
printf("The array is %s \n",sentence);
}
and gives the output
The size of the array is 8
The array is Septembe
How is this working? A string terminator is needed for C to know that the string has ended. How is the array worth 8 bytes of space and knows where to stop?
By passing a non-NUL-terminated string to printf("%s"), you're invoking undefined behavior.
By its very nature, the result is undefined. It may seemingly "work" (like you're seeing).
As others have explained, what's probably happening is that there happens to be a zero byte after your string, which stops printf from going further. However, if you were to add more stuff around that variable, you'd probably see different behavior:
#include<stdio.h>
int main(void)
{
char sentence[8] = "September"; // NOT NUL TERMINATED!
char stuff[] = "This way is better";
printf("%s\n", sentence); // Will overrun sentence
return 0;
}

unexpected results on simple string reverse algorithm

I'm relatively new to C. I wanted to lern the language a bit by solving coderbyte challenges.
But I'm stucked at the first. It is supposed to be a simple String reverse algorithm.
When I input things like "asdf" or "1234567" the output is correct ("fdsa", "7654321"). But when I type "12345678" or "thisiscool" I get "87654321▒#"/"loocsisiht#" as a result. I don't know where the # are comming from.
This is my code:
#include <stdio.h>
#include <string.h>
void FirstReverse(char str[]) {
int len = strlen(str);
char nstr[len];
int i;
for(i = 0; i < len; i++) {
nstr[i] = *(str+len-1-i);
}
printf("%s\n", nstr);
}
int main(void) {
char str[100];
FirstReverse(gets(str));
return 0;
}
Can someone please tell me where I can find the error?
Thanks in advance :)
In C, strings are zero-terminated. A string "cat", for example, has 4 characters, and is represented as ('c','a','t',(char)0). You forgot about the final 0.
Note that strlen returns the string length without the final 0, so a string foo contains strlen(foo)+1 characters. Remember this when you allocate strings.
As the other answers have mentioned, you're missing a terminator.
It should also be noted that it's bad practice to allocate strings the way you did. An array should always have a fixed size if you create it that way.
You should instead do:
char * nstr = malloc(sizeof(char) * (len+1));
Thereby allocating the size of each character (1 byte) times the lenght.
Note the +1 because you need room for the string terminator.
When you call printf(, string); , it's gonna start from the first letter and print everything up to the terminator. Since you have no terminator here, it prints random characters, such as #.
What you're gonna wanna do to fix that, is adding:
nstr[i] = '\0';
after your loop.
Also remember to free the allocated memory.
You forgot to allocate a char for the terminating '\0' in nstr[].
So, better use: char nstr[len + 1]; and set nstr[len] = 0;
Furthermore: gets() is evil: from the glibc manual page:
Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.

Resources