How do I use malloc and memcpy to put characters in a 2D array?

I'm writing a program to split text from a text file into tokens. I am trying to put characters read from the file into a 2D char array called **token. Each "row" in **token is supposed to hold a line of text, and each element in each row is supposed to hold a token from the line.  I've written:

word = (char*) malloc (tokenLength + 1);
memcpy(*token[0], word, tokenLength + 1);

The memcpy statement prompts an error that reads "invalid conversion from 'char' to 'void*' initializing argument 1 of 'void * memcpy(void*, const void*, size_t)' ". How do I use memcpy and avoid this error?
#include <iostream>
#include <fstream>
#include <string.h> 
#include "system_utilities.h"
#include "definitions.h"
 
using namespace std;
 
ifstream file; // create input stream object
 
 
char linetext[256]; // array of characters to hold 255 characters + terminating null char
int length; // variable to hold length of current line of input (num chars)
int pos = 0; // variable to hold position of last character of current input line read by getNextToken
char *word;
 
int errorcode;
 
void printError(int errorcode)
{
   switch ( errorcode )
   {
      case END_OF_FILE:
         cout << "Error: End of file has been reached." << endl;
         break;
      case FILE_NOT_OPENED:
         cout << "Error: File could not be opened." << endl;
         break;
      case TOKEN_NOT_FOUND:
         cout << "Error: Token not found." << endl;
         break;
      default:
         cout << "There is an error." << endl;
   }
}
 
int openInputFile (char fname[])
{
   file.open(fname, ios::in); // what is ios::in for?
   if (file.good())
   {
      cout << fname << " was read successfully" << endl;
      return 0; 
   }
   else
   {
      cout << "file not read successfully" << endl;
      return FILE_NOT_OPENED; 
   }
}
 
int getNextToken(char **token) 
{
   
   int tokenFound = 0; // whether or not a token has been found
   int tokenLength = 0; // length of token
  
   while(tokenFound == 0) // when no token has been found
   {
      if(pos == 0) // if you're at the beginning of a line
      {
         int j;
         for (j = 0; j <256; j++) // set all character array values to NULL
         {
            linetext[j] = '\0';
         }
         file.getline(linetext, 256); // read in a line of text from the file
         length = strlen(linetext); // get the length of the line
      }
      
      // Recognizing single characters and symbols (not quotes)
      int i;
      for(i = pos; i < length && (tokenFound == 0); i++) // loop through the whole line
      {
         if(((linetext[i] != ' ') && (linetext[i] != '\0'))) // if the character is not a space or NULL, or is a symbol
         {
            word = (char*) malloc (tokenLength + 1);
            memcpy(token[0], word, tokenLength + 1);
            cout << "word: " << word << endl;
            tokenLength = i - pos; // length of token
            pos = i + tokenLength; // new pos = next character after i (1 = length of these tokens; not i++ for all tokens)
            tokenFound = 1;
         }
      }
  
      if(pos == length) // if you've reached the end of the line
      {
         pos = 0; // reset pos to 0
         if(file.eof()) // if you've reached the end of the file
         {
            return END_OF_FILE;
         }
      }
   }
   return 0;
}
  
int symbol(char c)
{
   if ((c == '>') || (c == '<') || (c == '/') || (c == '='))
      {
      return 1;
      }
   else
      {
      return 0;
      }
}

Open in new window

vwpsAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

SreejithGCommented:
Please attach .h files too
0
vwpsAuthor Commented:
Sorry about that. Here is system_utilities.h:
int openInputFile(char fname[]); // input file name string, open file and assign to file-level ifstream variable
int getNextToken( char **token ); // finds next token in input file, allocates new space, assigns token to point to new space, copies characters
void printError(int errorcode); // prints appropriate error message
int symbol(char c);

Open in new window

0
vwpsAuthor Commented:
And definitions.h:
#define END_OF_FILE 201 
#define FILE_NOT_OPENED 202 
#define TOKEN_NOT_FOUND 301 
#define MAX_LINE_LENGTH 255 

