Click here to Skip to main content
15,897,891 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
RESOLVED:
Big thanks to Richard MacCutchan and everyone else who contributed to the thread!

So, the problem was that I wanted to take values from a CSV file that is formatted something like this:

Fname1,Minitial1,LName1,Com1,(Desc1)
Fname2,Minitial2,LName2,Com2,(Desc2)
Fname3,Minitial3,LName3,Com3,(Desc3)

What I wanted to accomplish was take each token delimited by a comma and assign it to a temporary value. The reason why I wanted to do this was because I wanted to rearrange the input values in to a specific order as well as be able to output the same token multiple times. This is an example of the desired output:

LName1 Com1 Fname1 Minitial1 (Desc1) Fname1.LName1
LName2 Com2 Fname2 Minitial2 (Desc2) Fname2.LName2
LName3 Com3 Fname3 Minitial3 (Desc3) Fname3.LName3

As you can see, temporary tokens [0] - 4] are needed to be able to accomplish this. For my specific purpose, the tokens needed to be rearranged as:

C++
outfile <<  szToken[2] << " ";
outfile <<  szToken[3] << " ";
outfile <<  szToken[0] << " ";
outfile <<  szToken[1] << " ";
outfile <<  szToken[4] << " ";
outfile <<  szToken[0] << ".";
outfile <<  szToken[2] << endl;



Here is the entire code:

C++
// reading a text file
#include iostream
#include fstream
#include string

using namespace std;

int main () {
  string line;
  ifstream infile ("infile.csv");
  ofstream outfile ("outfile.txt");
if (infile.is_open())
    {
        while (getline(infile, line))
        {
            // copy the string to a character array
            char* pszLine = new char[line.length() + 1];
            strcpy(pszLine, line.c_str());
            char* szToken[5];
 
            // split the line into tokens
            szToken[0] = strtok(pszLine, ",");
            for (int i = 1; i < 5; ++i)
            {
                szToken[i] = strtok(NULL, ",");
            }
 
            // write the tokens out in a different order
            outfile <<  szToken[2] << " ";
            outfile <<  szToken[3] << " ";
            outfile <<  szToken[0] << " ";
            outfile <<  szToken[1] << " ";
            outfile <<  szToken[4] << " ";
            outfile <<  szToken[0] << ".";
            outfile <<  szToken[2] << endl;
 
            // tidy up
            delete []pszLine;
        }
}

}


This will actually end up being used to produce VB scripts.


Thanks again to everyone, and I hope the next time I post here, it's helping someone like you guys helped me!
Posted
Updated 8-Aug-11 13:04pm
v17
Comments
Sergey Alexandrovich Kryukov 7-Aug-11 20:00pm    
Is there a problem.
--SA
JeremyMH 7-Aug-11 20:17pm    
Yeah there is. I just don't know how to properly state that it needs to take the line, separate it in to 5 different values (so I can rearrange them), and then do the same with the next line and so on.

I posted a couple of the codes that I have looked at and apparently those should work, but whenever I try to integrate them in to my cpp, I turn up with errors.

Thanks for the post
JeremyMH 7-Aug-11 21:47pm    
All I really need to do is keep separating the string until it reaches the end of the line. In my case, it's going to be 5 separate values.

You probably need to split your string into tokens. Once you have read it in you can copy the string data to a char array and use one of the tokenizer[^] functions to break it up into its constituent sub-strings.

[/edit]Added code snippet.[/edit]
C++
PTSTR szToken[5];
szToken[0] = strtok(szText, szSeparators);
for (int i = 1; i < 5; ++i)
{
    szToken[i] = strtok(NULL, szSeparators);
}

szToken[0] to 5 now contain your tokens
 
Share this answer
 
v3
Comments
JeremyMH 8-Aug-11 12:21pm    
Right. I do need to split my string up in to tokens, The problem that I am running in to is being able to temporarily assign each section that gets broken up a str1 - str5 value so I can rearrange it. Link This link has a code which breaks the initial string down well, but I can't figure out how to assign the subsequent broken down pieces to temporary strings.
Richard MacCutchan 8-Aug-11 13:09pm    
See my update above.
JeremyMH 8-Aug-11 13:23pm    
Going to go with that and see if I can make it work. Going to be interesting, haha.

Thanks for your help thus far.

JeremyMH 8-Aug-11 15:28pm    
Restated my problem in the top bit. Does your solution still apply?
Richard MacCutchan 8-Aug-11 15:37pm    
Yes, using strtok() for this sort of problem is a commonplace and makes it easy to achieve what you want. The issue is merely one of breaking your initial input into its constituent parts and putting those parts back together in a different order. Try printing a sample line on paper and then use scissors and sticky tape to see how easy it is.
OK, building on your code:
C++
if (myfile.is_open())
{
    while (getline(myfile, line))
    {
        // copy the string to a character array
        char* pszLine = new char[line.length() + 1];
        strcpy(pszLine, line.c_str());
        char* szToken[5];

        // split the line into tokens
        szToken[0] = strtok(pszLine, ",");
        for (int i = 1; i < 5; ++i)
        {
            szToken[i] = strtok(NULL, ",");
        }

        // write the tokens out in a different order
        cout << szToken[0] << ".";
        cout << szToken[3] << ".";
        cout << szToken[4] << ".";
        cout << szToken[2] << ".";
        cout << szToken[1] << endl;

        // tidy up
        delete []pszLine;
    }
}

