I am writing a program to write a head for a specific image format. This image format requires 256 characters as its header before any following raw image data. But I have problem padding empty spaces to make the header 256 characters long.
Below is an abstraction of my problem:
char pad[256];
sprintf( pad, "header info:%s=%f", "scale", 2.3);
cout<<pad<<"data here"<<endl;
The output is:
header info:scale=2.300000data here
However, the result I expect is like:
header info:scale=2.300000 data here
where "data here" appears after 256 characters from the beginning of the file.
How can I change the program to pad empty spaces in the character array?
Do this:
cout << setw(256) << left << pad << "data here" <<endl;
You may need #include <iomanip>.
BTW in your "real code" you should use snprintf to ensure there is no chance of a buffer overflow, assuming that your %s is going to get some argument that's worked out at runtime . (Or preferably replace the sprintf with a stringstream).
Maybe this can help you. The format - which left aligns the text. For example, the following will left align the float text with a fixed width of 20. The default space character is used as padding.
sprintf( pad, "header info:%s=%-20f", "scale", 2.3);
Related
When I read in information via fstream, it has ocurred twice in two different programs, that the input given to my program isn't stable, even if a given file doesn't change.
In my most recent program, which is concerned with audio-reading. I'm doing a simple check on the first four letters in the file. These letters are supposed to be RIFF, which they also are - I checked.
So, in order to check the format of a given binary file, I buffer the first four letters and see if they are equal to 'RIFF'.
char buffer[4];
std::ifstream in(fn,std::ios::binary);
in.read(buffer,4);
if(buffer!="RIFF"){//Always wrong atm
std::cout << "INVALID WAV FILE: " << buffer << std::endl;
}
When I first made the program, I recall this working properly. Now though, I get an error via my own cout:
INVALID WAV FILE: RIFFýfK
Does anyone have any idea as to what has gone wrong? Perhaps a way to make fstream more consistent?
You're reading 4 characters but not adding a zero terminator, furthermore your comparison is wrong since you're not comparing strings equality, you should rather do:
char buffer[5];
std::ifstream in(fn, std::ios::binary);
in.read(buffer, 4);
buffer[4] = '\0'; // Add a zero-terminator at the end
if (strcmp(buffer,"RIFF")) { // If buffer isn't {'R','I','F','F','\0'}..
std::cout << "INVALID WAV FILE: " << buffer << std::endl;
}
In C++, when we need to print a single space, we may do the following:
cout << ' ';
Or we can even use a converted ASCII code for space:
cout << static_cast<char>(32); //ASCII code 32 maps to a single space
I realized that, printing a null character will also cause a single space to be printed.
cout << static_cast<char>(0); //ASCII code 0 maps to a null character
So my question is: Is it universal to all C++ compilers that when I print static_cast<char>(0), it will always appear as a single space in the display?
If it is universal, does it applies to text files when I use file output stream?
No, it will be a zero(0) character in every compiler. Seems that the font you use renders zero characters as a space. For example, in the old times, DOS had a different image (an almost filled rectangle) for zero characters.
Anyway, you really should not output zero characters instead of spaces!
As for the text file part: open the outputted file using a hex editor to see the actual bits written. You will see the difference there!
On my computer, this code
#include <iostream>
int main() {
std::cout << "Hello" << static_cast<char>(0) << "world\n";
}
outputs this:
Helloworld
So no, it clearly doesn’t work.
Doing a message program thing, and ran into a problem I don't understand with the buffer. The answer i'm sure is really simple but I just can't wrap my head around it. I'm trying to ask the user to type in a 10 digit name that will work as a username.
char myID[11]; // stores 10 characters plus newline at the end
char sendBuff[1024]
cout << "Enter your nickname(10 digits): ";
cin >> myID;
cin.ignore(1000, '\n'); //clears buffer, or so I thought
Then I get some actual text for the message, store it in tempCharArray, then combine the username and the message text using sprintf_s.
char tempCharArray[1024];
cin.getline( tempCharArray, 1024 );
sprintf_s(sendBuff, 1024, "%s: %s", myID, tempCharArray ); //combines username and message text into one line before being printed
Now, my problem is that if I type in a name longer than 10 digits, it will print out the entire name in the sprintf_s function, despite myID being only 10 characters. I do not at all understand this behavior...
For example if I type in "HelloKitty69420" into myID, and then "yoyoyo" into tempCharArray, I would expect it to print "HelloKitty: yoyoyo" because myID can only hold 10 characters, yet it prints "HelloKitty69420: yoyoyo".
What's going on?
I would comment on your overall strategy for accomplishing your goal (ie. it is definitely no the way I would go about it) but I will focus on an answer.
Firstly, you should use std::cin.width(10) to limit the number of characters actually stored and moved to myID.
Secondly, you seem to have been lucky in the above case. The overflow bytes were written into the second array sendBuff and sprintf was writing characters from both myID and sendBuff.
The reason the overflow bytes were written into the second array is that the compiler simply placed myID and sendBuff in memory regions that were contiguous. ie myID[1000] would be the same as sendBuff[1000-11]
I'm trying to load a certificate and a png file into a char* in C++:
char certPath[] = "./user.pem";
char dataPath[] = "./test.png";
char *certificate = loadFile(certPath);
char *datafile = loadFile(dataPath);
And this is my loadFile()` method:
char* loadFile(char* filename) {
cout << endl << "Loading file: " << filename << endl;
char *contents;
ifstream file(filename, ios::in|ios::binary|ios::ate);
if (file.is_open())
{
int size = file.tellg();
contents = new char [size];
file.seekg (0, ios::beg);
file.read (contents, size);
file.clear();
file.close();
}
printf("contents: %s\n", contents);
cout << endl << "finished loading " << filename << endl;
return contents;
}
This is the output which it produces:
Loading file: ./user.pem
contents: -----BEGIN CERTIFICATE-----
MIID+TCCAuGgAwIBAgIJAJhxZybSGGMgMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYD
VQQGEwJBVDEPMA0GA1UECAwGU3R5cmlhMQ0wCwYDVQQHDARHcmF6MQowCAYDVQQK
DAEvMQowCAYDVQQLDAEvMR0wGwYDVQQDDBRDaHJpc3RvZiBTdHJvbWJlcmdlcjEs
MCoGCSqGSIb3DQEJARYdc3Ryb21iZXJnZXJAc3R1ZGVudC50dWdyYXouYXQwHhcN
MTIwMjE0MjEwMzA4WhcNMTMwMjEzMjEwMzA4WjCBkjELMAkGA1UEBhMCQVQxDzAN
BgNVBAgMBlN0eXJpYTENMAsGA1UEBwwER3JhejEKMAgGA1UECgwBLzEKMAgGA1UE
CwwBLzEdMBsGA1UEAwwUQ2hyaXN0b2YgU3Ryb21iZXJnZXIxLDAqBgkqhkiG9w0B
CQEWHXN0cm9tYmVyZ2VyQHN0dWRlbnQudHVncmF6LmF0MIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEA15ISaiXMSTVnmGtEF+bbhmVQk+4voU1pUZlOMVBj
QKjfPgCtgrmRaY8L+d6Pu61urFE1QrsfNJdDJRYs87Cc1eZgkvOXz0fSE2DHVNE2
i9YdFR8ea5niU5ATFZwiDIEhfCAcXWcEHWtZBB4yYYISsBkFxq6UBniGV+p7XOtE
aAtriBP0PZ4KUo+arJLStbwt4f9tBeytKowaKVNGlOpBgj7TG4bw8yA7Avdx8s+k
sReSxYteo0o9clIqISdKL0pRdzXP0Zrix54mBIfsxojfCW2SvqvLLLxtJlRKriQj
JfBc4koS6yAoktx7CvzcepGQk65ZGl0TNlteG4FJqy5yBQIDAQABo1AwTjAdBgNV
HQ4EFgQU1/g63xTix2Vs0zv2d3wVX9FGvVQwHwYDVR0jBBgwFoAU1/g63xTix2Vs
0zv2d3wVX9FGvVQwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAHyvI
0L+ibesg45qUxx2OQb37HA9aRpR3wYpt6d5Rd1x2pfqumrKeV/42XWodZJSkU3sH
EX8V2xKwNoUBsPb/q54S9suCHwE33XtWjLvJyR9v2wd2HjNRYdGF9XoYdpsOpcAk
/kaZ2pExzLAPDg5pTsqY9dpCFWnyccZUO1CLEeljinOZ4raIj7d6EryWsn+u5pbs
WB12EFaoNCybQ6j5+TIcRs5xdGpVD6qMkm7HUnBn6mtz8Q7qVj9sqo5us4UBRWY8
ie9X494oW59nRuLiZ8dOPGuOXsuCILY44/3eyDh6yvW7G+wrp3eZ7L7eLRSI3+lm
mxqSJNq8Yi6ArfcB+Q==
-----END CERTIFICATE-----
finished loading ./user.pem
Loading file: ./test.png
First the content of the certificate should appear and then the content of the image. The certificate works but when I try to load the image it is really strange. Nothing works anymore. Even a simple cout or printf doesn't show up on the console but the program doesn't crash...
Any suggestions what's wrong?
Your error is that you have \0 at the beginning of the PNG header.
EDIT:
Change:
printf("contents: %s\n", contents);
To:
std::cout.write( contents, size );
std::cout.flush();
You have to move size into the correct scope as well of course.
There are different kinds of PNG file. So it could be the PNG image is having non-printable character. If so, then it will not be printed using any print function, be it printf or std::cout<<.
However, you can print the hexadecimal values of non-printable character:
//write it inside the if-block
for(int i = 0 ; i < size; ++i)
std::cout << std::hex << (int) contents[i];
It would print hexadecimal value of each character.
You can test if a given character is printable or not, using isprint() function.
You can't print the contents of a png file to the console, it's a binary file - different from a certificate file, which contains the certificate MIME-encoded and thus is a regular text file.
A printable file (i.e. text) contains only bytes representing standard-ASCII characters (0x20 - 0x7F) and uses ASCII formatting characters (CR, LF, etc.) in a predictable way. Furthermore, it doesn't contain a 0x00 byte, which is used in C/C++ to mark the end of a string. A binary file may contain any byte in any order.
So, two things will happen when you try to print it: a) it'll stop at the first 0x00 byte found; b) every byte containing a non-ASCII character will be printed as a special char (if it's in the code page active for the console), or nothing at all, and bytes that contain ASCII formatting chars will be "executed" as if they were actual formatting in a text file.
The result: either you won't see anything at all or just a few strange chars mixed with random line feeds, tabs & etc.
To have what you expect, the first thing is to define exactly what it is. Do you want to see the png contents MIME-encoded? Then you should use a MIME-encoding routine (like this). Or do you want to print the hex value of each byte? Then you need to do std::cout << std::hex << byte (as Nawaz suggested) or printf("%02x") for each byte in a loop.
Also for the certificate file you should open as a text file, not binary. Otherwise, you'd have two undesired effects: no LF normalization (for instance, in Windows the EOL is marked by CR+LF, while in Unix/Linux it's just LF) and no handling for the EOF char.
Edit: I'm trying to convert a text file into bytes. I'm not sure if the code is turning it into bytes or not. Here is the link to the header so you can see the as_bytes function.
link
#include "std_lib_facilities.h"
int main()
{
cout << "Enter input file name.\n";
string file;
cin >> file;
ifstream in(file.c_str(), ios::binary);
int i;
vector<int> bin;
while(in.read(as_bytes(i), sizeof(int)))
bin.push_back(i);
ofstream out(file.c_str(), ios::out);
for(int i = 0; i < bin.size(); ++i)
out << bin[i];
keep_window_open();
}
Note that now the out stream just outputs the contents of the vector. It doesn't use the write function or the binary mode. This converts the file to a large line of numbers - is this what I'm looking for?
Here is an example of the second code's file conversion:
that guy likes to eat lots of pie (not sure if this was exact text)
turns to
543518319544825700191924850016351970295432362115448292821701667182186922608417526375411952522351186935715718643976841768956006
The reason your first method didn't change the file is because all files are stored in the same way. The only "difference" between text files and binary files is that text files contain only bytes that can be shown as ASCII characters, while binary files* have a much more random variety and order of bytes. So you are reading bytes in as bytes and then outputting them as bytes again!
*I'm including Unicode text files as binary, since they can have multiple bytes to denote one character point, depending on the character point and the encoding used.
The second method is also fairly simple. You are reading in the bytes, as before, and storing them in integers (which are probably 4 bytes long). Then you are just printing out the integers as if they are integers, so you are seeing a string of numbers.
As for why your first method cut off some of the bytes, you're right in that it's probably some bug in your code. I thought it was more important to explain what the ideas are in this case, rather than debug some test code.