Extra characters on cstring when cout - c++

I have a char[4] dataLabel that when I say
wav.read(dataLabel, sizeof(dataLabel));//Read data label
cout << "Data label:" <<dataLabel << "\n";
I get the output Data label:data� but when I loop through each char I get the correct output, which should be "data".
for (int i = 0; i < sizeof(dataLabel); ++i) {
cout << "Data label " << i << " " << dataLabel[i] << "\n";
}
The sizeof returns 4. I'm at a loss for what the issue is.
EDIT: What confuses me more is that essentially the same code from earlier in my program works perfectly.
ifstream wav;
wav.open("../../Desktop/hello.wav", ios::binary);
char riff[4]; //Char to hold RIFF header
if (wav.is_open()) {
wav.read(riff, sizeof(riff));//Read RIFF header
if ((strcmp(riff, "RIFF"))!=0) {
fprintf(stderr, "Not a wav file");
exit(1);
}
else {
cout << "RIFF:" << riff << "\n";
This prints RIFF:RIFF as intended.

You are missing a null terminator on your character array. Try making it 5 characters and making the last character '\0'. This lets the program know that your string is done without needing to know the size.
What is a null-terminated string?

The overload of operator<< for std::ostream for char const* expects a null terminated string. You are giving it an array of 4 characters.
Use the standard library string class instead:
std::string dataLabel;

See the documentation for istream::read; it doesn't append a null terminator, and you're telling it to read exactly 4 characters. As others have indicated, the << operator is looking for a null terminator so it's continuing to read past the end of the array until it finds one.
I concur with the other suggested answer of using std::string instead of char[].

Your char[] array is not null-terminated, but the << operator that accepts char* input requires a null terminator.
char dataLabel[5];
wav.read(dataLabel, 4); //Read data label
dataLabel[4] = 0;
cout << "Data label:" << dataLabel << "\n";

Variable dataLabel is defined like
char[4] dataLabel;
that it has only four characters that were filled with characters { 'd', 'a', 't', 'a' ) in statement
wav.read(dataLabel, sizeof(dataLabel));//
So this character array does not have the terminating zero that is required for the operator << when its argument is a character array.
Thus in this statement
cout << "Data label:" <<dataLabel << "\n";
the program has undefined behaviour.
Change it to
std::cout << "Data label: ";
std::cout.write( dataLabel, sizeof( dataLabel ) ) << "\n";

Related

Are std::string with null-character possible?

I initialized a C++ string with a string literal and replaced a char with NULL.
When printed with cout << the full string is printed and the NULL char prints as blank.
When printed as c_str the string print stop at the NULL char as expected.
I'm a little confused. Does the action came from cout? or string?
int main(){
std::string a("ab0cd");
a[2] = '\0'; // '\0' is null char
std::cout << a << std::endl; // abcd
std::cout << a.c_str() << std::endl; // ab
}
Test it online.
I'm not sure whether the environment is related, anyway, I work with VSCode in Windows 10
First you can narrow down your program to the following:
#include <iostream>
#include <string>
int main(){
std::string a("ab0cd");
a[2] = '\0'; // replace '0' with '\0' (same result as NULL, just cleaner)
std::cout << a << "->" << a.c_str();
}
This prints
abcd->ab
That's because the length of a std::string is known. So it will print all of it's characters and not stop when encountering the null-character. The null-character '\0' (which is equivalent to the value of NULL [both have a value of 0, with different types]), is not printable, so you see only 4 characters. (But this depends on the terminal you use, some might print a placeholder instead)
A const char* represents (usually) a null-terminated string. So when printing a const char* it's length is not known and characters are printed until a null-character is encountered.
Contrary to what you seem to think, C++ string are not null terminated.
The difference in behavior came from the << operator overloads.
This code:
cout << a.c_str(); // a.c_str() is char*
As explained here, use the << overloads that came with cout, it print a char array C style and stop at the first null char. (the char array should be null terminated).
This code:
cout << a; // a is string
As explained here, use the << overloads that came with string, it print a string object that internally known is length and accept null char.
string end limit (boundary) is not 0 (NULL) like simple char* but its size keep internally in its member data as it's actually user-defined type (an instantiated object) as opposed to primitive type, so
int main(){
string a("abc0d");
a[3] = 0; // '\0' is null char
a.resize(2);
std::cout << a << std::endl; // ab
std::cout << a.c_str() << std::endl; // ab
}
i'm sorry change your code to be more comfortable, watch as it results in
ab
ab
good learning: http://www.cplusplus.com/reference/string/string/find/index.html

Is there any way to know the size of what will be printed to standard output in C++?

For example, if I use the following:
cout << "hello world";
Is there any way to know the size of what's being printed to stdout?
You can use std::stringstream for this:
#include <sstream>
#include <iostream>
int main(){
std::stringstream ss;
int a = 3;
ss<<"Hello, world! "<<a<<std::endl;
std::cout<<"Size was: "<<ss.str().size()<<std::endl;
std::cout<<ss.str()<<std::endl;
}
The above returns 16: 14 character for "Hello, world!", 1 character for the contents of the variable a, and one character from std::endl.
I doubt there is a standard way to determine how much bytes will be written to the standard output before writing it.
What you could do is, write it to an ostringstream and get the size of the stream. This doubles the work, but gives you a standard generic way to determine how many bytes will an object take when written to a stream:
template <class T>
std::size_t stream_len(const T& t)
{
std::ostringstream oss;
oss << t;
return oss.tellp();
}
Here is a demo: http://coliru.stacked-crooked.com/a/3de664b4059250ae
Here's an old school C style way that is still valid C++ as well as modern C++:
#include <iostream>
int main() {
// C style but still valid c++
std::cout << "C style but still valid C++\n";
char phrase[] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd' };
char phrase2[] = { "hello world" };
// Adding 1 for the new line character.
std::cout << "size of phrase[] in bytes = "
<< sizeof(phrase)
<< " + 1 for newline giving total of "
<< sizeof(phrase) + 1
<< " total bytes\n"; // Not Null terminated
std::cout << "size of phrase2[] in bytes = "
<< sizeof(phrase2)
<< " + 1 for newline giving total of "
<< sizeof(phrase2) + 1
<< " total bytes\n"; // Null terminated
// Or you can do it more c++ style
std::cout << "\nC++ style\n";
// Also adding one for newline character and this string is not null terminated
std::cout << "size of string in bytes = "
<< std::string("hello world").size()
<< " + 1 for newline giving a total of "
<< std::string("hello world").size() + 1
<< " total bytes\n";
std::cout << "Press any key and enter to quit." << std::endl;
char c;
std::cin >> c;
return 0;
}
Since each character in C/C++ is 1 byte; all you need is the count of characters including special characters such as space, null terminator, newline etc. That is why there is a sizeof( Type ) operator in C/C++.
Output
C style but still valid C++
size of phrase[] in bytes = 11 + 1 for newline giving total of 12 total bytes
size of phrase2[] in bytes = 12 + 1 for newline giving total of 13 total bytes
C++ style
size of string in bytes = 11 + 1 for newline giving a total of 12 total bytes
Press any key and enter to quit.
Now this will only give you the size of the output before you send it to the ostream's cout object. This also doesn't reflect the added characters of text that is describing this output.
As others have stated you can use stringstream to concatenate a bunch of strings, characters and other data types into the stringstream object with the insertion operator << and then have the stream's member function give you the size in bytes.
It works in the same manner as std::string( ... ).size().

Difference between string.empty and string[0] == '\0'

Suppose we have a string
std::string str; // some value is assigned
What is the difference between str.empty() and str[0] == '\0'?
C++11 and beyond
string_variable[0] is required to return the null character if the string is empty. That way there is no undefined behavior and the comparison still works if the string is truly empty. However you could have a string that starts with a null character ("\0Hi there") which returns true even though it is not empty. If you really want to know if it's empty, use empty().
Pre-C++11
The difference is that if the string is empty then string_variable[0] has undefined behavior; There is no index 0 unless the string is const-qualified. If the string is const qualified then it will return a null character.
string_variable.empty() on the other hand returns true if the string is empty, and false if it is not; the behavior won't be undefined.
Summary
empty() is meant to check whether the string/container is empty or not. It works on all containers that provide it and using empty clearly states your intent - which means a lot to people reading your code (including you).
Since C++11 it is guaranteed that str[str.size()] == '\0'. This means that if a string is empty, then str[0] == '\0'. But a C++ string has an explicit length field, meaning it can contain embedded null characters.
E.g. for std::string str("\0ab", 3), str[0] == '\0' but str.empty() is false.
Besides, str.empty() is more readable than str[0] == '\0'.
Other answers here are 100% correct. I just want to add three more notes:
empty is generic (every STL container implements this function) while operator [] with size_t only works with string objects and array-like containers. when dealing with generic STL code, empty is preferred.
also, empty is pretty much self explanatory while =='\0' is not very much.
when it's 2AM and you debug your code, would you prefer see if(str.empty()) or if(str[0] == '\0')?
if only functionality matters, we would all write in vanilla assembly.
there is also a performance penalty involved. empty is usually implemented by comparing the size member of the string to zero, which is very cheap, easy to inline etc. comparing against the first character might be more heavy. first of all, since all strings implement short string optimization, the program first has to ask if the string is in "short mode" or "long mode". branching - worse performance. if the string is long, dereferencing it may be costly if the string was "ignored" for some time and the dereference itself may cause a cache-fault which is costly.
empty() is not implemented as looking for the existence of a null character at position 0, its simply
bool empty() const
{
return size() == 0 ;
}
Which could be different
Also, beware of the functions you'll use if you use C++ 11 or later version:
#include <iostream>
#include <cstring>
int main() {
std::string str("\0ab", 3);
std::cout << "The size of str is " << str.size() << " bytes.\n";
std::cout << "The size of str is " << str.length() << " long.\n";
std::cout << "The size of str is " << std::strlen(str.c_str()) << " long.\n";
return 0;
}
will return
The size of str is 3 bytes.
The size of str is 3 long.
The size of str is 0 long.
You want to know the difference between str.empty() and str[0] == '\0'. Lets follow the example:
#include<iostream>
#include<string>
using namespace std;
int main(){
string str, str2; //both string is empty
str2 = "values"; //assigning a value to 'str2' string
str2[0] = '\0'; //assigning '\0' to str2[0], to make sure i have '\0' at 0 index
if(str.empty()) cout << "str is empty" << endl;
else cout << "str contains: " << str << endl;
if(str2.empty()) cout << "str2 is empty" << endl;
else cout << "str2 contains: " << str2 << endl;
return 0;
}
Output:
str is empty
str2 contains: alues
str.empty() will let you know the string is empty or not and str[0] == '\0' will let you know your strings 0 index contains '\0' or not. Your string variables 0 index contains '\0' doesn't mean that your string is empty. Yes, only once it can be possible when your string length is 1 and your string variables 0 index contains '\0'. That time you can say that, its an empty string.
C++ string has the concept of whether it is empty or not. If the string is empty then str[0] is undefined. Only if C++ string has size >1, str[0] is defined.
str[i] == '\0' is a concept of the C-string style. In the implementation of C-string, the last character of the string is '\0' to mark the end of a C-string.
For C-string you usually have to 'remember' the length of your string with a separate variable. In C++ String you can assign any position with '\0'.
Just a code segment to play with:
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char* argv[]) {
char str[5] = "abc";
cout << str << " length: " << strlen(str) << endl;
cout << "char at 4th position: " << str[3] << "|" << endl;
cout << "char at 5th position: " << str[4] << "|" << endl;
str[4]='X'; // this is OK, since Cstring is just an array of char!
cout << "char at 5th position after assignment: " << str[4] << "|" << endl;
string cppstr("abc");
cppstr.resize(3);
cout << "cppstr: " << cppstr << " length: " << cppstr.length() << endl;
cout << "char at 4th position:" << cppstr[3] << endl;
cout << "char at 401th positon:" << cppstr[400] << endl;
// you should be getting segmentation fault in the
// above two lines! But this may not happen every time.
cppstr[0] = '\0';
str[0] = '\0';
cout << "After zero the first char. Cstring: " << str << " length: " << strlen(str) << " | C++String: " << cppstr << " length: " << cppstr.length() << endl;
return 0;
}
On my machine the output:
abc length: 3
char at 4th position: |
char at 5th position: |
char at 5th position after assignment: X|
cppstr: abc length: 3
char at 4th position:
char at 401th positon:?
After zero the first char. Cstring: length: 0 | C++String: bc length: 3

how to print a char array using a pointer only? (we don't know the size of the array)

I have a function with three parameters: a pointer to a character array (also known as a C-String), and two pointers to specific characters (we will assume that they point to characters in the C-String).
void stringPointerOperation(char* str, char* firstPtr, char* secondPtr)
{
cout << str << endl;
cout << "First character=" << *firstPtr << endl;
cout << "Second character =" << *secondPtr << endl;
}
Questions:
How do I print out the characters from firstPtr to the end of str?
How do I find out how many characters are between firstPtr and secondPtr?
Answer to question 1:
If your array of chars is properly formatted, it should be null-terminated (i.e., the last character should be \0). Simply print characters until you get there, as:
while(*firstPtr != '\0') {
cout << *firstPtr << endl;
*firstPtr++;
}
Answer to question 2:
If you are sure they are pointers to the same array of characters, simply subtracting them should work:
int charsBetween = secondPtr - firstPtr;

how to print char array in c++

how can i print a char array such i initialize and then concatenate to another char array? Please see code below
int main () {
char dest[1020];
char source[7]="baby";
cout <<"source: " <<source <<endl;
cout <<"return value: "<<strcat(dest, source) <<endl;
cout << "pointer pass: "<<dest <<endl;
return 0;
}
this is the output
source: baby
return value: v����baby
pointer pass: v����baby
basically i would like to see the output print
source: baby
return value: baby
pointer pass: baby
You haven't initialized dest
char dest[1020] = ""; //should fix it
You were just lucky that it so happened that the 6th (random) value in dest was 0. If it was the 1000th character, your return value would be much longer. If it were greater than 1024 then you'd get undefined behavior.
Strings as char arrays must be delimited with 0. Otherwise there's no telling where they end. You could alternatively say that the string ends at its zeroth character by explicitly setting it to 0;
char dest[1020];
dest[0] = 0;
Or you could initialize your whole array with 0's
char dest[1024] = {};
And since your question is tagged C++ I cannot but note that in C++ we use std::strings which save you from a lot of headache. Operator + can be used to concatenate two std::strings
Don't use char[]. If you write:
std::string dest;
std::string source( "baby" )
// ...
dest += source;
, you'll have no problems. (In fact, your problem is due to the fact
that strcat requires a '\0' terminated string as its first argument,
and you're giving it random data. Which is undefined behavior.)
your dest array isn't initialized. so strcat tries to append source to the end of dest wich is determined by a trailing '\0' character, but it's undefined where an uninitialized array might end... (if it does at all...)
so you end up printing more or less random characters until accidentially a '\0' character occurs...
Try this
#include <iostream>
using namespace std;
int main()
{
char dest[1020];
memset (dest, 0, sizeof(dest));
char source[7] = "baby";
cout << "Source: " << source << endl;
cout << "return value: " << strcat_s(dest, source) << endl;
cout << "pointer pass: " << dest << endl;
getchar();
return 0;
}
Did using VS 2010 Express.
clear memory using memset as soon as you declare dest, it's more secure. Also if you are using VC++, use strcat_s() instead of strcat().