Click to See Complete Forum and Search --> : [RESOLVED] Parsing text file data by certain characters or newline
_Cobra
January 5th, 2007, 07:57 PM
So, I finally figured out (with your help) how to save an online text file onto your computer and load it into a project. Now, the questions is how can I parse the data within?
Starting out simple, I want to do the following:
-Split the text file by line into an array of ints
-get the number of lines in the file
In another project I need to parse data in a more complex way. The stuff in the text file is in the following format:
1%2003A%A%00000001%00320000%1%7,920,000
5%2001%B%03200001%03520000%2%10,587,000
Is there a way to separate each 'column' - separated by a '%' into a like array? Example: 1 & 5 are in an stringA array, 2003A & 2001 are in a stringB array, etc.?
Thanks for the help,
-David
Zaccheus
January 6th, 2007, 04:59 AM
Is there a way to separate each 'column' - separated by a '%' into a like array? Example: 1 & 5 are in an stringA array, 2003A & 2001 are in a stringB array, etc.?
Thanks for the help,
-David
In .net you can use System::String's Split (http://msdn2.microsoft.com/en-us/library/system.string.split.aspx) method.
_Cobra
January 6th, 2007, 11:42 AM
Before I can use the split method, I need to correctly read in data from a text file to an array.
String^ length;
array<String^>^serialString;
array<int>^serials;
int count=0;
while (length = sr->ReadLine())//get length of textfile...there's an easier way, right?
count++;
for(int x=0;x<=count;x++)
{
serialString[x] = sr->ReadLine();//runtime error on this line...
serials[x] = Convert::ToInt32(serialString[x]);
MessageBox::Show(serialString[x] + "\r\n" + serials[x], "alert", MessageBoxButtons::OK);
}
It compiles fine, but when I run it I get a NullReferenceException: Object reference not set to an instance of an object. Is this because I'm reading to an array?
Thanks for the continued help!
Zaccheus
January 6th, 2007, 01:09 PM
Can you not read the whole file into a single string and then use Split to break the string into its individual lines first?
_Cobra
January 6th, 2007, 01:56 PM
I'm sure I could if I knew how...
I checked out the page you directed me to, but don't understand all of what I'm reading. I understand how to split a string now, but I don't know how to read the text from the entire file as one string.
String^ words = "1%2003%500%123\n85%654";
array<Char>^chars = {'%','\n'};
array<String^>^split = words->Split(chars);
IEnumerator^ myEnum = split->GetEnumerator();
while(myEnum->MoveNext())
{
String^ s = safe_cast<String^>(myEnum->Current);
if (!s->Trim()->Equals( "" ))
MessageBox::Show(s, "alert", MessageBoxButtons::OK);
Also, what does the 'if (!s->Trim()->Equals( "" ))' line do?
Zaccheus
January 6th, 2007, 02:43 PM
Hmm .. on second thought StreamReader seems like a good idea.
How about:
try
{
StreamReader^ sr = gcnew StreamReader( "TestFile.txt" );
try
{
String^ line;
array<wchar_t>^ percent = gcnew array<wchar_t>{'%'};
while ( line = sr->ReadLine() )
{
array<String^>^ columns = line->Split(percent);
for each(String^ str in columns)
{
// use str here
}
}
}
finally
{
delete sr;
sr = nullptr;
}
}
catch ( Exception^ e )
{
// Let the user know what went wrong.
}
The s->Trim()->Equals( "" ) in your code removes all leading and trailing white-space characters from s and then checks whether that produces an empty string.
_Cobra
January 12th, 2007, 09:15 PM
Thanks for the help thus far. Unfortunatly, one question answered exponentially creates more questions.
Is it possible to write each line to an array?
Here is what I have so far...I'll try to explain as best I can what I'm trying to do with it.
String^ line;
int y = 0;
while (line = sr->ReadLine())
{
y++;//get number of lines in file
}
//create 3 arrays: numberStr (string), number (int), name (string)
int*x = new int[y];
//how do I make the string arrays?
for(int x=1;x<=y;x++)
{
//see below...
}
Textfile:
10%jimmy%
54%timmy%
25%bobby%
63%jonny%
I'm trying to split each line into two arrays (numberStr and name) - numberStr will later be parsed to number. The two variables are split by the %. That way, number[x] && name[x] correspond as long as x is the same in both arrays.
I have a feeling that I need to manipulate the code you've already presented me, but I just don't know how.
Teaching myself C++ after one year of a Java class is harder than I thought...
Zaccheus
January 13th, 2007, 04:48 AM
I don't quite understand what you are trying to do, but given your input data, the code I posted should to the following:
The first time it goes through the while loop, it should produce an array containing these strings:
"1" "2003A" "A" "00000001" "00320000" "1" "7,920,000"
The second time it goes through the while loop, it should produce an array containing these strings:
"5" "2001" "B" "03200001" "03520000" "2" "10,587,000"
You can iterate through such arrays using 'for each'.
_Cobra
January 13th, 2007, 09:06 AM
You are right. the first time it goes through the loop, the array has "1" "2003A" "A" "00000001" "00320000" "1" "7,920,000" but when it goes through the loop the next time, that data is rewritten to "5" "2001" "B" "03200001" "03520000" "2" "10,587,000."
Instead of me trying to solve my problem at once, I guess I should start with the basics...arrays.
int*x = new int[5];
- I can access any of the ints in the array with an index like so: x[3].
How do I do that with strings?
String^testArray = gcnew String[5]; doesn't work.
I think if you help me with string arrays (with indices), I'll be more likely to solve this problem I have.
Thanks for the continued support, though.
Zaccheus
January 13th, 2007, 11:23 AM
You can create arrays of strings like this:
array<String^>^ someStrings = gcnew array<String^>(5);
You could add each string array to a linked-list for safe keeping, and later iterate through the linked list:
typedef System::Collections::Generic::LinkedList< array<String^>^ > StringArrayLinkedList;
StringArrayLinkedList^ fileContents = gcnew StringArrayLinkedList();
// Inside the while loop:
fileContents->AddLast(columns);
// Later on:
for each(array<String^>^ theColumns in fileContents)
{
for(int index = 0; index < theColumns->Length; ++index)
{
// theColumns[index];
}
}
Have a look at the linked-list class:
http://msdn2.microsoft.com/en-us/library/h64606bk.aspx
_Cobra
January 13th, 2007, 09:57 PM
This should be my last question on the topic if all goes to plan.
First of all, you should know that I went a completely different route in solving the original task.
I have the entire text file in an array of strings (one line per index). Lets call that array linesArray. Is there a way to split linesArray to get the first part of the split into an array of strings called numberArray and the second part of the split into an array of strings called lettersArray?
Sample Textfile:
20%abc
58%def
45%ghi
12%jkl
75%mnl
There is no direct way of doing this, is there? Right now, I'm trying to think of some sort of algorithm with temporary arrays and strings to accomplish this.
Edit:
When it comes to programming, the best thing you can do is take a break away from the computer.
I havent tested it yet, but I think this will work:
String^tempStr;
String^tempLetterStr;
String^tempNumStr;
array<String^>^tempArray = gcnew<String^>(someLength);
array<String^>^numberArray = gcnew<String^>(someLength);
array<String^>^lettersArray = gcnew<String^>(someLength);
for(int x=0; x<=someLength; x++){
tempStr = lineArray[x];
tempArray = tempStr->Split(percent);
tempNumStr = tempArray[0];
tempLetterStr = tempArray[1];
numberArray[x] = tempNumStr;
lettersArray[x] = tempLetterStr;
}
Zaccheus
January 14th, 2007, 05:26 AM
I havent tested it yet, but I think this will work:
String^tempStr;
String^tempLetterStr;
String^tempNumStr;
array<String^>^tempArray = gcnew<String^>(someLength);
array<String^>^numberArray = gcnew<String^>(someLength);
array<String^>^lettersArray = gcnew<String^>(someLength);
for(int x=0; x<=someLength; x++){
tempStr = lineArray[x];
tempArray = tempStr->Split(percent);
tempNumStr = tempArray[0];
tempLetterStr = tempArray[1];
numberArray[x] = tempNumStr;
lettersArray[x] = tempLetterStr;
}
Yes, that looks good.
:thumb:
codeguru.com
Copyright WebMediaBrands Inc., All Rights Reserved.