tags:

views:

148

answers:

6

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.

+9  A: 

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.

LukeH
This only works if the array is of type byte[]. The asker specified that the array is of type int[].
Joseph Sturtevant
@Joseph: this should work, as the select receives an `IEnumerable<int>` and returns `IEnumerable<byte>`, which is then turned into a `byte[]`.
John Saunders
@John Saunders: My comment was made prior to LukeH editing his answer. His second solution does work on int[] as you pointed out.
Joseph Sturtevant
A: 

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

Greg B
+4  A: 

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.

Greg Beech
A: 

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
Matthew Whited
+1  A: 

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));
}
Joseph Sturtevant
A: 

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;
        }
    }
}
Dan Snyder