This question already has answers here:
cout not printing unsigned char
(5 answers)
Closed 6 years ago.
I need to take a peek at what's inside a declared unsigned char pointer, I reduced my problem to this short example
#include<iostream>
int main (int argc, char *argv[])
{
unsigned char * buffer = new unsigned char;
*buffer = 8;
std::cout << "buffer = " << (unsigned char) (*buffer) << std::endl;
}
I am expecting this output : buffer = 8
But I get
buffer =
Blank, which drives me nuts, not even any value !!!
How I am actually dealing with it :
#include<iostream>
typedef unsigned char uint8_t;
int main (int argc, char *argv[])
{
uint8_t * buffer = new uint8_t ;
*buffer = 8;
std::cout << "buffer = " << (int) (*buffer) << std::endl;
}
I am using this example in ns3 , buffer constructs a one byte payload packet, and I need it to be a pointer.
That's why I actually tagged my question as "C" along with "C++", because the core of the issue is also concerned in C. But I found myself down voted for that ! I know "cout" and "new" are c++ literals, but it's irrelevant to the issue !!
Not having a coding problem with all that, my problem is just what's unsigned char then if it reads as a regular char with cout !!!!!
I stated I am expecting it to be buffer = 8 because unsigned char are one byte integers.
Thank you guys because you made me notice cout is dealing with it as if it is a regular char, despite it was expected for me otherwise.
If we extend your example slightly to this:
int main(int argc, char *argv[]) {
unsigned char * buffer = new unsigned char;
*buffer = 8;
std::cout << "buffer = [" << (*buffer) << "]\n";
}
the output is
buffer = ]
The ASCII char 8 means backspace, and it has nuked the opening [.
Notice you don't need the cast to unsigned char - *buffer is an unsigned char.
If you want it to have the character '8' you need to set its contents to 8.
Don't forget to delete what you new.
int main(int argc, char *argv[]) {
unsigned char * buffer = new unsigned char;
*buffer = '8'; //<---- see the single quotes?
std::cout << "buffer = [" << (*buffer) << "]\n";
delete buffer;
}
with output
buffer = [8]
Of course, we don't really need these pointers:
int main(int argc, char *argv[]) {
unsigned char buffer = '8';
std::cout << "buffer = [" << buffer << "]\n";
}
And if you insist on using raw character codes:
int main(int argc, char *argv[]) {
unsigned char buffer = 56;
std::cout << "buffer = [" << buffer << "]\n";
}
Edit:
If what you want to know is what numeric value is in the buffer variable and therefore want << to report an integer value rather than stream this as a character, use a cast.
int main(int argc, char *argv[]) {
unsigned char buffer = 56;
std::cout << "buffer = [" <<static_cast<unsigned int>(buffer) << "]\n";
}
'8' is the character 8.
8 is just a code of a character which is invisible.
Try writing *buffer = 48; and guess why the output is "Buffer = 0" based on this table.
Found this just now unsigned():
#include<iostream>
int main (int argc, char *argv[])
{
unsigned char * buffer = new unsigned char;
*buffer = 8;
std::cout << "buffer = " << unsigned(*buffer) << std::endl;
}
it gives the output I wanted in my question buffer = 8
which is not buffer = '8' as some might have thought I meant
Related
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
unsigned int a =5;
unsigned int *pint = NULL;
cout << "&a = " << &a << endl;
cout << " &pint = " << &pint << endl;
}
Output:
&a = 0x6ffe04
&pint = 0x6ffdf8
I'm wondering why the address of pint equals 0x6ffdf8. pint is an unsigned int (4 bytes), shouldn't the address of it be 0x6ffe00?
Your pint is not an unsigned int. It is a pointer to an unsigned int.
Pointer can have a different size and can especially have the size 8.
It could hence fit into 0x6ffdfc before 0x6ffe04.
But it also has bigger alignment needs, it wants an address dividable by 8, so 0x...c is out, it needs e.g. 0x...8.
With 463035818_is_not_a_number I agree that this not really predictable, there are implementation specific aspects. That is why I phrase "softly" with "can", "wants", "e.g."....
I have this code:
#include <iostream>
#include <cstdlib>
#include <stdio.h>
int main()
{
std::string napis = "Inhibitor";
int length = napis.length();
char hex[256];
std::cout << "Original: " << napis << '\n';
for (int i = 0; i < length; i++)
{
char buffer[2];
itoa(napis[i], buffer, 16);
hex[2*i] = buffer[0];
hex[2*i+1] = buffer[1];
}
for (int i = 0; i < length * 2 + 1; i++)
{
std::cout << hex[i];
}
}
After all those operations I get that hex[0] == 0. Don't really know why. I am not setting this value anywhere I guess. Program is supposed to code string into hexadecimal.
The itoa function will write a terminating nul character into the buffer. In your code, this it will write 2 or 3 characters (depending in the ASCII value of the character in the string), which can exceed the array bounds.
The solution is to increase the size of buffer by at least 1:
char buffer[4];
Even better is to use the non-deprecated name (_itoa), which, in C++ with a character array, will call the safe version of the function (_itoa_s) which will detect buffer overruns.
Just avoid the temporary buffer and write directly in the result buffer.
char str[] {"abcdefg"};
char hex[256];
for (uint i {0}; i < sizeof(str) - 1; ++i) {
::sprintf (&hex[i*2], "%02X", str[i]);
}
std::cout << "Hex: " << hex << std::endl;
I have tried to simplify the original code to a simple test example which replicates the issue that I am having. I do apologize for the simple question in advance.. I am a beginner with C++.
So moving on the actual question.. why do I get 0 as an output? For the purposes of my this example and for my understanding, functions should not be modified with the exception of the numerical values in them should it be required (meaning I got it wrong:).
Many thanks in advance.
static unsigned short buffer[5];
void settingMemory()
{
memset(buffer, 0, sizeof(buffer));
}
void copingMemory(const unsigned short *pixels)
{
memcpy(&buffer[5], pixels, 5*sizeof(unsigned short));
}
void printingMemory()
{
unsigned short *test = buffer;
std::cout << *test << std::endl;
std::cout << *test++ << std::endl;
std::cout << *test++ << std::endl;
std::cout << *test++ << std::endl;
std::cout << *test++ << std::endl;
std::cout << *test++ << std::endl;
}
int main(int argc, char* argv[])
{
settingMemory();
unsigned short test[5];
test[0] = 5;
test[1] = 55;
test[2] = 555;
test[3] = 5555;
test[4] = 55555;
copingMemory(test);
printingMemory();
}
My output is:
0
0
0
0
0
0
The line memcpy(&buffer[5], pixels, 5*sizeof(unsigned short)); copies to the start of the 6th element of buffer (i.e. the first element /outside/ the buffer. Replace it with memcpy(&buffer[0], pixels, 5*sizeof(unsigned short));, so you copy it to the 1st element instead.
Im trying to read blocks of data from a file, but I couldn't know how to ignore the newline character when I use istream::read.
Im aware that I can use for loop to load the characters to a cstring one by one with condition to ignore new lines character, but I hope there is clever way to solve this problem.
My intention to avoid using strings or vectors.
#include <iostream>
#include <fstream>
#include <cstring>
void readIt(char* fileName) {
std::ifstream seqsFile;
seqsFile.open(fileName) ;
if (seqsFile.fail()) {
std::cout << "Failed in opening: " << fileName << std::endl;
std::exit(1);
}
seqsFile.seekg(84);
char *buffer;
buffer = new char [7];
seqsFile.read(buffer, 7);
buffer[7] = 0;
std::cout << buffer << std::endl;
}
int main(int argc, char** argv) {
readIt(argv[1]);
return 0;
}
file:
gsi|33112219|sp|O
GACATTCTGGTGGTGGACTCGGAGGCATGATAGCAGGTGCAGCTGGTGCAGCCGCAGCAGCTTATGGAGC
GCAGCAGCTTATGGAGC
current output:
GAGC
GC
desired output:
GAGCGCA
modified version:
void readIt(char* fileName) {
std::ifstream seqsFile;
seqsFile.open(fileName) ;
if (seqsFile.fail()) {
std::cout << "Failed in opening: " << fileName << std::endl;
std::exit(1);
}
seqsFile.seekg(84);
char *buffer;
buffer = new char [7];
char next ;
for ( int i = 0 ; i < 7; i++) {
seqsFile.get(next);
if (next=='\n') {
i--;
continue;
}
buffer[i] = next;
}
buffer[7]=0;
std::cout << buffer << std::endl;
}
Your program has undefined behavior since you are modifying buffer using an out of range index. You have:
buffer = new char [7]; // Allocating 7 chars.
seqsFile.read(buffer, 7); // Reading 7 chars. OK.
buffer[7] = 0; // 7 is an out of range index. Not OK.
Allocate memory for at least 8 chars.
buffer = new char [8];
Also, when you intend to read the contents of a file using istream::read, it is recommended that you open the file in binary mode.
seqsFile.open(fileName, std::ios_base::binary) ;
Well, you can not tell not to read newlines - they will appear in your buffer variable anyway and you have to handle it.
Also, you have to fix the buffer size, as R Sahu mentioned
Regarding your question, i can suggest following snippet:
while ((index = strlen(buffer)) < 7)
{
seqsFile >> &buffer[index];
}
strlen here will return size of buffer upto /0 or newline character as well
You didn't tell what to do with whitespaces, so they will be ignored as well
TL;DR: Why do my char* variables have the same value, even though I input different ones?
Consider this very short program:
char *GetCompleteString ()
{
char *completeString;
std::cout << "Please enter the complete string.\n";
std::cin.getline(completeString,100);
return completeString;
}
char *GetSubstring ()
{
char* substring;
std::cout << "Please enter the substring for which to search.\n";
std::cin.getline(substring,100);
return substring;
}
//////////////////////////////////////////////////
int main(int argc, const char * argv[])
{
char *complete, *sub;
complete = GetCompleteString();
sub = GetSubstring();
//diagnostic
std::cout << "Complete is " << complete << " and sub is " << sub;
//diagnostic
return 0;
}
Now, I enter "foo" for the first string, and "bar" for the second. But the output tells me that both variables are the same.
The Xcode debugger shows that both variables have the same address, so when I assign a value to bar, the previously-entered foo (which lives at the same address) takes the same value. Here's what the debugger pane is showing just before the program exits:
argv const char ** 0x00007fff5fbff928
argc int 1
complete char * 0x00007fff5fbff928
*complete char 'b'
sub char * 0x00007fff5fbff928
*sub char 'b'
&complete char ** 0x00007fff5fbff8e8
&sub char ** 0x00007fff5fbff8e0
Why are these two variables being assigned the same address? What am I missing here? (And why are they retaining the same address as argv, which I think is just for interfacing with the CLI?)
And are they even retaining the same addresses? (I added the last two (&) lines to the debugger, myself. And those show different addresses...)
What you are doing there is undefined behaviour since neither completeString nor substring point to actual allocated memory. Anything can happen ;)
To be more precise: It is very likely that since you don't assign a value to the local variables they just get the first value lying on the stack which could be random or something the initialisation of your libc left there.
You can use following updated code
char *GetCompleteString ()
{
char *completeString = (char*)malloc(sizeof(char)*numberofchars);
std::cout << "Please enter the complete string.\n";
std::cin.getline(completeString,100);
return completeString;
}
char *GetSubstring ()
{
char* substring = (char*)malloc(sizeof(char)*numberofchars);
std::cout << "Please enter the substring for which to search.\n";
std::cin.getline(substring,100);
return substring;
}
//////////////////////////////////////////////////
int main(int argc, const char * argv[])
{
char *complete, *sub;
complete = GetCompleteString();
sub = GetSubstring();
//diagnostic
std::cout << "Complete is " << complete << " and sub is " << sub;
//diagnostic
return 0;
}
I have added memory allocation calls in your functions. numberofchars is numbers of chars you expect in that char *, or you can give some more thought to make it dynamic
There are a few problems with your code. I will list them here -
The statement char *completeString; defines completeString to be a pointer to a character. What you need is a character array to store the string entered by the user.
The variable completeString and subString are local to the functions GetCompleteString and GetSubstring respectively. They are allocated on the stack and go out of scope when the function returns. If you try to access them in main, then this invokes undefined behaviour. You need to allocate space to store strings on the heap using new operator. This allocates memory on the heap. You should free this memory using the delete[] operator after you are done with it.
The signature of main as per the standard should be one of the following -
int main(); or int main(int argc, char *argv[]);
Applying these changes to your code, it is
#include <iostream>
#define MAX_LEN 100
char *GetCompleteString()
{
char *completeString = new char[MAX_LEN];
std::cout << "Please enter the complete string.\n";
std::cin.getline(completeString, MAX_LEN);
return completeString;
}
char *GetSubstring()
{
char* substring = new char[MAX_LEN];
std::cout << "Please enter the substring for which to search.\n";
std::cin.getline(substring, MAX_LEN);
return substring;
}
int main()
{
char *complete, *sub;
complete = GetCompleteString();
sub = GetSubstring();
std::cout << "Complete is " << complete << " and sub is " << sub;
delete[] sub;
delete[] complete;
return 0;
}