Capture String from Array - c#

I'm trying to figure out how to get a string from an array starting at some given position. Say we have an array that's arbitrarily long and my string starts at location 1000. If I wanted to get a string from a file I would simply use something like getc or scanf or something. How do I carry out these same functions on an array instead of a file?
*oh, keep in mind that the array is of type int and is full of numerical representations of ASCII characters.

If you were dealing with a byte[] array then you could just do this:
string yourString = Encoding.ASCII.GetString(yourArray, startIndex, length);
Since your array is of type int[] then -- assuming that each element represents a single ASCII character -- you'll need to convert those ints to bytes first. If the array is "arbitrarily long" then you may not want to convert the whole thing to a byte[] array, in which case just convert the section that you need:
byte[] temp =
yourArray.Skip(startIndex).Take(length).Select(i => (byte)i).ToArray();
string yourString = Encoding.ASCII.GetString(temp);
If each element of your int[] array doesn't actually represent a single ASCII character then you'll need to give us more info about the precise format that it uses.

Assuming the string is null terminated (you don't specify how you know the end of the string) then a bit of Linq should do the trick:
var chars = ints.Skip(1000).TakeWhile(i => i != 0).Select(i => (char)i);
var str = new string(chars.ToArray());
The first like skips 1000 ints, takes them while they're not a null-terminator, and then converts them to a char as appropriate for ints representing ASCII codes. The second line simply makes them into a string.
If the string has no null terminator, and just ends when the array ends, then just remove the call to TakeWhile.

Here is an alternative (similar to the solution provided by LukeH) that might be faster (since it uses built in array methods rather than LINQ):
public static string GetString(int[] array, int startIndex, int length)
{
var subarray = new int[length];
Array.Copy(array, startIndex, subarray, 0, length);
return Encoding.ASCII.GetString(Array.ConvertAll(subarray, i => (byte)i));
}

Could you slice the elements from the array and call ASCIIEncoding.GetString() on it

LINQ can be pretty hand at times...
var ints = Enumerable.Range(0, 255).ToArray();
var start = 65;
var length = 26;
var value = new string(ints.Select(i => (char)i)
.Skip(start)
.Take(length)
.ToArray());
Console.WriteLine(value); //ABCDEFGHIJKLMNOPQRSTUVWXYZ

Here is my code just for reference. If you goto the "SYSCALL" section you will find an if statement pertaining to "open 4" this is where I'm stuck. Oh, by the way, I'm not using visual studio, I'm using a program called "Verilator" which allows me to interface Verilog Code with C++ code.
#include "VMIPS.h"
#include "VMIPS_MIPS.h"//required to explicitly access signals from submodules
#include <verilated.h>
#include <cstdio>
#include <cmath>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <vector>
using namespace std;
unsigned int main_time = 0;
static inline int hexCharValue(char ch)
{
if (ch>='0' && ch<='9')return ch-'0';
if (ch>='a' && ch<='f')return ch-'a'+10;
return 0;
}
int main(int argc, char **argv)
{
///////////////////////////////////////// Instruction Capture /////////////////////////////////////////////
ifstream inClientFile( "TEXT.txt",ios::in ); //stream object
//test if instruction file can be opened
if ( !inClientFile )
{
cerr << "File couldn't be opened" << endl;
return 1; //no point using exit inside main
}
//fill string array with all file values and determines length of program
vector<string> words;
words.reserve(274815);
string word;
while (inClientFile >> word)words.push_back(word); //helper function is unnecessary
cout << "Number of words:" << words.size() << endl;
const int wordCount=words.size();
vector<int> InstructionMemory;
vector<string> tempInstructionMemory;
tempInstructionMemory.reserve(wordCount);
//cut out undesired strings from vector
for(int i=0; i<wordCount; i++)
{
if (words[i].length()==8 && words[i].find("fs24")==string::npos) //f0 can exist at pos 1 in a valid hex string
{
tempInstructionMemory.push_back(words[i]);
}
}
//convert string hex to numerical decimal
InstructionMemory.resize(tempInstructionMemory.size());
for( int j=0; j<tempInstructionMemory.size(); j++ )
{
for( int y=0; y<8; y++)
{
InstructionMemory[j]+=hexCharValue(tempInstructionMemory[j][y])<<(4*(7-y));//4194608+4*
}
}
//printf("Amortized Instruction Vector Size:%d\n",InstructionMemory.size());
////////////////////////////////////// Data Capture ////////////////////////////////////////////////
ifstream inClientDataFile( "DATA.txt",ios::in ); //stream object
//test if instruction file can be opened
if ( !inClientDataFile )
{
cerr << "File couldn't be opened" << endl;
return 1; //no point using exit inside main
}
//fill string array with all file values and determines length of program
vector<string> datas;
datas.reserve(274815);
string data;
while (inClientDataFile >> data)datas.push_back(data); //helper function is unnecessary
cout << "Number of data packets:" << datas.size() << endl;
const int dataCount=datas.size();
vector<int> DataMemory;
vector<string> tempDataMemory;
tempDataMemory.reserve(dataCount);
//cut out undesired strings from vector
for( int i=0; i<dataCount; i++)
{
if (datas[i].length()==8 && datas[i].find("fs24")==string::npos) //f0 can exist at pos 1 in a valid hex string
{
tempDataMemory.push_back(datas[i]);
}
}
//convert string hex to numerical decimal
DataMemory.resize(tempDataMemory.size());
for( int j=0; j<tempDataMemory.size(); j++ )
{
for( int y=0; y<8; y++)
{
DataMemory[j]+=hexCharValue(tempDataMemory[j][y])<<(4*(7-y));
}
}
//printf("Amortized Data Vector Size:%d\n",DataMemory.size());
/////////////////////////////////////////// MIPS I processor interface /////////////////////////////////////////////
Verilated::commandArgs(argc, argv);
VMIPS *top = new VMIPS;
top->CLK = 0;
vector<int> HS0,HS1,HS2;
vector<string> FDT_filename;
vector<int> FDT_state;//1 = open, 0 = closed
int FileDescriptorIndex = 3;//start of non-reserved indecies
FILE *f;
//first 3 positions reserved for stdin, stdout, and stderr
FDT_filename.push_back("stdin");
FDT_filename.push_back("stdout");
FDT_filename.push_back("stderr");
FDT_state.push_back(0);
FDT_state.push_back(0);
FDT_state.push_back(0);
//int FDT[100];
printf("IMAddr:%d IM:%d \n***************\n",top->Iaddr,InstructionMemory[(top->Iaddr)/4]);
while (!Verilated::gotFinish())
{
//clock generation
top->CLK=!(top->CLK);
//vector mapping
if ( ( top->Daddr >= 0 ) && ( top->Daddr <= 419604 ) )
{
if(top->MemRead)
top->Din = HS0[(top->Daddr)/4];
if(top->MemWrite)
HS0[(top->Daddr)/4] = top->Dout;
}
else if ( ( top->Daddr >= (419608+InstructionMemory.size()+4) ) && ( top->Daddr <= 268435452 ) )
{
if(top->MemRead)
top->Din = HS1[(top->Daddr-419608)/4];
if(top->MemWrite)
HS1[(top->Daddr-419608)/4] = top->Dout;
}
else if ( ( top->Daddr >= 268435456 ) && ( top->Daddr <= (268435456+DataMemory.size()) ) )
{
if(top->MemRead)
top->Din = DataMemory[(top->Daddr-2668435456)/4];
if(top->MemWrite)
DataMemory[(top->Daddr-2668435456)/4] = top->Dout;
}
else if ( top->Daddr >=(268435456+DataMemory.size()+4) )
{
if(top->MemRead)
top->Din = HS2[(top->Daddr-(268435456+DataMemory.size()+4))/4];
if(top->MemWrite)
HS2[(top->Daddr-(268435456+DataMemory.size()+4))/4] = top->Dout;
}
//instruction supply mapping
if ( top->Iaddr < 4194608 )
{
top->Iin = InstructionMemory[(top->Iaddr)/4];
}
else
{
top->Iin = InstructionMemory[(top->Iaddr-4194608)/4];
}
//instruction split
if(main_time%2)
printf("IMAddr:%d IM:%d \n***************\n",top->Iaddr,InstructionMemory[(top->Iaddr)/4]);//-4194608)/4]);
//evaluate instruction call and increment time counter
top->eval();
main_time++;
//exit loop
if(main_time>=2)
{
return 0;
}
top->Iin = 3690987776;
//SYSCALL
if ( top->Iin == 3690987584 )//exit 1
{
cout << "Exit" << endl;
return 0;
}
else if ( top->Iin == 3690987776 )//open 4
{
cout << endl << endl << "Open File" << endl << endl;
string filename;
filename = "DATA.txt";
//fill filename with characters from memory
//FDT_filename(top->a0) is the string start pointer
FDT_filename.push_back(filename);//add new filename to newest location
FDT_state.push_back(1);//add new open indicator to newest location
top->v0 = FileDescriptorIndex;//place file descriptor into register
FileDescriptorIndex++;//ready the next file descriptor
//printf("Filename:%d FileDescriptorIndex:%d",FDT_filename.at3(FileDescriptorIndex),FileDescriptorIndex);
}
else if ( top->Iin == 3690987648 )//read 2
{
cout << "Read" << endl;
int max_char_count = top->a2;
int char_CTR = 0;
//create file object and open filename
//read chars from file
//place in
//FILE *f = fopen(filename,"rb");
//scanf("%s %top->a2",&FDT_filename(top->a0) >> top->a1;
//top->v0 = char_CTR;
}
else if ( top->Iin == 3690987712 )//write 3
{
cout << "Write" << endl;
int max_char_count = top->a2;
int char_CTR = 0;
//f fopen(FDT_filename(top->a0));
}
else if ( top->Iin == 3690987840 )//close 5
{
cout << "Close File" << endl;
//FDT_state(top->v0)=0;
}
else if ( top->Iin == 3690987904 )//time 6
{
cout << "Time:" << main_time << endl;
top->a0 = main_time;
top->a1 = main_time;
}
}
}

Related

Store multiple chars in a long and recover them

The following code is used to compact multiple values in a long. The long is used as a key in a C++ unordered_map. It allows me to use the map with a number instead of a complex structure and ifs on each properties. The map searching to be as efficient as possible.
DWORD tmpNo = object->room->details->No;
unsigned char compactNo = tmpNo ;
unsigned __int16 smallX = object->x;
unsigned __int16 smallY = object->y;
unsigned __int64 longCode = 0;
longCode = (item->code[0] << 56) |
(item->code[1] << 48) |
(item->code[2] << 40) |
(compactNo << 32) |
(smallX << 24) |
(smallY << 8);
Am I using the | operator correctly here ?
To recover the values, I tryed :
unsigned char c0 = key >> 56;
unsigned char c1 = key >> 48;
unsigned char c2 = key >> 40;
etc, but it didn't work.
Is it because the original item->code chars are chars and not unsigned chars (the values are always positive though) ?
Also, in an ideal world, the long's values would be recovered in a .NET DLL. Is it possible to do so in C# ?
C# has a byte type for an 8-bit value, but otherwise the logic is similar.
Your | logic looks fine (except you should be shifting smallX by 16 and smallY by 0)
It would help if you gave a complete example.
But assuming that item->code[0] is a char or int (signed or unsigned), you need to convert it to a 64 bit type before shifting, otherwise you end up with undefined behaviour, and the wrong answer.
Something like
((unsigned __int64) item->code[0]) << 56
should work better.
I think that stdint.h is very useful to understand this kind of implementation (sized integers are very meaningful). So here's the code:
#include <stdio.h>
#include <stdint.h>
int8_t getValue8(int index, uint64_t container) {
return (uint8_t)((container >> (index * 8)) & 0XFF);
}
void setValue8(int index, uint64_t* container, uint8_t value) {
// get left part of container including the last byte (cleared by ~0xFF mask) to be used by value
int shift = index * 8;
uint64_t mask = (uint64_t) ~0xFF;
uint64_t left = (*container >> shift) & mask;
left = (left | value) << shift;
// right part of container (complement)
mask = ((uint64_t)1 << ++shift) - 1;
uint64_t right = *container & mask;
// update container
*container = left | right;
}
int main() {
uint64_t* container; // container: can contain 8 chars (64-bit sized container)
uint64_t containerValue = 0;
int n = 8; // n value must be <= 8 considering a 64-bit sized container
uint8_t chars[n]; // eight char values to be stored
// add/set values to container
container = &containerValue;
int i;
for (i = 0; i < n; ++i) {
chars[i] = (uint8_t)((i+1)*10);
setValue8(i, container, chars[i]);
printf("setValue8(%d, container, %d)\n", i, chars[i]);
}
// get values from container
for (i = 0; i < n; ++i) {
printf("getValue8(%d, container)=%d\n", i, getValue8(i, *container));
}
return 0;
}
The code use only bit masks and some bitwise operations, and so you can easily port it to C#. If you have any questions about it just ask. I hope I have been helpful.

Errors on hex characters and hash

I have a project that is almost near completion aside from a couple of stubborn but probably simple error Im receiving. I am by know means knowledgeable of C and me getting this project this far is a miracle. Im hoping someone can detect what it is I am missing in my code. Here is the view of the errors and below is the code.
private void button1_Click(object sender, EventArgs e)
{
Random rnd = new Random();
StringBuilder bin = new StringBuilder();
int buf = 0;
int bufLen = 0;
int left = 53;
for (int i = 106; i >= 1; i += -1)
{
buf <<= 1;
if (rnd.Next(i) < left)
{
buf += 1;
left -= 1;
}
bufLen += 1;
if (bufLen == 4)
{
bin.Append("0123456789ABCDEF"(buf));
bufLen = 0;
buf = 0;
}
}
string b = bin.ToString();
bin.Append("048c"(buf));
System.Security.Cryptography.SHA1Managed m = new System.Security.Cryptography.SHA1Managed();
byte[] hash = m.ComputeHash(Encoding.UTF8.GetBytes(b));
//replace first two bits in hash with bits from buf
hash(0) = Convert.ToByte(hash(0) & 0x3f | (buf * 64));
//append 24 bits from hash
b = b.Substring(0, 26) + BitConverter.ToString(hash, 0, 3).Replace("-", string.Empty);
}
}
}
x(y) means "call x with y as a parameter".
You have written "0123456789ABCDEF"(buf). "0123456789ABCDEF" isn't a function (or a functor) so you can't call it.
Perhaps you meant to index it, with "0123456789ABCDEF"[buf]? This returns the buf'th character from "0123456789ABCDEF", which is buf in hexadecimal as long as buf is between 0 and 15.
You can't concatenate a string literal with a string variable.
#include <iostream>
using std::cout;
void concatenate(const std::string& s)
{
cout << "In concatenate, string passed is: "
<< s
<< "\n";
}
int main(void)
{
std::string world = " World!\n";
concatenate("Hello"(world));
return 0;
}
Thomas#HastaLaVista ~/concatenation
# g++ -o main.exe main.cpp
main.cpp: In function `int main()':
**main.cpp:15: error: `"Hello"' cannot be used as a function**
Thomas#HastaLaVista ~/concatenation
# g++ --version
g++ (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
You will need a temporary string variable:
if (bufLen == 4)
{
std::string temp("01234567890ABCDEF");
temp += buf;
bin.Append(temp);
bufLen = 0;
buf = 0;
}

convert from BitArray to 16-bit unsigned integer in c#

BitArray bits=new BitArray(16); // size 16-bit
There is bitArray and I want to convert 16-bit from this array to unsigned integer in c# ,
I can not use copyto for convert, is there other method for convert from 16-bit to UInt16?
You can do it like this:
UInt16 res = 0;
for (int i = 0 ; i < 16 ; i++) {
if (bits[i]) {
res |= (UInt16)(1 << i);
}
}
This algorithm checks the 16 least significant bits one by one, and uses the bitwise OR operation to set the corresponding bit of the result.
You can loop through it and compose the value itself.
var bits = new BitArray(16);
bits[1] = true;
var value = 0;
for (int i = 0; i < bits.Length; i++)
{
if (lBits[i])
{
value |= (1 << i);
}
}
This should do the work
private uint BitArrayToUnSignedInt(BitArray bitArray)
{
ushort res = 0;
for(int i= bitArray.Length-1; i != 0;i--)
{
if (bitArray[i])
{
res = (ushort)(res + (ushort) Math.Pow(2, bitArray.Length- i -1));
}
}
return res;
}
You can check this another anwser already in stackoverflow of that question:
Convert bit array to uint or similar packed value

Access violation exception importing a c++ dll file into c#

Am trying to use functions from a dll file i built in c++ in c#; below is the c++ .h codes
#pragma once
#pragma unmanaged
#ifndef _DLL_H_
#define _DLL_H_
#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */
#include <list>
#include <string>
using namespace std;
extern "C"
{
string DLLIMPORT encrypt(string keeper);
string DLLIMPORT decrypt(string keeper);
}
#endif /* _DLL_H_ */
the c++ .cpp codes are below
#pragma managed
#include "cenH.h"
#include <windows.h>
#include <iostream>
using namespace std;
const char alphabets[] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n',
'o','p','q','r','s','t','u','v','w','x','y','z'};
string encrypt(string keeper)
{
string keep;
string m = keeper;
cout << keeper.length() << endl;
for(int count = 0; count < m.length(); count++)
{
for(int c = 0; c < 26; c++)
{
if(m[count] == alphabets[c])
{
int counter = c - 8;
if(counter < 0)
{
counter = counter + 26;
keep += alphabets[counter];
}
else
{
keep += alphabets[counter];
}
}
else if(m[count] == ' ')
{
keep+=".";
break;
}
}//end of second loop
//end first loop
cout << keep << endl;
return keep;
}
string decrypt(string keeper)
{
//cout << "\n" << endl;
string keep;
string m = keeper;
for(int count = 0; count < m.length(); count++)
{
for(int c = 0; c < 26; c++)
{
if(m[count] == alphabets[c])
{
int counter = c + 8;
if(counter >= 26)
{
counter = counter - 26;
keep += alphabets[counter];
}
else
{
keep += alphabets[counter];
}
}else if(m[count] == '.')
{
keep+=" ";
break;
}
}//end of third loop
}//end second loop
//cout << keep << endl;
return keep;
}
BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ ,
DWORD reason /* Reason this function is being called. */ ,
LPVOID reserved /* Not used. */ )
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
/* Returns TRUE on success, FALSE on failure */
return TRUE;
}
i compile this codes and they dont give errors, i even test run them in a c++ console app by calling the dll file and it works fine but when i call this dll file into my c# programs it give me the AccessViolationException Attempted to read or write protected memory. This is often an indication that other memory is corrupt. The dll is complied in the MinGW GCC 4.6.2 32-bit and my c# runs on x86(32-bit).can someone please point to me what i have done wrong.
This is how i imported the dll inside my c# code
[DllImport("cen.dll",CallingConvention = CallingConvention.StdCall)]
internal static extern string decrypt(String keeper);
string line = decrypt("savethemonkeys");