Open in new window

0
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

SreejithGCommented:
please provide your main/calling functio function also
0
vwpsAuthor Commented:
main.cpp:
#include <iostream>
#include "system_utilities.h"
#include "definitions.h"
 
using namespace std;
 
int stop;
char **token1;
 
int main() 
{
   openInputFile("symbols.txt");
   while(getNextToken(token1) != END_OF_FILE);
   cout<<"Done";
   cin >> stop;
   return 0;
}

Open in new window

0
sweetfa2Commented:
memcpy( (void*) token[0], word, tokenLength + 1);
0
vwpsAuthor Commented:
Sweetfa2 - thanks for your response! Unfortunately, when I ran that code, it prompted a generic Windows XP error of "Project4-1.exe has encountered a problem and needs to close. We are sorry for the inconvenience." Any thoughts?
0
Infinity08Commented:
You need to allocate memory for 'token' before trying to copy data into it.


A few remarks :

>> into a 2D char array called **token.

The 2D array is called 'token' - ** is part of the type, ie. char** or a pointer-to-pointer-to-char.


>> Each "row" in **token is supposed to hold a line of text, and each element in each row is supposed to hold a token from the line.

Currently, the way you defined 'token', it only supports an array of strings (char*). So, that's only one line of text. To support multiple lines of text, you'll need a char*** or pointer-to-pointer-to-pointer-to-char.

Do not forget to properly allocate memory.


Btw, why don't you use the C++ way of allocating memory ? You are using C++, aren't you ?

        http://www.cplusplus.com/doc/tutorial/dynamic.html
        http://www.cplusplus.com/doc/tutorial/pointers.html

I highly recommend reading these tutorials before continuing.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
itsmeandnobodyelseCommented:
>>> You need to allocate memory for 'token' before trying to copy data into it.
Not only for token but for each token element as well.

    token = new char*[MAX_TOKEN];
    for (int i = 0;i<MAX_TOKEN ; ++i)
         token[i] = new char[MAX_TOKEN_LENGTH];
0
itsmeandnobodyelseCommented:
In C++ use string and vector.

// include the headers for string and vector
#include <string>
#include <vector>
// omit std:: prefix
using namespace std;

// pass line, vecor for tokens and separators, e. g. " ;/,.\()"
int gettokens(const string& str, vector<string> v, string seps)
{
      string s = str + seps[0];  // add separator at end
      int pos1=0;
      int pos2=0;
      while ((pos2 = (int)s.find_first_of(seps, pos1)) != string::npos)
      {
            v.push_back(s.substr(pos1, pos2-pos1));
            pos1 = pos2 + 1;
      }
      return v.size();
}

Note, you call the above for each line. You could take one vector for all lines, or you define a

   vector<vector<string> >  tokensArr;   // note the space between > >

to have one vector for each line.

0
vwpsAuthor Commented:
Thanks a lot!
0
Infinity08Commented:
May I ask why you gave a B grade ? That usually means that something was missing in the answer and/or that something is still unclear. If that's the case, then you do not have to close the question, and can just ask for clarification where needed. Do you need something explained further ?
0
vwpsAuthor Commented:
Infinity08 - I'm sorry, I should have been more clear. I read about new and understand that it's more appropriate, but was supposed to use malloc. Can I re-open the question, or is it too late to stop this B from tarnishing your profile?
0
Infinity08Commented:
>> I read about new and understand that it's more appropriate, but was supposed to use malloc.

No problem :) the concept is the same, except for the syntax (C++ dynamic memory allocation versus C dynamic memory allocation).


>> Can I re-open the question, or is it too late to stop this B from tarnishing your profile?

You can always re-open a question by using the "Request Attention" link if you want to. But don't worry about my profile ;) I just wanted to make sure you got the help you needed, and didn't require any further assistance (which is usualy what a B grade indicates).

Do not hesitate to ask further about this topic if there's still something that you're unsure about.
0
vwpsAuthor Commented:
Infinity08 - Thanks for the explanation!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Programming Languages-Other

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.