Task:Write a code to the new string of Dna According to its pattern. Just so you know In DNA strings, symbols "A" and "T" are complements of each other, as "C" and "G".
Fore example:DNA_strand ("ATTGC") //returns "TAACG" or DNA_strand ("GTAT") //returns "CATA"
My Code=>
#include <string>
#include <vector>
#include <iostream>
std::string DNAStrand(const std::string& dna)
{
std::string Sym;
std::string c;
std::stringstream s;
s << Sym;
s >> c;
for(int i = 0; i < dna.size() - 1; i++) {
switch (dna[i]) {
case ('A'):
Sym[i] = 'T';
break;
case ('T'):
Sym[i] = 'A';
break;
case ('C'):
Sym[i] = 'G';
break;
case ('G'):
Sym[i] = 'C';
break;
default:
std::cout << "invalid";
} return c.str();
}
int main() {
std::cout << DNAStrand("ATTGC") << "\n"; //retun "TAACG"
std::cout << DNAStrand("GTAT") << "\n"; //retun "CATA"
}
}
You have created a vector<string>, but in the if statements, you are setting the elements of the vector to chars. You want to build a string, not a vector<string>.
You should replace subsequent if statements with else if, or use a switch statement. Otherwise if statements subsequent to a satisfied if statement are executed needlessly.
Replace this vector with an ostringstream. Naming the stream as s, you would append a char named c with s << c. At the end of iterating over dna, return s.str().
I'm working on an arduino assignment that splits an incoming string and puts the terms of the string in 6 different variables( a sample input string when split up has 6 terms). i have the following error popping up: cannot convert 'String' to 'char*' for argument '1' to 'char* strtok(char*, const char*)' . Can you guys suggest changes to the code to get it right ?
String str(" ");
char a[5],b[5],c[5],d[5],e[5],f[5];
char *token = strtok(str, " ");
void setup()
{
Serial.begin(9600);
}
void loop(){
while (!Serial.available());
str = Serial.readStringUntil('\n');
Serial.println(str);
strcpy(a,token);
token = strtok(NULL, " ");
strcpy(b,token);
token = strtok(NULL, " ");
strcpy(c,token);
token = strtok(NULL, " ");
strcpy(d,token);
token = strtok(NULL, " ");
strcpy(e,token);
token = strtok(NULL, " ");
strcpy(f,token);
Serial.println(a);
Serial.println(b);
Serial.println(c);
Serial.println(d);
Serial.println(e);
Serial.println(f);
}
enter code here
You need to convert str to char array, because strtok expects char* argument, not String.
String str("...");
char str_array[str.length()];
str.toCharArray(str_array, str.length());
char* token = strtok(str_array, " ");
// Define
String str = "This is my string";
// Length (with one extra character for the null terminator)
int str_len = str.length() + 1;
// Prepare the character array (the buffer)
char char_array[str_len];
// Copy it over
str.toCharArray(char_array, str_len);
I'm trying to interact with an API which takes GET and POST requests which include a signature derived from a message and my private key, hashed using HMAC SHA512. The docs give an example:
key (in base-64):
bEDtDJnW0y/Ll4YZitxb+D5sTNnEpQKH67EJRCmQCqN9cvGiB8+IHzB7HjsOs3mSlxLmu4aiPDRpe9anuWzylw==
message:
/account/balance1515058794242
should produce the following (base-64) signature:
NjqZ8Mgdkj6hrtY/xdKBy1S0kLjU2tA7G+pR2TdOBF45b7+evfpzGH/C/PiNHEDvuiRChRBlRo3AGJ7Gcvlwqw==
The docs also state that the key needs to be decoded from base-64 before using in the hmac, but is unclear about what format it should be in.
I've been playing around with online hmac generators and can replicate the example signature with no issue. For example, at https://www.liavaag.org/English/SHA-Generator/HMAC/ - input the above key as input type = Base-64, the above message string as input type = TEXT, and output type = base-64, and the output signature is the same as above. It also works fine when I give the key as HEX-type and use the hex equivalent:
6C40ED0C99D6D32FCB9786198ADC5BF83E6C4CD9C4A50287EBB1094429900AA37D72F1A207CF881F307B1E3B0EB379929712E6BB86A23C34697BD6A7B96CF297
BUT I cannot replicate the example signature using my own program using BCrypt. It seems that the BCrypt hmac is interpreting my key as 'TEXT'-type input in the same way as the online generator. That is, when I give the key as the hex string:
CONST BYTE key[] = { "6C40ED0C99D6D32FCB9786198ADC5BF83E6C4CD9C4A50287EBB1094429900AA37D72F1A207CF881F307B1E3B0EB379929712E6BB86A23C34697BD6A7B96CF297" };
I get an output signature (in hex) of:
16ab16ed3874fab51dbda66155edf269883d128de6067d77762dcee4129f1612b36fc556df10beb358c81262d034efe4c50d68d89ac43606df4318a8af56b
On the online generator I get the same output when I use that hex string (6C40...) as TEXT type key and ouput as HEX.
Is there any way I can force BCrypt to interpret my key as hex? I've even tried declaring the key as hex literals, i.e:
CONST BYTE key[] = { 0x6C, 0x40, 0xed, 0x0c, 0x99, 0xd6, 0xd3, 0x2f,
0xCB, 0x97, 0x86, 0x19, 0x8a, 0xdc, 0x5b, 0xf8,
0x3E, 0x6c, 0x4c, 0xd9, 0xc4, 0xa5, 0x02, 0x87,
0xeb, 0xb1, 0x09, 0x44, 0x29, 0x90, 0x0a, 0xa3,
0x7d, 0x72, 0xf1, 0xa2, 0x07, 0xcf, 0x88, 0x1f,
0x30, 0x7b, 0x1e, 0x3b, 0x0e, 0xb3, 0x79, 0x92,
0x97, 0x12, 0xe6, 0xbb, 0x86, 0xa2, 0x3c, 0x34,
0x69, 0x7b, 0xd6, 0xa7, 0xb9, 0x6c, 0xf2, 0x97 };
But this gives another, different signature. At least the hex string key is getting something sort of like replicating the online converter. Sorry for any confusion around why I'm using hex instead of base-64, which is what I'll eventually need to use - it's just an extra complicating step at the moment, so for now I'm just trying to get the hex equivalent working, and then I can concentrate on encoding it as base-64. The hex equivalent of the base-64 signature I'm trying to get is:
363a99f0c81d923ea1aed63fc5d281cb54b490b8d4dad03b1bea51d9374e045e396fbf9ebdfa73187fc2fcf88d1c40efba2442851065468dc0189ec672f970ab
Full code I'm using is below:
#include <windows.h>
#include <stdio.h>
#include <bcrypt.h>
#pragma comment(lib, "bcrypt.lib")
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
#include <fstream>
int hexToInt(char ch)
{
return 0;
}
void __cdecl wmain(
int argc,
__in_ecount(argc) LPWSTR *wargv)
{
std::wofstream fout;
fout.open("signature.txt");
BCRYPT_ALG_HANDLE hAlg = NULL;
BCRYPT_HASH_HANDLE hHash = NULL;
NTSTATUS status = STATUS_UNSUCCESSFUL;
DWORD cbData = 0,
cbHash = 0,
cbHashObject = 0;
PBYTE pbHashObject = NULL;
PBYTE pbHash = NULL;
CONST BYTE message[] = { "/account/balance1515058794242" };
CONST BYTE key[] = { "6C40ED0C99D6D32FCB9786198ADC5BF83E6C4CD9C4A50287EBB1094429900AA37D72F1A207CF881F307B1E3B0EB379929712E6BB86A23C34697BD6A7B96CF297" };
//open an algorithm handle
if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(
&hAlg,
BCRYPT_SHA512_ALGORITHM,
NULL,
BCRYPT_ALG_HANDLE_HMAC_FLAG)))
{
fout << "**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n" << status;
goto Cleanup;
}
//calculate the size of the buffer to hold the hash object
if (!NT_SUCCESS(status = BCryptGetProperty(
hAlg,
BCRYPT_OBJECT_LENGTH,
(PBYTE)&cbHashObject,
sizeof(DWORD),
&cbData,
0)))
{
fout << "**** Error 0x%x returned by BCryptGetProperty\n" << status;
goto Cleanup;
}
//allocate the hash object on the heap
pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHashObject);
if (NULL == pbHashObject)
{
fout << "**** memory allocation failed\n";
goto Cleanup;
}
//calculate the length of the hash
if (!NT_SUCCESS(status = BCryptGetProperty(
hAlg,
BCRYPT_HASH_LENGTH,
(PBYTE)&cbHash,
sizeof(DWORD),
&cbData,
0)))
{
fout << "**** Error 0x%x returned by BCryptGetProperty\n" << status;
goto Cleanup;
}
//allocate the hash buffer on the heap
pbHash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHash);
if (NULL == pbHash)
{
fout << "**** memory allocation failed\n";
goto Cleanup;
}
//create a hash
if (!NT_SUCCESS(status = BCryptCreateHash(
hAlg,
&hHash,
pbHashObject,
cbHashObject,
(PBYTE)key,
sizeof(key) - 1,
0)))
{
fout << "**** Error 0x%x returned by BCryptCreateHash\n" << status;
goto Cleanup;
}
//hash some data
if (!NT_SUCCESS(status = BCryptHashData(
hHash,
(PBYTE)message,
sizeof(message) - 1,
0)))
{
fout << "**** Error 0x%x returned by BCryptHashData\n" << status;
goto Cleanup;
}
//close the hash
if (!NT_SUCCESS(status = BCryptFinishHash(
hHash,
pbHash,
cbHash,
0)))
{
fout << "**** Error 0x%x returned by BCryptFinishHash\n" << status;
goto Cleanup;
}
fout << "\nThe hash is: \n";
for (DWORD i = 0; i < cbHash; i++)
{
fout << std::hex << pbHash[i];
}
Cleanup:
if (hAlg)
{
BCryptCloseAlgorithmProvider(hAlg, 0);
}
if (hHash)
{
BCryptDestroyHash(hHash);
}
if (pbHashObject)
{
HeapFree(GetProcessHeap(), 0, pbHashObject);
}
if (pbHash)
{
HeapFree(GetProcessHeap(), 0, pbHash);
}
fout.close();
};
You need to use the CONST BYTE key[] = { 0x6C, ... }; method of specifying your key. Keys and input data are binary data, represented as byte arrays in most programming languages. Hexadecimals and base 64 are two ways of representing or encoding binary values so that they can be used as printable text.
However, if you use a byte array then sizeof will return the number of actual bytes. Arrays aren't null terminated, so there is no reason to remove the final null byte. So sizeof(key) - 1 will remove the last byte of the key as input parameter, rather than remove the non-existent null byte.
The message string is null terminated, so it should work well. You may however explicitly want to mention that the message needs to be US-ASCII or explicitly encode the string (e.g. to UTF-8).
Here is the entire program, please help me, I've tried everything to find out what exactly is going with the memory. The problem is everything runs perfectly, but there are some extra characters printed with output.
Here is the .h file:
class MyString
{
public:
MyString();
MyString(const char *message);
MyString(const MyString &source);
~MyString();
const void Print() const;
const int Length() const;
MyString& operator()(const int index, const char b);
char& operator()(const int i);
MyString& operator=(const MyString& rhs);
bool operator==(const MyString& other) const;
bool operator!=(const MyString& other) const;
const MyString operator+(const MyString& rhs) const;
MyString& operator+=(const MyString& rhs);
friend ostream& operator<<(ostream& output, const MyString& rhs);
const int Find(const MyString& other);
MyString Substring(int start, int length);
private:
char *String;
int Size;
};
istream& operator>>(istream& input, MyString& rhs);
The .cpp file:
MyString::MyString()
{
char temp[] = "Hello World";
int counter(0);
while(temp[counter] != '\0')
{
counter++;
}
Size = counter;
String = new char [Size];
for(int i=0; i < Size; i++)
String[i] = temp[i];
}
//alternate constructor that allows for setting of the inital value of the string
MyString::MyString(const char *message)
{
int counter(0);
while(message[counter] != '\0')
{
counter++;
}
Size = counter;
String = new char [Size];
for(int i=0; i < Size; i++)
String[i] = message[i];
}
//copy constructor
MyString::MyString(const MyString &source)
{
int counter(0);
while(source.String[counter] != '\0')
{
counter++;
}
Size = counter+1;
String = new char[Size];
for(int i = 0; i <= Size; i++)
String[i] = source.String[i];
}
//Deconstructor
MyString::~MyString()
{
delete [] String;
}
//Length() method that reports the length of the string
const int MyString::Length() const
{
int counter(0);
while(String[counter] != '\0')
{
counter ++;
}
return (counter);
}
/*Parenthesis operator should be overloaded to replace the Set and Get functions of your previous assignment. Note that both instances should issue exit(1) upon violation of the string array bounaries.
*/
MyString& MyString::operator()(const int index, const char b)
{
if(String[index] == '\0')
{
exit(1);
}
else
{
String[index] = b;
}
}
char& MyString::operator()(const int i)
{
if(String[i] == '\0')
{
exit(1);
}
else
{
return String[i];
}
}
/*Assignment operator (=) which will copy the source string into the destination string. Note that size of the destination needs to be adjusted to be the same as the source.
*/
MyString& MyString::operator=(const MyString& rhs)
{
if(this != &rhs)
{
delete [] String;
String = new char[rhs.Size];
Size = rhs.Size;
for(int i = 0; i < rhs.Size+1 ; i++)
{
String[i] = rhs.String[i];
}
}
return *this;
}
/*Logical comparison operator (==) that returns true iff the two strings are identical in size and contents.
*/
bool MyString::operator==(const MyString& other)const
{
if(other.Size == this->Size) {
for(int i = 0; i < this->Size+1; i++)
{
if(&other == this)
return true;
}
}
else
return false;
}
//Negated logical comparison operator (!=) that returns boolean negation of 2
bool MyString::operator!=(const MyString& other) const
{
return !(*this == other);
}
//Addition operator (+) that concatenates two strings
const MyString MyString::operator+(const MyString& rhs) const
{
char* tmp = new char[Size + rhs.Size +1];
for(int i = 0; i < Size; i++)
{
tmp[i] = String[i];
}
for(int i = 0; i < rhs.Size+1; i++) {
tmp[i+Size] = rhs.String[i];
}
MyString result;
delete [] result.String;
result.String = tmp;
result.Size = Size+rhs.Size;
return result;
}
/*Addition/Assigment operator (+=) used in the following fashion: String1 += String2 to operate as String1 = String1 + String2
*/
MyString& MyString::operator+=(const MyString& rhs)
{
char* tmp = new char[Size + rhs.Size + 1];
for(int i = 0; i < Size; i++) {
tmp[i] = String[i];
}
for(int i = 0; i < rhs.Size+1; i++)
{
tmp[i+Size] = rhs.String[i];
}
delete [] String;
String = tmp;
Size += rhs.Size;
return *this;
}
istream& operator>>(istream& input, MyString& rhs)
{
char* t;
int size(256);
t = new char[size];
input.getline(t,size);
rhs = MyString(t);
delete [] t;
return input;
}
ostream& operator<<(ostream& output, const MyString& rhs)
{
if(rhs.String != '\0')
{
output << rhs.String;
}
else
{
output<<"No String to output\n";
}
return output;
}
/*MyString::Find that finds a string in a larger string and returns the starting location of the substring. Note that your string location starts from 0 and ends at length -1. If the string is not found, a value of -1 will be returned
*/
const int MyString::Find(const MyString& other)
{
int nfound = -1;
if(other.Size > Size)
{
return nfound;
}
int i = 0, j = 0;
for(i = 0; i < Size; i++) {
for(j = 0; j < other.Size; j++) {
if( ((i+j) >= Size) || (String[i+j] != other.String[j]) )
{
break;
}
}
if(j == other.Size)
{
return i;
}
}
return nfound;
}
/*MyString::Substring(start, length). This method returns a substring of the original string that contains the same characters as the original string starting at location start and is as long as length.
*/
MyString MyString::Substring(int start, int length)
{
char* leo = new char[length+1];
for(int i = start; i < start + length+1; ++i)
{
leo[i-start] = String[i];
}
MyString sub;
delete [] sub.String; sub.String = leo; sub.Size = Size;
return sub;
}
//Print() method that prints the string
const void MyString::Print() const
{
for(int i=0; i < Size; i++)
{
cout<<String[i];
}
cout<<endl;
}
The main.cpp file:
int main (int argc, char **argv)
{
MyString String1;
const MyString ConstString("Target string"); //Test of alternate constructor
MyString SearchString; //Test of default constructor that should set "Hello World".
MyString TargetString (String1); //Test of copy constructor
cout << "Please enter two strings. ";
cout << "Each string needs to be shorter than 256 characters or terminated by /\n." << endl;
cout << "The first string will be searched to see whether it contains exactly the second string. " << endl;
cin >> SearchString >> TargetString; // Test of cascaded string-extraction operator
if(SearchString.Find(TargetString) == -1) {
cout << TargetString << " is not in " << SearchString << endl;
}
else {
cout << TargetString << " is in " << SearchString << endl;
cout << "Details of the hit: " << endl;
cout << "Starting position of the hit: " << SearchString.Find(TargetString) << endl;
cout << "The matching substring is: " << SearchString.Substring(SearchString.Find(TargetString), TargetString.Length()-1)<<"\n";
}
return 0;
}
Running the program you get this:
Please enter two strings. Each string needs to be shorter than 256 characters or terminated by /
.
The first string will be searched to see whether it contains exactly the second string.
firstly
real
realt World is not in firstly
Please Help!!
try adding a '\0' at the end of your strings in your MyString::MyString(const char *message) constructor
#Sam's answer is correct. I'm going to add on to it to help you learn what's happening.
C and C++ strings are really character arrays that follow a convention that the string is terminated with \0, sometimes called NUL (not null), which is a character where all bits are 0.
Your code gets the first part right in that it creates an array of characters. However, you do not apply the convention that the string must be NUL terminated.
You then pass a string that does not follow the NUL termination convention to cout, which does follow that convention. In other words, it runs through the string, printing each character to stdout, until it happens across the character \0 in memory. It's actually fairly lucky that it terminates. If there were not a \0 in the character array it is outputing, it would just keep on going until reaching a memory address that does not belong to your program and failing with a segmentation fault.
I faced a problem cannot convert parameter from 'System::String ^' to 'std::string'. How can i convert System::String^ into standard C++ string in Visual C++ environment ?
From this link at Microsoft:
void MarshalString ( String ^ s, string& os ) {
using namespace Runtime::InteropServices;
const char* chars =
(const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
os = chars;
Marshal::FreeHGlobal(IntPtr((void*)chars));
}
int main() {
string a = "test";
String ^ c = gcnew String("abcd");
cout << a << endl;
MarshalString(c, a);
cout << a << endl;
}
//*** convert String^ to standard C++ string
` String ^SyStr = "abc"; // system string
string StStr =""; // standard string
for each (char c in SyStr )
{
StStr .push_back( c);
} `
//**** End convert String^ to standard C++ string
//**** convert standard C++ string to String^
` String ^SyStr = ""; // system string
string StStr ="xyz"; // standard string
SyStr = gcnew String(StStr.c_str());`
//**** End convert standard C++ string to String^