2

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.

Matt
  • 127
  • 10
  • 6
    Is your char array null terminated? If it is not it could explain the issue. Try making it 5 characters and making the last character '\0' – marsh Jul 07 '15 at 20:33
  • 2
    @marsh - you're very correct, just not confident enough. Matt noted the array is of size 4 (`char[4] dataLabel`), and the data it holds is 4 characters long ("data"). It is definitely missing the null character. – Amit Jul 07 '15 at 20:36
  • try `char[5] dataLabel`. If `"data"` is being read in, there's no space for the `\0` character! – AndyG Jul 07 '15 at 20:36
  • @Amit ah yes good catch. I did not notice the string was listed. – marsh Jul 07 '15 at 20:44
  • The code seemed to work fine using essentially the same lines earlier. I'm curious why that would be, see the edit – Matt Jul 08 '15 at 13:11

5 Answers5

3

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?

Community
  • 1
  • 1
marsh
  • 2,592
  • 5
  • 29
  • 53
  • What happens if there is no null terminator? It seemed like it worked fine previously in my code. – Matt Jul 08 '15 at 13:12
  • 1
    It will work as long as you are aware of the length and are iterating through it. Though it is definitely not recommended. As you can see many built in functions dealing with char arrays use the null terminate to find out when it ends. It may lead to trouble down the road. A std::string may be a smart choice as well, though without seeing all your code it is hard to say. If it worked before with cout, chances are that where your string was placed in memory happened to be surrounded by nulled out data. This is random and cannot be assured to stay the same. – marsh Jul 08 '15 at 13:15
  • See my edit. Why does it work there but not in the original question? Thanks – Matt Jul 08 '15 at 13:17
  • So it's undefined behavior that changes each time? Thanks. I'm going to change it to `std::string` – Matt Jul 08 '15 at 13:30
  • Basically yes, it just depends where the string is put in memory, that is my theory anyway. A more experienced member may come up with a better reason. std::string is optimized for small values anyway so it should not be a performance hit. – marsh Jul 08 '15 at 13:31
1

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;
Shoe
  • 74,840
  • 36
  • 166
  • 272
0

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[].

Brian Vandenberg
  • 4,011
  • 2
  • 37
  • 53
0

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";
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

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";
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335