Having an issue with character displacemet - c++

I'm reading a file with a line of text. I'm reading the file and changing the characters based on a displacement given by the user. While it works for some characters, it doesn't for others beyond a certain point.
My file contains this text: "This is crazy".
When I run my code with a displacement of 20, this is what I get:
▒bc▒ c▒ w▒u▒▒
string Security::EncWordUsingRot(int rotNum, string word)
{
rotNum = rotNum%26;
string encWord = word;
for (int i = 0; i < word.size(); i++)
{
char c = word[i];
c = tolower(c);
if ((c < 'a') || (c > 'z'))
encWord[i] = c;
else
{
c = (c + rotNum);
if (c > 'z')
c = (c - 26);
}
encWord[i] = c;
}
return encWord;
}
*EDIT**
I changed the commented sections to correct my error. I changed unsigned char c = word[i] back to char c = word[i]. I also added another two lines of code that took care of the value of c being lower than 'a'. I did this because I noticed an issue when I wanted to essentially return the encrypted statement to its original form.
string Security::EncWordUsingRot(int rotNum, string word)
{
rotNum = rotNum%26;
string encWord = word;
for (int i = 0; i < word.size(); i++)
{
char c = word[i]; //removed unsigned
c = tolower(c);
if ((c < 'a') || (c > 'z'))
encWord[i] = c;
else
{
c = (c + rotNum);
if (c > 'z')
c = (c - 26);
if (c < 'a') //but I added this if statement if the value of c is less than 'a'
c = (c + 26);
}
encWord[i] = c;
}
return encWord;
}

Change:
char c = word[i];
To:
unsigned char c = word[i];

In C and C++ you should always pay attention to numeric overflow because the language assumption is that a programmer will never make such a mistake.
A char is a kind of integer and is quite often 8 bits and signed, giving it an acceptable range of -128...127. This means that when you store a value in a char variable you should never exceed those bounds.
char is also a "storage type" meaning that computations are never done using chars and for example
char a = 'z'; // numeric value is 122 in ASCII
int x = a + 20; // 122 + 20 = 142
x will actually get the value 142 because the computation did not "overflow" (all char values are first converted to integers in an expression)
However storing a value bigger that the allowable range in a variable is undefined behaviour and code like
char a = 'z'; // numeric value is 122 in ASCII
char x = a + 20; // 122 + 20 = 142 (too big, won't fit)
is not acceptable: the computation is fine but the result doesn't fit into x.
Storing a value outside the valid range for signed chars in a signed char variable is exactly what your code did and that's the reason for the strange observed behaviour.
A simple solution is to use an integer to store the intermediate results instead of a char.
A few more notes:
A few functions about chars are indeed handling integers because they must be able to handle the special value EOF in addition to all valid chars. For example fgetc returns an int and isspace accepts an int (they return/accept either the code of the char converted to unsigned or EOF).
char could be signed or not depending on the compiler/options; if unsigned and 8-bit wide the allowable range is 0...255
Most often when storing a value outside bounds into a variable you simply get a "wrapping" behavior, but this is not guaranteed and doesn't always happen. For example a compiler is allowed to optimize (char(x + 20) < char(y + 20)) to (x < y) because the assumption is that the programmer will never ever overflow with signed numeric values.

Related

hexa-decimal to decimal conversion (using implicit type casting)

I think there's some problem in my vs code I am new to this coding stuff even after writing the correct code it gives me wrong results in almost every second code I write i get uncertain results Plz guys help me with this , plz check running this code in your machine....
#include <iostream>
using namespace std;
int main()
{
char a[30];
cout << "enter the hexadecimal";
cin >> a;
int i = 0, c, digit, decimal = 0, p = 1;
while (a[i] != '\0') {
i++;
}
for (int j = i; j >= 0; j--) {
c = a[j];
if (c >= 48 && c <= 57) {
digit = c - 48;
}
else if (c >= 97 && c <= 112) {
digit = c - 87;
}
decimal += digit * p;
p *= 8;
}
cout << "\ndecimal is " << decimal;
return 0;
}
while entering hexa decimal plz only enter small alphabets i have not taken capital letters into consideration
for cheking hexadecimal to decimal use this site https://www.rapidtables.com/convert/number/hex-to-decimal.html?x=146
There are several problems with the code, but I think that the main one is that you are multiplying p by 8 when it should be 16 (as hex is base-16, not base-8).
You also should take care with invalid inputs. What happens if someone enters an invalid letter 'j' for instance?
Besides, when you calculate the initial length of the string, you are setting ito the position of the array with a '\0' value so when you start processing the input, a[i] is 0 and that leads to using an uninitialized variable (digit has not been assigned a value, this is related to the previous "invalid input" issue).
By the way, I would also use chars in the comparisions instead of ASCII codes, it's easier to see what you are looking for:
if (c >= '0' && c <= '9') {
digit = c - '0';
}
and so on...

