I dont know if I have the correct tiltle for this, so please correct me if I am wrong and I will change my title.
I have a string, for this example I will use:
"8ce4b16b"
I would like to shift the bits (I think) along 1 so the string would be:
"9df5c27c"
Any Ideas?
EDIT:
Just so you know, these strings are hex. So it will never reach z.
All I want to do is add a number to the numbers and progress one step through the alphabet so a->b, f->g ect ect
If the number is 9 there will be a condition to keep it as 9.
The output DOES NOT need to be a hex.
Also the string is only an example. It is part of an MD5 encryption.
Transform a string? This sounds like a job for std::transform():
#include <cassert>
#include <string>
char increment(char c)
{
if ('9' == c)
{
return '9';
}
return ++c;
}
std::string increment_string(const std::string& in)
{
std::string out;
std::transform(in.begin(), in.end(), std::back_inserter(out), increment);
return out;
}
int main()
{
assert(increment_string("8ce4b16b") == "9df5c27c");
assert(increment_string("ffffffff") == "gggggggg");
assert(increment_string("89898989") == "99999999"); // N.B: this is one of 2^8 strings that will return "99999999"
assert(increment_string("99999999") == "99999999"); // This is one more. Mapping backwards is going to be tricky!
return 1;
}
Any limits you wish to impose on the characters can be implemented in the increment() function, as demonstrated.
If, on the other hand, you wish to treat the string as a hexadecimal number and add 0x11111111 to it:
#include <sstream>
#include <cassert>
int main()
{
std::istringstream iss("8ce4b16b");
long int i;
iss >> std::hex >> i;
i += 0x11111111;
std::ostringstream oss;
oss << std::hex << i;
assert(oss.str() == "9df5c27c");
return 1;
}
No bits were shifted in the construction of this string.
It looks like you simply added 0x11111111 to the integer. But can you specify precisely what tpye your input has? And what the result should be when you add one to "f" or "9"?
That's not shifting the bits ... shifting a bit multiplies a word value by 2. You're simply incrementing each hex value by 1, and that can be done by adding 0x11111111 to your dword.
For instance, if you took your value 0x8ce4b16b (that would be treating the values you printed above as-if they were a 4-byte double-word in hexadecimal), shifting it by one bit, you would end up with 0x19C962D6.
But if you simply want to increment each nibble of your dword (each individual value in a hex-number represents 4-bits or a nibble), you're going to have to add an offset of 0x1 to each nibble. Also there is no value of G in a hex-word ... you have the values 0->9, and then A->F, where F represents the base-10 value 15. Finally, when you add 0x1 to 0xF, you're going to wrap around to 0x0.
Do you mean you want to increment each character in the string?
You can do that my iterating through the array and adding one to each character.
Related
I a writing a program and I need to write a function that returns the amount of characters and spaced in a string. I have a string(mystring) that the user writes, I want the function to return the exact amount of letters and spaces in string, for examples "Hello World" should return 11, since there are 10 letters and 1 space. I know string::size exists but this returns the size in bytes, which is of no use to me.
I'm not sure if you want the length of the string in characters or you just want to count the number of letters and spaces.
There is no specific function that lets you count just letters and spaces, however you can get the amount of letters and spaces (and ignore all other types of characters) quite simply:
#include <string>
#include <algorithm>
#include <cctype>
int main() {
std::string mystring = "Hello 123 World";
int l = std::count_if(mystring.begin(), mystring.end(), [](char c){ return isspace(c) || isalpha(c); });
return 0;
}
Otherwise, unless you use non-ascii strings, std::string::length should work for you.
In general, it's not so simple and you're quite right if you assumed that one byte doesn't necessarily mean one character. However, if you're just learning, you don't have to deal with unicode and the accompanying nastiness yet. For now you can assume 1 byte is 1 character, just know that it's not generally true.
Your first aim should be to figure out if the string is ascii encoded or encoded with a multi-byte format.
For ascii string::size would suffice. You could use the length property of string as well.
In the latter case you need to find the number of bytes per character.
You should take the size of your array, in bytes, using string::size and then divide this by the size in bytes of an element of that string (a char).
That would look like: int len = mystring.size() / sizeof(char);
Just make sure to include iostream, the header file that contains std::sizeof.
You can make your own function to get the length of string in C++ (For std::string)
#include <iostream>
#include <cstring>
using namespace std;
int get_len(string str){
int len = 0;
char *ptr;
while(*ptr != '\0')
{
ptr = &str[len];
len++;
}
int f_len = len - 1;
return f_len;
}
To use this function, simply use:
get_len("str");
Again I've got a little problem with my DLL:
I try to convert a number (in this case "20") to a char which I can write to the file.
It doesn't really matter in which way this is done (whether following the ascii-table or not), but I need a way to convert back as well.
This was my attempt:
file.write((char*)20,3);
But it's throwing an access violence error..
Could someone tell me how this is done and also how I can reverse the process?
I could also use a method which works with numbers larger than 255 so the result are for example two or three chars (two chars = 16-bit-number.
Anyone have an idea?
If you just want to write an arbitrary byte, you can do this:
file.put(20);
or
char ch = 20;
file.write(&ch, 1); // Note a higher digit than 1 here will mean "undefined behaviour".
To reverse the process, you'd use file.get() or file.read(&ch, 1).
For larger units than a single byte, you'll have to use file.write(...), but it gets less portable, since it now relies on the size of the value being the same between different plaforms, AND that the internal representation is the same. This is not a problem if you are always running this on the same type of machine (Windows on an x86 processor, for example), but it will be a problem if you start using the code on different types of machines (x86, Sparc, ARM, IBM mainframe, Mobile phone DSP, etc) and possibly also between different OS's.
Something like this will work with the above restrictions:
int value = 4711;
file.write((char *)&value, sizeof(value));
It is much more portable to write this value to a file in text-form, which can be read by any other computer than recognises the same character encoding.
This will convert an unsigned long long into multiple characters depending on how big the number is, and output them to a file.
#include <fstream>
int main() {
unsigned long long number = 2098798987879879999;
std::ofstream out("out.txt");
while (number) { // While number != 0.
unsigned long long n = number & 255; // Copy the 8 rightmost bits.
number >>= 8; // Shift the original number 8 bits right.
out << static_cast<unsigned char>(n); // Cast to char and output.
}
out << std::endl; // Append line break for every number.
}
You can read it back from a file using something like this
#include <iostream>
#include <fstream>
#include <algorithm>
#include <string>
int main() {
std::ifstream in("out.txt");
unsigned long long number = 0;
std::string s;
std::getline(in, s); // Read line of characters.
std::reverse(begin(s), end(s)); // To account for little-endian order.
for (unsigned char c : s) {
number <<= 8;
number |= c;
}
std::cout << number << std::endl;
}
This outputs
2098798987879879999
I am really confused. I have to be missing something rather simple but nothing I am reading about strtol() is making sense. Can someone spell it out for me in a really basic way, as well as give an example for how I might get something like the following to work?
string input = getUserInput;
int numberinput = strtol(input,?,?);
The first argument is the string. It has to be passed in as a C string, so if you have a std::string use .c_str() first.
The second argument is optional, and specifies a char * to store a pointer to the character after the end of the number. This is useful when converting a string containing several integers, but if you don't need it, just set this argument to NULL.
The third argument is the radix (base) to convert. strtol can do anything from binary (base 2) to base 36. If you want strtol to pick the base automatically based on prefix, pass in 0.
So, the simplest usage would be
long l = strtol(input.c_str(), NULL, 0);
If you know you are getting decimal numbers:
long l = strtol(input.c_str(), NULL, 10);
strtol returns 0 if there are no convertible characters at the start of the string. If you want to check if strtol succeeded, use the middle argument:
const char *s = input.c_str();
char *t;
long l = strtol(s, &t, 10);
if(s == t) {
/* strtol failed */
}
If you're using C++11, use stol instead:
long l = stol(input);
Alternately, you can just use a stringstream, which has the advantage of being able to read many items with ease just like cin:
stringstream ss(input);
long l;
ss >> l;
Suppose you're given a string char const * str. Now convert it like this:
#include <cstdlib>
#include <cerrno>
char * e;
errno = 0;
long n = std::strtol(str, &e, 0);
The last argument 0 determines the number base you want to apply; 0 means "auto-detect". Other sensible values are 8, 10 or 16.
Next you need to inspect the end pointer e. This points to the character after the consumed input. Thus if all input was consumed, it points to the null-terminator.
if (*e != '\0') { /* error, die */ }
It's also possible to allow for partial input consumption using e, but that's the sort of stuff that you'll understand when you actually need it.
Lastly, you should check for errors, which can essentially only be overflow errors if the input doesn't fit into the destination type:
if (errno != 0) { /* error, die */ }
In C++, it might be preferable to use std::stol, though you don't get to pick the number base in this case:
#include <string>
try { long n = std::stol(str); }
catch (std::invalid_argument const & e) { /* error */ }
catch (std::out_of_range const & e) { /* error */ }
Quote from C++ reference:
long int strtol ( const char * str, char ** endptr, int base );
Convert string to long integer
Parses the C string str interpreting its content as an integral number of the specified base, which is returned as a long int value. If endptr is not a null pointer, the function also sets the value of endptr to point to the first character after the number.
So try something like
long l = strtol(pointerToStartOfString, NULL, 0)
I always use simply strol(str,0,0) - it returns long value. 0 for radix (last parameter) means to auto-detect it from input string, so both 0x10 as hex and 10 as decimal could be used in input string.
What is the best way to convert a char array (containing bytes from a file) into an decimal representation so that it can be converted back later?
E.g "test" -> 18951210 -> "test".
EDITED
It can't be done without a bignum class, since there's more letter combinations possible than integer combinations in an unsigned long long. (unsigned long long will hold about 7-8 characters)
If you have some sort of bignum class:
biguint string_to_biguint(const std::string& s) {
biguint result(0);
for(int i=0; i<s.length(); ++i) {
result *= UCHAR_MAX;
result += (unsigned char)s[i];
}
return result;
}
std::string biguint_to_string(const biguint u) {
std::string result;
do {
result.append(u % UCHAR_MAX)
u /= UCHAR_MAX;
} while (u>0);
return result;
}
Note: the string to uint conversion will lose leading NULLs, and the uint to string conversion will lose trailing NULLs.
I'm not sure what exactly you mean, but characters are stored in memory as their "representation", so you don't need to convert anything. If you still want to, you have to be more specific.
EDIT: You can
Try to read byte by byte shifting the result 8 bits left and oring it
with the next byte.
Try to use mpz_inp_raw
You can use a tree similar to Huffman compression algorithm, and then represent the path in the tree as numbers.
You'll have to keep the dictionary somewhere, but you can just create a constant dictionary that covers the whole ASCII table, since the compression is not the goal here.
There is no conversion needed. You can just use pointers.
Example:
char array[4 * NUMBER];
int *pointer;
Keep in mind that the "length" of pointer is NUMBER.
As mentioned, character strings are already ranges of bytes (and hence easily rendered as decimal numbers) to start with. Number your bytes from 000 to 255 and string them together and you've got a decimal number, for whatever that is worth. It would help if you explained exactly why you would want to be using decimal numbers, specifically, as hex would be easier.
If you care about compression of the underlying arrays forming these numbers for Unicode Strings, you might be interested in:
http://en.wikipedia.org/wiki/Standard_Compression_Scheme_for_Unicode
If you want some benefits of compression but still want fast random-access reads and writes within a "packed" number, you might find my "NSTATE" library to be interesting:
http://hostilefork.com/nstate/
For instance, if you just wanted a representation that only acommodated 26 english letters...you could store "test" in:
NstateArray<26> myString (4);
You could read and write the letters without going through a compression or decompression process, in a smaller range of numbers than a conventional string. Works with any radix.
Assuming you want to store the integers(I'm reading as ascii codes) in a string. This will add the leading zeros you will need to get it back into original string. character is a byte with a max value of 255 so it will need three digits in numeric form. It can be done without STL fairly easily too. But why not use tools you have?
#include <iostream>
#include <sstream>
using namespace std;
char array[] = "test";
int main()
{
stringstream out;
string s=array;
out.fill('0');
out.width(3);
for (int i = 0; i < s.size(); ++i)
{
out << (int)s[i];
}
cout << s << " -> " << out.str();
return 0;
}
output:
test -> 116101115116
Added:
change line to
out << (int)s[i] << ",";
output
test -> 116,101,115,116,
I don't see this an option in things like sprintf().
How would I convert the letter F to 255? Basically the reverse operation of conversion using the %x format in sprintf?
I am assuming this is something simple I'm missing.
char const* data = "F";
int num = int(strtol(data, 0, 16));
Look up strtol and boost::lexical_cast for more details and options.
Use the %x format in sscanf!
The C++ way of doing it, with streams:
#include <iomanip>
#include <iostream>
#include <sstream>
int main() {
std::string hexvalue = "FF";
int value;
// Construct an input stringstream, initialized with hexvalue
std::istringstream iss(hexvalue);
// Set the stream in hex mode, then read the value, with error handling
if (iss >> std::hex >> value) std::cout << value << std::endl;
else std::cout << "Conversion failed" << std::endl;
}
The program prints 255.
You can't get (s)printf to convert 'F' to 255 without some black magic. Printf will convert a character to other representations, but won't change its value. This might show how character conversion works:
printf("Char %c is decimal %i (0x%X)\n", 'F', 'F', 'F');
printf("The high order bits are ignored: %d: %X -> %hhX -> %c\n",
0xFFFFFF46, 0xFFFFFF46, 0xFFFFFF46, 0xFFFFFF46);
produces
Char F is decimal 70 (0x46)
The high order bits are ignored: -186: FFFFFF46 -> 46 -> F
Yeah, I know you asked about sprintf, but that won't show you anything until you do another print.
The idea is that each generic integer parameter to a printf is put on the stack (or in a register) by promotion. That means it is expanded to it's largest generic size: bytes, characters, and shorts are converted to int by sign-extending or zero padding. This keeps the parameter list on the stack in sensible state. It's a nice convention, but it probably had it's origin in the 16-bit word orientation of the stack on the PDP-11 (where it all started).
In the printf library (on the receiving end of the call), the code uses the format specifier to determine what part of the parameter (or all of it) are processed. So if the format is '%c', only 8 bits are used. Note that there may be some variation between systems on how the hex constants are 'promoted'. But if a value greater thann 255 is passed to a character conversion, the high order bits are ignored.