I'll leave you to write the output strings to a file rather than cout.
 
Share this answer
 
Comments
JeremyMH 8-Aug-11 18:06pm    
Time to try and figure it out! Haha, thanks again. I appreciate the continued patience.
Espen Harlinn 8-Aug-11 18:09pm    
Nice reply Richard, my 5
JeremyMH 8-Aug-11 19:08pm    
Exactly, I repeat "exactly," what I needed accmoplished. The program works beautifully! Cleared out all the garbage in the question and replaced it with something that was a little more congruent, in my opinion. Thanks again!
Richard MacCutchan 9-Aug-11 3:09am    
Happy to help.
If you could write you question more clear, things could be much easier. Here is a good sample "C++ Parse Split Delimited String" that you can adapt to your needs.
 
Share this answer
 
Comments
JeremyMH 8-Aug-11 11:32am    
What about my question is unclear? I want to take a line of input from one file, break it down by delimiter and rearrange the inputs and write it to another file.
Sergey Chepurin 8-Aug-11 11:46am    
And now compare this with two pages of text with code in your original question. Now you can "break it down by delimiter"?
JeremyMH 8-Aug-11 12:12pm    
And since I haven't said it yet, thanks for your help thus far.
JeremyMH 8-Aug-11 15:29pm    
Just restated my problem at the top of the topic.
JeremyMH 8-Aug-11 12:12pm    
I'm looking at your link and the fact that it is breaking it down by delimiter and setting the index at the last delimiter works perfect for what I am trying to do, but now I just have to figure out a way to put a statement in there that stores for val1 - val5 as it's breaking it down.
A really simple example:
C++
TCHAR* splitrow(const TCHAR* filebuff,const unsigned int filesize,unsigned int& seek,TCHAR** array,const unsigned int count)
{
  typedef struct
  {
    typedef enum{ UNK, COL, ROW, } WHAT;
    static WHAT token(const TCHAR c)
    {
      switch(c)
      {
        case '\n'return ROW;
        case ',' : return COL;
      }
      return UNK;
    }
  } is;
  
  unsigned int  i,n,c;
  TCHAR*        holdbuff;

  // calculate buffer size
  for(n=seek;(n<filesize)&&(is::ROW!=is::token(filebuff[n]));n++);
  
  // have we a valid array
  if(!count){ seek = n<filesize?n:1+n; return 0; }

  holdbuff = (TCHAR*)malloc(sizeof(TCHAR)*(1+n-seek));

  // init the result array
  for(i=0;i<count;i++) array[i] = __TEXT("");

  // transfer to holdbuff
  for(c=0,i=0,array[c++]=holdbuff;i<n;i++,seek++)
  {
    switch(is::token(filebuff[seek]))
    {
      case is::ROW:
        holdbuff[i] = 0;
      break;
      case is::COL:
        holdbuff[i] = 0;
        if(c<count) array[c++] = holdbuff+1+i;
      break;
      default:
        holdbuff[i] = filebuff[seek];
      break;
    }
  }

  if(seek<filesize) ++seek;
  return holdbuff;
}

void dojob(const TCHAR* filebuff,const unsigned int filesize)
{
  enum{ FName,MInitial,LName,Description,Comment,Endrow };

  unsigned int  seek;
  TCHAR*        array[Endrow];
  TCHAR*        hold;
  for(seek=0;seek<filesize;)
  {
    hold = splitrow(filebuff,filesize,seek,array,sizeof(array)/sizeof(array[0]));
    // write your results
    /* i.e:
    write( array[LName],array[Description],array[MInitial] );
    */
    free(hold);
  }
}

Good luck.
 
Share this answer
 
v6
Comments
JeremyMH 8-Aug-11 19:23pm    
Thanks for your post!
Take a look at the Boost Tokenizer Class[^]

int main(){
   using namespace std;
   using namespace boost;
   string s = "This is,  a test";
   tokenizer<> tok(s);
   for(tokenizer<>::iterator beg=tok.begin(); beg!=tok.end();++beg){
       cout << *beg << "\n";
   }
}

Generates the following output:
This
is
a
test


Simpler, and safer, than the old c functions.

Boost can be downloaded here: Download[^]

Best regards
Espen Harlinn
 
Share this answer
 
Comments
JeremyMH 8-Aug-11 19:23pm    
Thanks for your post!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900