Transform 'B' into 0xB

I'm trying to decode ISO8583 message bitmap in a fast way. Supposing the first bitmap char is a 'B', I want to convert it to hex value 0xB (11 in decimal) to after that, check what bits are flagged. The last part I'm doing this way:
for(int i = 0; i < 4; i++){
std::cout << (value &(1 << i));
}
Because bitmaps and messages are long I'm trying to decoding fast. I saw some SO posts using std::hex and std::stringstream. But using this or lookup tables it isn't too much?
What I want is convert from 'B' to hex value 0xB, which is 11
So, you want to interpret B as hexadecimal digit and get numerical value, rather than "convert it to hexadecimal representation". Following works for any base (up to base 36) and with upper and lower case digits:
int value =
(c >= '0' && c <= '9') ? (c - '0') :
(c >= 'A' && c <= 'Z') ? (c - 'A' + 0xA) :
(c >= 'a' && c <= 'z') ? (c - 'a' + 0xA) :
-1; // error
You can substitute z with f if you want the error value when input is not a hexadecimal digit.
Old answer:
Characters are encoded as numbers. What numerical value represents which character is determined by the character encoding.
"Hex representation" of a number is a string of characters. Those characters represent the hexadecimal digits of the number individually. The numerical values of the characters in the hex representation are meaningless without the context of the character encoding.
Supposing the first bitmap char is a 'B', I want to convert it to hex representation (Transform 'B' into 0xB)
#include <string>
using namespace std::string_literals;
int main() {
char c = 'B';
std::string hex = "0x"s + c; // now hex is "0xB"
}
It would indeed be quite inefficient to first convert B to an integer, and then back to hex representation with std::stringstream if all you want is to add the prefix.
Create an array that acts as a map.
int hexNumbers[] = { 0xA, 0xB, 0xC, 0xD, 0xE, 0xF };
and then use it to as below:
if ( c >= 'A' && c <= 'F' )
{
number = hexNumbers[c-'A'];
}
else if ( c >= 'a' && c <= 'f' )
{
number = hexNumbers[c-'a'];
}
You can do it without a map also:
if ( c >= 'A' && c <= 'F' )
{
number = 0xA + (c-'A');
}
else if ( c >= 'a' && c <= 'f' )
{
number = 0xA + (c-'a');
}

Appending character to a string in C with strcat

