i have a question regarding splitting a string. I am working on creating a binary to Hex converter, and want to split up my binary sequence that is represented as a string by 4 chars so that I can easily convert each set of 4 bits into a hexadecimal form:
Example:
00000111010110111100110100010101
would turn into:
"0000", "0111", "0101", "1011", "1100", "1101", "0001", "0101"
Thank you for any assistance you can provide!
Using the std::string::substr function and a simple for loop you can just sub-divide the string into groups of 4 and push them into a std::vector<std::string> as shown below...
#include <iostream>
#include <vector>
#include <string>
int main() {
std::string nums = "00000111010110111100110100010101";
std::vector<std::string> bins;
for (std::size_t i = 0; i < nums.size(); i += 4)
bins.push_back(nums.substr(i, 4));
return 0;
}
Then bins becomes a std::vector filled with the sub-divided binary numbers.
Related
So I want to build a simple calculator program with hexadecimals as their input. But the input would also contain both the operation and the numbers to operate. The first two hexadecimals would be the math operations which are 01 = addition, 02 = subtraction, 03 = multiplication, and 04 = division, and the following four or more hexadecimals would be two hexadecimals (a max value of FF) to operate on.
An example input would be 010306 where it would be the operation 03 + 06 since 01 is addition and 03 and 06 being the numbers to operate on. I can manage implementing the calculator part but I can't seem to figure out how to chop up strings by 2 and convert them to hexadecimals. I kind of know a way but I do now know the correct syntax. Here is my thought code:
#include <iostream>
#include <iterator>
#include <string>
using namespace std;
int main() {
string input = "010306";
int exampleHex[input.length()/2];
for(int index = 0; index < exampleHex.length(); index+2){
exampleHex[index] = stoi(input[index] + stoi(input[index+1]), 0, 16);
}
/*
* or somethiing like this to somehow get
* int exampleHex[] = {01, 03, 06}
*/
return 0;
}
For the splitting, doing something like this should produce the result you want, so long as it's always a consistent 2 (or whatever) characters.
std::string nums = "010306";
int splitLength = 2;
std::vector<std::string> substrings;
for (int i = 0; i < nums.length(); i += splitLength)
{
substrings.push_back(nums.substr(i, splitLength));
}
Giving the resulting vector { "01", "03", "06" }
I'm trying to understand how can I convert multiple integers from a string. I have tried to use atoi(), stoi() and istringstream() and they all do the same thing. I can't get more than one integer.
For example, if the string is "Chocolate and Milk 250 pounds and 2 oz or 1.5 coins."
All of the above functions will not work. It won't take the whole string. If I leave only a single number then it will work. I want to be able to read the whole string and get all of the integers only (not float).
I am using a while(getline()) for the string. Then try to get it into string.
Although, if I could only return the total amount of integers in the string that would be better. Either way, I'm trying to learn both ways. In this case, the output would be "2", since there are only two int.
One way is to split the string using as delimiter and using stoi on individual strings to check if they are integers.
#include <iostream>
#include <sstream>
#include <string>
int main(){
std::string s = "Chocolate and Milk 250 pounds and 2 oz or 1.5 coins.";
int count = 0;
std::istringstream iss(s);
std::string token;
while(getline(iss,token,' ')){
if(std::isdigit(token[0]) &&stoi(token) && token.find('.')==std::string::npos){
count++;
}
}
std::cout<<count<<std::endl;
}
Note that more complex checks can be done on strings if stoi succeeds, but the input is not a valid integer. You can have a helper function which checks if all the characters are digits or not by using isdigit etc.
I have a string = "abcdefg". I will copy it to another string inside a loop. Then I want to erase only one character every time. First I will remove the character a from the first and it will be "bcdefg". Second time I will remove b and the string will be "acdefg". And so on. I tried to do it using erase() but it didn't work. You may take a look at how I tried:
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int main() {
string abc = "abcdefg"; // the main string
int len = abc.length();
for(int i=0;i<len;i++)
{
string cba = abc; // I copy it to another string
cba.erase(i,i+1); // I try to erase only one element
cout<<cba<<endl;
}
return 0;
}
The output should be:
bcdefg
acdefg
abdefg
abcefg
abcdfg
abcdeg
abcdef
But my code prints:
bcdefg
adefg
abfg
abc
abcd
abcde
abcdef
Can anybody please suggest me a way to do it correctly?? I'm really in danger.
The std::basic_string::erase function you are calling takes an index and a count. The second parameter is the number of characters to remove and you should be using 1.
For some example code:
//M a r k
//0 1 2 3
string name = "Mark";
//erase the single character 'r' at position 2
name.erase(2, 1); //M a k
PROBLEM SOLVED: thanks everyone!
I am almost entirely new to C++ so I apologise in advance if the question seems trivial.
I am trying to convert a string of letters to a set of 2 digit numbers where a = 10, b = 11, ..., Y = 34, Z = 35 so that (for example) "abc def" goes to "101112131415". How would I go about doing this? Any help would really be appreciated. Also, I don't mind whether capitalization results in the same number or a different number. Thank you very much in advance. I probably won't need it for a few days but if anyone is feeling particularly nice how would I go about reversing this process? i.e. "101112131415" --> "abcdef" Thanks.
EDIT: This isn't homework, I'm entirely self taught. I have completed this project before in a different language and decided to try C++ to compare the differences and try to learn C++ in the process :)
EDIT: I have roughly what I want, I just need a little bit of help converting this so that it applies to strings, thanks guys.
#include <iostream>
#include <sstream>
#include <string>
int returnVal (char x)
{
return (int) x - 87;
}
int main()
{
char x = 'g';
std::cout << returnVal(x);
}
A portable method is to use a table lookup:
const unsigned int letter_to_value[] =
{10, 11, 12, /*...*/, 35};
// ...
letter = toupper(letter);
const unsigned int index = letter - 'A';
value = letter_to_value[index];
cout << index;
Each character has it's ASCII values. Try converting your characters into ASCII and then manipulate the difference.
Example:
int x = 'a';
cout << x;
will print 97; and
int x = 'a';
cout << x - 87;
will print 10.
Hence, you could write a function like this:
int returnVal(char x)
{
return (int)x - 87;
}
to get the required output.
And your main program could look like:
int main()
{
string s = "abcdef"
for (unsigned int i = 0; i < s.length(); i++)
{
cout << returnVal(s[i]);
}
return 0;
}
This is a simple way to do it, if not messy.
map<char, int> vals; // maps a character to an integer
int g = 1; // if a needs to be 10 then set g = 10
string alphabet = "abcdefghijklmnopqrstuvwxyz";
for(char c : alphabet) { // kooky krazy for loop
vals[c] = g;
g++;
}
What Daniel said, try it out for yourself.
As a starting point though, casting:
int i = (int)string[0] + offset;
will get you your number from character, and: stringstream will be useful too.
How would I go about doing this?
By trying to do something first, and looking for help only if you feel you cannot advance.
That being said, the most obvious solution that comes to mind is based on the fact that characters (i.e. 'a', 'G') are really numbers. Suppose you have the following:
char c = 'a';
You can get the number associated with c by doing:
int n = static_cast<int>(c);
Then, add some offset to 'n':
n += 10;
...and cast it back to a char:
c = static_cast<char>(n);
Note: The above assumes that characters are consecutive, i.e. the number corresponding to 'a' is equal to the one corresponding to 'z' minus the amount of letters between the two. This usually holds, though.
This can work
int Number = 123; // number to be converted to a string
string Result; // string which will contain the result
ostringstream convert; // stream used for the conversion
convert << Number; // insert the textual representation of 'Number' in the characters in the stream
Result = convert.str(); // set 'Result' to the contents of the stream
you should add this headers
#include <sstream>
#include <string>
Many answers will tell you that characters are encoded in ASCII and that you can convert a letter to an index by subtracting 'a'.
This is not proper C++. It is acceptable when your program requirements include a specification that ASCII is in use. However, the C++ standard alone does not require this. There are C++ implementations with other character sets.
In the absence of knowledge that ASCII is in use, you can use translation tables:
#include <limits.h>
// Define a table to translate from characters to desired codes:
static unsigned int Translate[UCHAR_MAX] =
{
['a'] = 10,
['b'] = 11,
…
};
Then you may translate characters to numbers by looking them up in the table:
unsigned char x = something;
int result = Translate[x];
Once you have the translation, you could print it as two digits using printf("%02d", result);.
Translating in the other direction requires reading two characters, converting them to a number (interpreting them as decimal), and performing a similar translation. You might have a different translation table set up for this reverse translation.
Just do this !
(s[i] - 'A' + 1)
Basically we are converting a char to number by subtracting it by A and then adding 1 to match the number and letters
Initially I have user input decimal numbers (0 - 15), and I will turn that into binary numbers.
Say these numbers are written into a text file, as shown in the picture. These numbers are arranged by the numbers of 1's. The dash - is used to separate different groups of 1.
I have to read this file, and compare strings of one group with the all the strings in the group below, i.e., Group 1 with all the strings in group 2, and group 2 - group 3.
The deal is that, only one column of 0 / 1 difference is allowed, and that column is replaced by letter t. If more than one column of difference is encountered, write none.
So say group 2, 0001 with group 3, 0011, only the second column is different. however, 0010 and 0101 are two columns of difference.
The result will be written into another file.....
At the moment, when I am reading these strings, I am using vector string. I came across bitset. What is important is that I have to access the character one at a time, meaning I have break the vector string into vector char. But it seems like there could be easier way to do it.
I even thought about a hash table - linked-list. Having group 1 assigned to H[0]. Each comparison is done as H[current-group] with H[current_group+1]. But beyond the first comparison (comparing 1's and 0's), the comparison beyond that will not work under this hash-linked way. So I gave up on that.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
using namespace std;
int main() {
ifstream inFile("a.txt");
vector<string> svec;
copy(istream_iterator<string>(inFile), istream_iterator<string>(), back_inserter(svec));
copy(svec.begin(), svec.end(), ostream_iterator<string>(cout,"\n"));
for(int i = 0; i < svec.size(); i++)
{
cout << svec[i] << " ";
}
inFile.close();
return 0;
}
This is the sample code of writing it into a file....but like I said, the whole deal of vector seems impractical in my case....
Any help is appreciated. thanks
I don't understand your code snippet -- it looks like all it does is read in the input file into a vector of strings, which will then contain each whitespace-delimited word in a separate string, then write it back out in 2 different ways (once with words separated by \n, once with them separated by spaces).
It seems the main problem you're having is with reading and interpreting the file itself, as opposed to doing the necessary calculations -- right? That's what I hope this answer will help you with.
I think the line structure of the file is important -- right? In that case you would be better off using the global getline() function in the <string> header, which reads an entire line (rather than a whitespace-delimited word) into a string. (Admittedly that function is pretty well-hidden!) Also you don't actually need to read all the lines into a vector, and then process them -- it's more efficient and actually easier to distill them down to numbers or bitsets as you go:
vector<unsigned> last, curr; // An unsigned can comfortably hold 0-15
ifstream inf("a.txt");
while (true) {
string line;
getline(inf, line); // This is the group header: ignore it
while (getline(inf, line)) {
if (line == "-") {
break;
}
// This line contains a binary string: turn it into a number
// We ignore all characters that are not binary digits
unsigned val = 0;
for (int i = 0; i < line.size(); ++i) {
if (line[i] == '0' || line[i] == '1') {
val = (val << 1) + line[i] - '0';
}
}
curr.push_back(val);
}
// Either we reached EOF, or we saw a "-". Either way, compare
// the last 2 groups.
compare_them_somehow(curr, last); // Not doing everything for you ;)
last = curr; // Using swap() would be more efficient, but who cares
curr.clear();
if (inf) {
break; // Either the disk exploded, or we reached EOF, so we're done.
}
}
Perhaps I've misunderstood your goal, but strings are amenable to array member comparison:
string first = "001111";
string next = "110111";
int sizeFromTesting = 5;
int columnsOfDifference = 0;
for ( int UU = sizeFromTesting; UU >=0; UU-- )
{
if ( first[ UU ] != next[ UU ] )
columnsOfDifference++;
}
cout << columnsOfDifference;
cin.ignore( 99, '\n' );
return 0;
Substitute file streams and bound protection where appropriate.
Not applicable, but to literally bitwise compare variables, & both using a mask for each digit (000010 for second digit).
If or = 0, they match: both are 0. If they or = 1 and & = 1, that digit is 1 for both. Otherwise they differ. Repeat for all the bits and all the numbers in the group.
in vb.net
'group_0 with group_1
If (group_0_count > 0 AndAlso group_1_count > 0) Then
Dim result = ""
Dim index As Integer = 0
Dim g As Integer = 0
Dim h As Integer = 0
Dim i As Integer = 0
For g = 0 To group_0_count - 1
For h = 0 To group_1_count - 1
result = ""
index = 0
For i = 0 To 3
If group_1_0.Items(g).ToString.Chars(i) <> group_1_1.Items(h).ToString.Chars(i) Then
result &= "-"
index = index + 1
Else
result &= group_1_0.Items(g).ToString.Chars(i)
End If
Next
Next
Next
End If
Read it in as an integer, then all you should need is comparisons with bitshifts and bit masks.