Reason for such unusual output in c++ - c++

I cannot understand the unusual behavior of this code output.
It prints:
hellooo
monusonuka
Code is here:
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
printf(" hellooo \n");
char name[7]="sonuka";
char name1[4]={'m','o','n','u'};
printf("%s",name1);
system("pause");
return 0;
}

Your name1 array is not terminated with a zero character ('\0'). The printf function prints characters until it finds a zero. In your case it goes past the end of the array. What happens is undefined behaviour. A likely outcome is that other variables or garbage is printed to the screen until eventually a \0 somewhere else in memory is hit, but anything could happen including your program crashing.

name1 must be NULL-terminated, otherwise printf will print as many bytes, as it find, till hitting the \0.
It must be
char name1[5]={'m','o','n','u', '\0'};
What you have is undefined behaviour : printf prints memory after the memory, allocated for name1.
In this case, it seems like your compiler has placed the memory for name after name1, that's why they are both printed (name is correctly NULL-terminated, as all literals are).

name1 is not null-terminated, so printf just keeps printing chars until a \0 is reached.

printf("%s",name1);
s conversion specifier requires the argument to be a pointer to a C string.
char name1[4]={'m','o','n','u'};
is not a C string in because the array is not null terminated. Violating the requirement of the conversion speicier invokes undefined behavior and this is why you get this unexpected result.

You're trying to print a char array as a string with printf. Try this code:
int pointer=0;
while(pointer < 4){
printf("%c",name1[pointer]);
pointer++;
}

Related

C++ strcpy function fails in few major cases

When this code for swapping two string is being executed I get undesired outputs
#include<bits/stdc++.h>
using namespace std;
int main()
{
char a2[] = "Hello world";
char a1[] = "Geek";
char a3[20];
cout<<a2<<endl<<a1<<endl;
strcpy(a3,a1);
strcpy(a1,a2);
strcpy(a2,a3);
cout<<a2<<endl<<a1<<endl;
}
I get these results:
Hello world
Geek
Geek
HelloGeek (I expect it to be HelloWorld)
Is there something I'm doing wrong in the code.
In your program
char a2[] = "Hello world";
defines a character array sized to fit the string literal "Hello world". It can contain 12 characters including the nul terminator.
char a1[] = "Geek";
behaves the same, but "Geek" only requires 5 characters with the nul, so the array is 5 characters long.
strcpy(a3,a1);
does what you expect, copies 4 characters of "Geek" into a3's 20 byte buffer and nul terminates.
strcpy(a1,a2);
tries to put "Hello world" into the five character array of a1. This invokes Undefined Behaviour when the buffer is overrun. Undefined Behaviour is what it sounds like, something undefined happens, so you cannot rely on any of your expectations of this program from here on. What probably happens is one of the other variables around a1 partially overwritten but the compiler would be just as correct if it produced a program that made your computer jump up and start dancing the Macarena.
To elaborate on Paul Mc Kenzie's comment:
The memory for the strings has been statically allocated on your programs stack. E.g. the array containing 'Geek' only has space for that and the terminating null character, so you should not copy the longer string there.
I'd recommend you to use std::string instead. It handles the buffer allocations automatically and you can use = instead of strcpy.

null termination didn't appear in the array on strcpy-ing

While I was using c_str() to transform std::string into C-style string, I didn't see the last character overridden by the null-termination which c_str() is supposed to add in this program:
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int main()
{
string s = "helloworld";
char c[10];
strcpy(c, s.c_str());
cout << c << endl;
return 0;
}
What I am asking is why d is being printed (added to c) as I was expecting null-termination to be there. What am I missing here?
Your code has undefined behavior, because c, the array into which you copy the string, does not allocate enough space for null terminator.
The number of characters that you copy is 10, so you need an array of 11 to accommodate the null terminator.
To avoid overrun troubles like that with statically allocated arrays, use dynamic allocation instead:
char *c = new char[s.size()+1];
strcpy(c, s.c_str());
cout << c <<endl;
delete[] c;
You have undefined behaviour, "helloworld" is actually "helloworld\0", that is 11 characters. strcpy tries to copy over the whole string including NUL but c is only able to hold 10 characters.
strcpy does not know how long the target array is. It copies until (and including) the terminating 0 byte. So, the whole string helloworld\0 is copied. Note that this is 11 chars and you might as well get a crash.

C++ At() function of class string Access violetion

this code throw me an Access violation error
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string a;
cin >> a;
printf("%s",a.at(1));
return 0;
}
I wrote this line because this function gave me problem with a larger program and i want to figure out what the problem really is...
thanks !
The immediate problem is that "%s" requires a pointer to a C-style string as its corresponding argument. a.at(1) is a single character, not a pointer, so you have undefined behaviour when it's misinterpreted as a pointer. You want "%c" to print a character.
The more general problem is the use of non-typesafe C functions. In C++, you could use a typesafe output stream:
cout << a.at(1);
std::string at returns a char type. Using the %s format specifier for a char type will give you undefined behaviour. Boom!
Two things:
1) Check the size of the string before accessing elements using at: at(1) is accessing the second character of the string as the indexing is zero based.
2) Use the correct format specifier in printf: printf("%c", a.at(1))
at() doesn't return a string, it returns a character. %s is trying to interpret that character as a (very invalid) pointer.
Try:
printf("%c", a.at(1));
(assuming a is at least two characters long).
The printf function expect a char pointer and you give a char. The char value gets interpreted as an address and it is wrong.
If you only want to print a single char, use:
printf("%c", a.at(1))
provided your string is at least 2 characters long.