Hi guys I'm still really confused with pointers and I'm wondering if there's anyways to do the following without having to use sprintf:
char a[100], b[100], c[2];
//Some code that puts a string into a
for(i = 0; i<strlen(a); i++)
{
if(a[i] == 'C')
strcat(b, "b");
else if(a[i] == 'O')
strcat(b, "a");
else if(a[i] == 'D')
strcat(b, "1");
else
{
sprintf(c, "%s", a[i]);
strcat(b, c);
}
}
pretty much a for loop looping through a string(an array) and filling up another string with a character(or string) depending on what the character is, if the character ain'T C, O or D it just adds it to the other string.
I can't seem to just do strcat(b, a[i]); and I understand that it wouldn't work because it would try strcat(char *, char) instead of char*, const char*).
Is there anyway I can turn it into a pointer? they still confuse me so much..and I'm new to programming in general just to low level languages...
also what would be the best way to initialize char[]s? that are gonna be filled with a string, what I use right now is :
char ie[30] = ""
Also let me know if there's any easier way to do what
I want and sorry if it's unclear this is obviously a throwaway script but the same concept is used in my script.
Thank you in advance stackoverflow :X
(1) One bug may be in your code:
You are commenting that Some code that puts a string into a, and I think you don't assign any string to b. so by default char b[100]; have garbage value (may not present \0 in b). but string concatenation function expects that b must be a string. So
strcat(b, "b"); <--will Undefined Behavior
(2) A technique to initialize empty string:
Yes you should always initialize you variable (array) with default values like:
char a[100] = {0}, b[100] = {0}, c[2] = {0};
note: remaining elements of a half initialize array would be 0 (null), Initialize a variable assume to be good practice
(3) Yes strcat(b, a[i]); is wrong:
To concatenate string from a[i] on words into b you can do like:
strcat(b, a + i);
yes you are correct strcat(b, a[i]); is not valid indeed.
note: a[i] and (a + i) are not same, a[i] is char type, where as (a + i) is string that is type of a.
Suppose you have following string array a and value of i is 2 then:
+----+----+----+---+---+----+----+----+---+
| 'u'| 's' |'e'|'r'|'5'| '6'| '7'|'8' | 0 |
+----+----+----+---+---+----+----+----+---+
201 202 203 204 205 206 207 208 209 210 211
^ ^
| |
a (a+i)
So in above diagram a values is 201 and type is char [100] (assuming array is 100 in size) (a + i) also points a string from 'e' at address 203. where as a[i] = 'e'
So you can't do strcat(b, a[i]); but strcat(b, a + i); is valid syntax.
Additionally, From #BenVoigt to concat n chars from a from ith position you can do like:
strncat(b, a+i, n);
its will append n char from a+i to b.
Since you want to take a substring of a exactly one character long:
strncat(b, a+i, 1);
Initialize all char array to null so that no garbage values exists in code.
You are appending to garbaged char array.
char a[100]={0}, b[100]={0}, c[2]={0};
Now strcat() function behaves properly.
You seem to be confused in regards to strings. A string isn't just an array. Which book are you reading?
When you first call strcat to operate on b, b isn't guaranteed to be a string. The result is undefined behaviour. This code might seem to function correctly on your system, but if it does then that is by coincidence. I have seen code like this fail in strange ways on other systems. Fix it like this:
char a[100], b[100];
//Some code that puts a string into a
a[x] = '\0'; // <--- Null terminator is required for a to contain a "string".
// Otherwise, you can't pass a to strlen.
for(i = 0; i<strlen(a); i++)
{
if(a[i] == 'C')
b[i] = 'b';
else if(a[i] == 'O')
b[i] = 'a';
else if(a[i] == 'D')
b[i] = '1';
else
b[i] = a[i];
}
b[i] = '\0'; // If you don't put a null character at the end, it isn't a string.
Now, what is a string?
There are many possible ways to do as you wish. There are ways that avoid using strcat() and sprintf() altogether — see below; you can avoid sprintf() while continuing to use strcat().
The way I'd probably do it would keep a record of where the next character is to be added to the target string, b. This will be more efficient since repeatedly using strcat() involves quadratic behaviour as you build up a string one character at a time. Also, it is generally best to avoid using strlen() in the loop condition for the same reason; it is (probably) evaluated on each iteration, so that it too leads to quadratic behaviour.
char a[100], b[100];
char *bp = b;
//Some code that puts a string into a
size_t len = strlen(a);
for (int i = 0; i < len; i++, bp++)
{
if (a[i] == 'C')
*bp = 'b';
else if(a[i] == 'O')
*bp = 'a';
else if(a[i] == 'D')
*bp = '1';
else
*bp = a[i];
}
*bp = '\0'; // Null-terminate the string
You could also do without the pointer by using the index variable i to assign to b (as long as you only add one character to the output for each input character):
char a[100], b[100];
//Some code that puts a string into a
size_t len = strlen(a);
for (int i = 0; i < len; i++)
{
if (a[i] == 'C')
b[i] = 'b';
else if(a[i] == 'O')
b[i] = 'a';
else if(a[i] == 'D')
b[i] = '1';
else
b[i] = a[i];
}
b[i] = '\0'; // Null-terminate the string
As long as the string in a is short enough to fit, the code shown (either version) cannot overflow b. If you sometimes added several characters to b, you'd either need to indexes (i and j), or you could increment the pointer bp in the first version more than once per loop, and you'd need to ensure that you don't overflow the bounds of b.

How to convert a string of hex values to a string?