Convert C# to C++ Bitwise shift

I have the following code in c# which reverses a string:
char[] charArray = s.ToCharArray();
int len = s.Length - 1;
for (int i = 0; i < len; i++, len--)
{
charArray[i] ^= charArray[len];
charArray[len] ^= charArray[i];
charArray[i] ^= charArray[len];
}
return new string(charArray);
I am trying to convert it to C++ as an intellectual exercise more than anything. Here is what I have so far:
void main(void)
{
char* str = "testing";
char* result;
int len;
len = strlen(str);
if (len <= 12)
{
result = new char[strlen(str)];
for (int i = 0; i < len; i++, len--)
{
result[i] ^= str[len];
result[len] ^= str[i];
result[i] ^= str[len];
}
}
else{
std::reverse(str, &str[strlen(str)]);
}
cout << endl << result << endl;
// cleanup
str = NULL;
result = NULL;
}
In .Net if the string is <= 12 (I think it's twelve) xor is faster than array reverse. Source - Sam Saffron I am basically trying to see if it still holds up in C++.
The string comes out in a weird format (════╣¥¿ë²²² to be precise).
Any ideas?
Note: I know the else statement doesn't work, I'll figure that bit out after ;)
Note 2: I am probably doing this completely wrong, so feel free to point absolutely anything out
Update
Thanks to everyone that has participated. I haven't played with c++ in a fair few years (and it shows) and thought it would be quiet easy to convert but obviously not. Think it's best I abandon this idea. Thanks again
A few things:
result = new char[strlen(str)];
Should be
result = new char[len + 1];
len because you've already calculated the length of str, and + 1 to make room for the NUL terminator.
Secondly, you need to copy the string into result before operating on it, because otherwise your array is full of garbage otherwise:
strcpy(result, str);
Thirdly,
std::reverse(str, &str[strlen(str)]);
Is wrong for two reasons: one, because you can't modify string literals, and two, because you should be using result:
std::reverse(result, result + len);
But if you do that, you also need to copy str into result first.
And lastly, setting a pointer to NULL does not deallocate the memory it points to. You have to
delete[] result; // delete[] because new[]
Note that for this to work even when the else is taken (and therefore result is not made to point to allocated memory), you need to do
char* result = NULL; // delete[] is defined as a nop on NULL pointers
All the above applies if you're sure you want to use C-strings. Once you get the hang of pointers, you can graduate to std::string:
std::string str("testing");
std::reverse(std::begin(str), std::end(str)); // or if you don't want to do it in-place,
// std::string result(str.rbegin(), str.rend());
xor swap is for swapping. If you're copying into a result array then that's assigning, not swapping. Also, you must only iterate half-way through the array, otherwise you swap it twice.
Here is a translation of the C# code:
#include <iostream>
#include <algorithm>
int main(void)
{
char str[] = "testing"; // arrays have automatic storage - no need to new/delete
const size_t str_len = sizeof(str)-1; // sizeof(str) returns size of the array
if (str_len <= 12) // because str_len is a constant expression, the other branch will be compiled-out
{
// this should probably use iterators (pointers) but oh well
for (size_t i = 0, len = str_len-1; i < str_len/2; i++, len--)
{
str[i] ^= str[len];
str[len] ^= str[i];
str[i] ^= str[len];
}
}
else{
std::reverse(str, str + str_len); // str decays to a pointer
}
std::cout << str << '\n'; // don't use endl if you don't need to flush
}
This is pretty bad code. Just use std::string and std::reverse. It is faster than xor and only 2 lines long.
std::string str = "testing"
std::reverse(str.begin(), str.end());
A better way of doing it, more C++, less C
std::string mystring = "testing";
std::string reversed;
for(std::string::iterator str_it = mystring.rbegin(); str_it != mystring.rend(); ++str_it)
{
reversed += *str_it;
}
std::cout << reversed << std::endl;

Categories