atof and non-null terminated character array

using namespace std;
int main(int argc, char *argv[]) {
char c[] = {'0','.','5'};
//char c[] = "0.5";
float f = atof(c);
cout << f*10;
if(c[3] != '\0')
{
cout << "YES";
}
}
OUTPUT: 5YES
Does atof work with non-null terminated character arrays too? If so, how does it know where to stop?
Does atof work with non-null terminated character arrays too?
No, it doesn't. std::atof requires a null-terminated string in input. Failing to satisfy this precondition is Undefined Behavior.
Undefined Behavior means that anything could happen, including the program seeming to work fine. What is happening here is that by chance you have a byte in memory right after the last element of your array which cannot be interpreted as part of the representation of a floating-point number, which is why your implementation of std::atof stops. But that's something that cannot be relied upon.
You should fix your program this way:
char c[] = {'0', '.', '5', '\0'};
// ^^^^
No, atof does not work with non-null terminated arrays: it stops whenever it discovers zero after the end of the array that you pass in. Passing an array without termination is undefined behavior, because it leads the function to read past the end of the array. In your example, the function has likely accessed bytes that you have allocated to f (although there is no certainty there, because f does not need to follow c[] in memory).
char c[] = {'0','.','5'};
char d[] = {'6','7','8'};
float f = atof(c); // << Undefined behavior!!!
float g = atof(d); // << Undefined behavior!!!
cout << f*10;
The above prints 5.678, pointing out the fact that a read past the end of the array has been made.
No... atof() requires a null terminated string.
If you have a string you need to convert that is not null terminated, you could try copying it into a target buffer based on the value of each char being a valid digit. Something to the effect of...
char buff[64] = { 0 };
for( int i = 0; i < sizeof( buff )-1; i++ )
{
char input = input_string[i];
if( isdigit( input ) || input == '-' || input == '.' )
buff[i] = input;
else
break;
}
double result = atof( buff );
From the description of the atof() function on MSDN (probably applies to other compilers) :
The function stops reading the input string at the first character that it cannot recognize as part of a number. This character may be the null character ('\0' or L'\0') terminating the string.
It must either be 0 terminated or the text must contain characters that do not belong to the number.
std::string already terminate a string with NULL!
So why not
std::string number = "7.6";
double temp = ::atof(number.c_str());
You can also do it with the stringstream or boost::lexical_cast
http://www.boost.org/doc/libs/1_53_0/doc/html/boost_lexical_cast.html
http://www.cplusplus.com/reference/sstream/stringstream/
Since C++11, we have std::stof. By replacing atof with std::stof, it would be easier to handle.
I made a handy wrapper if you always pass a known size of char array.
Live Demo
#include <fmt/core.h>
#include <type_traits>
#include <iostream>
// SFINAE fallback
template<typename T, typename =
std::enable_if< std::is_pointer<T>::value >
>
float charArrayToFloat(const T arr){ // Fall back for user friendly compiler errors
static_assert(false == std::is_pointer<T>::value, "`charArrayToFloat()` dosen't allow conversion from pointer!");
return -1;
}
// Valid for both null or non-null-terminated char array
template<size_t sz>
float charArrayToFloat(const char(&arr)[sz]){
// It doesn't matter whether it's null terminated or not
std::string str(arr, sz);
return std::stof(str);
}
int main() {
char number[4] = {'0','.','4','2'};
float ret = charArrayToFloat(number);
fmt::print("The answer is {}. ", ret);
return 0;
}
Output: The answer is 0.42.
Does atof work with non-null terminated character arrays too?
No, this function expects a pointer to a null terminated string. Failing to do so, say for example by passing a pointer to a non-null terminated string(or a non-null terminated character array) is undefined behavior.
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior.
So the output that you're seeing(maybe seeing) is a result of undefined behavior. And as i said don't rely on the output of a program that has UB. The program may just crash.
So the first step to make the program correct would be to remove UB. Then and only then you can start reasoning about the output of the program.
1For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program.

Weird output when printing char pointer from struct

Here is the code:
#include<iostream>
struct element{
char *ch;
int j;
element* next;
};
int main(){
char x='a';
element*e = new element;
e->ch= &x;
std::cout<<e->ch; // cout can print char* , in this case I think it's printing 4 bytes dereferenced
}
am I seeing some undefined behavior? 0_o. Can anyone help me what's going on?
You have to dereference the pointer to print the single char: std::cout << *e->ch << std::endl
Otherwise you are invoking the << overload for char *, which does something entirely different (it expects a pointer to a null-terminated array of characters).
Edit: In answer to your question about UB: The output operation performs an invalid pointer dereferencing (by assuming that e->ch points to a longer array of characters), which triggers the undefined behaviour.
It will print 'a' followed by the garbage until it find a terminating 0. You are confusing a char type (single character) with char* which is a C-style string which needs to be null-terminated.
Note that you might not actually see 'a' being printed out because it might be followed by a backspace character. As a matter of fact, if you compile this with g++ on Linux it will likely be followed by a backspace.
Is this a null question.
Strings in C and C++ end in a null characher. x is a character but not a string. You have tried to make it one.