Say I have a string like:
string hex = "48656c6c6f";
Where every two characters correspond to the hex representation of their ASCII, value, eg:
0x48 0x65 0x6c 0x6c 0x6f = "Hello"
So how can I get "hello" from "48656c6c6f" without having to create a lookup ASCII table? atoi() obviously won't work here.
int len = hex.length();
std::string newString;
for(int i=0; i< len; i+=2)
{
std::string byte = hex.substr(i,2);
char chr = (char) (int)strtol(byte.c_str(), null, 16);
newString.push_back(chr);
}
Hex digits are very easy to convert to binary:
// C++98 guarantees that '0', '1', ... '9' are consecutive.
// It only guarantees that 'a' ... 'f' and 'A' ... 'F' are
// in increasing order, but the only two alternative encodings
// of the basic source character set that are still used by
// anyone today (ASCII and EBCDIC) make them consecutive.
unsigned char hexval(unsigned char c)
{
if ('0' <= c && c <= '9')
return c - '0';
else if ('a' <= c && c <= 'f')
return c - 'a' + 10;
else if ('A' <= c && c <= 'F')
return c - 'A' + 10;
else abort();
}
So to do the whole string looks something like this:
void hex2ascii(const string& in, string& out)
{
out.clear();
out.reserve(in.length() / 2);
for (string::const_iterator p = in.begin(); p != in.end(); p++)
{
unsigned char c = hexval(*p);
p++;
if (p == in.end()) break; // incomplete last digit - should report error
c = (c << 4) + hexval(*p); // + takes precedence over <<
out.push_back(c);
}
}
You might reasonably ask why one would do it this way when there's strtol, and using it is significantly less code (as in James Curran's answer). Well, that approach is a full decimal order of magnitude slower, because it copies each two-byte chunk (possibly allocating heap memory to do so) and then invokes a general text-to-number conversion routine that cannot be written as efficiently as the specialized code above. Christian's approach (using istringstream) is five times slower than that. Here's a benchmark plot - you can tell the difference even with a tiny block of data to decode, and it becomes blatant as the differences get larger. (Note that both axes are on a log scale.)
Is this premature optimization? Hell no. This is the kind of operation that gets shoved in a library routine, forgotten about, and then called thousands of times a second. It needs to scream. I worked on a project a few years back that made very heavy use of SHA1 checksums internally -- we got 10-20% speedups on common operations by storing them as raw bytes instead of hex, converting only when we had to show them to the user -- and that was with conversion functions that had already been tuned to death. One might honestly prefer brevity to performance here, depending on what the larger task is, but if so, why on earth are you coding in C++?
Also, from a pedagogical perspective, I think it's useful to show hand-coded examples for this kind of problem; it reveals more about what the computer has to do.
std::string str("48656c6c6f");
std::string res;
res.reserve(str.size() / 2);
for (int i = 0; i < str.size(); i += 2)
{
std::istringstream iss(str.substr(i, 2));
int temp;
iss >> std::hex >> temp;
res += static_cast<char>(temp);
}
std::cout << res;
strtol should do the job if you add 0x to each hex digit pair.

"The Debugger has exited due to signal 10" when writing a char* iteration

So I have a program that makes char* stuff lowercase. It does it by iterating through and manipulating the ascii. Now I know there's probably some library for this in c++, but that's not the point - I'm a student trying to get a grasp on char*s and stuff :).
Here's my code:
#include <iostream>
using namespace std;
char* tolower(char* src);
int main (int argc, char * const argv[])
{
char* hello = "Hello, World!\n";
cout << tolower(hello);
return 0;
}
char* tolower(char* src)
{
int ascii;
for (int n = 0; n <= strlen(src); n++)
{
ascii = int(src[n]);
if (ascii >= 65 && ascii <= 90)
{
src[n] = char(ascii+32);
}
}
return src;
}
( this is not for an assignment ;) )
It builds fine, but when I run it it I get a "The Debugger has exited due to signal 10" and Xcode points me to the line: "src[n] = char(ascii+32);"
Thanks!
Mark
Yowsers!
Your "Hello World!" string is what is called a string literal, this means its memory is part of the program and cannot be written to.
You are performing what is called an "in-place" transform, e.g. instead of writing out the lowercase version to a new buffer you are writing to the original destination. Because the destination is a literal and cannot be written to you are getting a crash.
Try this;
char hello[32];
strcpy(hello, "Hello, World!\n");
Also in your for loop, you should use <, not <=. strlen returns the length of a string minus its null terminator, and array indices are zero-based.
As Andrew noted "Hello World\n" in code is a read-only literal. You can either use strcpy to make a modifiable copy, or else try this:
char hello[] = "Hello, World!\n";
This automatically allocates an array on the stack big enough to hold a copy of the literal string and a trailing '\0', and copies the literal into the array.
Also, you can just leave ascii as a char, and use character literals instead of having to know what the numeric value of 'A' is:
char ascii;
for (int n = 0; n < strlen(src); n++)
{
ascii = src[n];
if (ascii >= 'A' && ascii <= 'Z')
{
src[n] = ascii - 'A' + 'a';
}
}
While you're at it, why bother with ascii at all, just use src[n]:
for (int n = 0; n < strlen(src); n++)
{
if (src[n] >= 'A' && src[n] <= 'Z')
{
src[n] -= 'A' - 'a';
}
}
And then, you can take advantage of the fact that in order to determine the length of a c-string, you have to iterate though it anyway, and just combine both together:
for (char *n = src; *n != 0; n++)
if (*n >= 'A' && *n <= 'Z')
*n -= 'A' - 'a';