Link to home
Start Free TrialLog in
Avatar of packman25
packman25

asked on

Reading an array of characters from a data file

I am a newbie that is trying to read a line from a data file into an array of characters.  I know how to read a string in but that will not work.  I am guessing the code would look something like this:

char arrayName[20];
ifstream infile; //input file object
infile.open("address.txt");
infile.getline(arrayName,20,'\n');

thanks in advance
ASKER CERTIFIED SOLUTION
Avatar of Exceter
Exceter
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of bcladd
bcladd

Just curious: Why won't reading in a string work? Using the built-in data structres to handle variable sized data is often more flexible than hard-coding limits into a program.

-bcl
Your code is fine as long as the line is no longer than 20 characters including the terminating null byte. Also, be aware that getline reads everything up to but not including the delimiter and stops when number of characters read equals the size of the buffer. Again, I believe that size includes the terminating null byte so it will actually stop before the value n to getline.

In other words, if every line is 19 characters or less the getline(arrayName,20,'\n'); should work fine.

Be aware that the delimiter ('\n') will be the next character in the buffer and isn't read yet so you need to do an ignore() or something to get rid of it.

infile.ignore(1024,'\n'); should get rid of that '\n' character. Be aware that as the call is specified, if the next 1024 characters are not '\n' it will only read 1024 chars and then the next char will be the next char to read. However, I believe that surely the line must be less than 1044 characters (20 chars from getline + 1024 from ignore) so that should work fine.

Note that if you do ignore and the line is longer than 19 characters, only the 19 first characters will actually be read, the characters after those 19 up to and including the next '\n' will be ignored.

Alf
>> I believe that size includes the terminating null byte

Correct.
Or You can go straight to Windows approach and write:

#include <windows.h>
#define MAX_READ_BUF 200000
#define MYASSERT(a,b) if (!a) { errhandler(b); return 0; }

void errhandler(char *str) {
  char *lpMsgBuf;
  FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, // source and processing options
    NULL, // pointer to  message source
    GetLastError(), // requested message identifier
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language // language identifier for requested message
    (LPTSTR) &lpMsgBuf, // pointer to message buffer
    0, // maximum size of message buffer
    NULL); // address of array of message inserts
  MessageBox(GetActiveWindow(), lpMsgBuf, str, MB_OK|MB_ICONEXCLAMATION);
  LocalFree(lpMsgBuf);
}

char *ReadFile(char *FilePath)
{
  HANDLE FileHandle;
  BY_HANDLE_FILE_INFORMATION FileInfo;
  DWORD nFileSizeLow, BytesRead;
  char *ReadBuffer;

//Open file
  FileHandle = CreateFile(
    FilePath, //lpFileName
    GENERIC_READ, //dwDesiredAccess
    FILE_SHARE_READ, //dwShareMode
    NULL, //lpSecurityAttributes
    OPEN_EXISTING, //dwCreationDisposition
    FILE_ATTRIBUTE_NORMAL, //dwFlagsAndAttributes
    NULL);
  MYASSERT((FileHandle != INVALID_HANDLE_VALUE), "Problems opening the file!");

//Read in file info...
  MYASSERT(GetFileInformationByHandle(FileHandle, &FileInfo), "Problems reading the file info!");
  nFileSizeLow = FileInfo.nFileSizeLow;
  MYASSERT(nFileSizeLow, "Empty File!");

  MYASSERT((nFileSizeLow < MAX_READ_BUF), "Too big file to read in!");

//Memory allocation for read buffer
  ReadBuffer = (char*)GlobalAlloc(GMEM_FIXED, nFileSizeLow);
  MYASSERT(ReadBuffer, "Problems allocating buffer memory!");

//Read the file in
  MYASSERT(ReadFile(
    FileHandle,
    ReadBuffer,
    nFileSizeLow,
    &BytesRead, // LPDWORD lpNumberOfBytesRead
    NULL/*LPOVERLAPPED lpOverlapped*/), "Problem z odczytem pliku konfiguracyjnego pomocy!");
  MYASSERT((BytesRead == nFileSizeLow), "Unsuccessful read!");

//Close the read file
  MYASSERT(CloseHandle(FileHandle),"Problems closing the file!");
  return ReadBuffer;

//Remember to GlobalFree the obtained buffer like:
//  MYASSERT(!GlobalFree((HGLOBAL)ReadBuffer), "Problems closing the input file!");
}




This approach handles a few possible simple errors and might be good in commercial implementations. Am I right?
Not a must for everybody, though, to use those Windows functions.
Gadzooks!!!

xyzzer, isn't that a little complicated for a task as simple as reading a line of text from disk?

Exceter
Funny You ask. I actually agree! :]
Windows takes QUITE A FEW parameters in its simple functions. And I know it's not a case for beginners. I was just curious if people might consider this useful to check all those assertions and stuff. Might be good for debugging though. Now, if a customer of ours calls us saying that the program crashes saying that "the library called ...dll could not be opened" - we know exactly what happened, even if the person claims the file is there to read... which happens

--Filip
I also see that he included a call to LocalFree(). As far as I know that is a depreceated function from Win32, it's a leftover from old Win 3.1 and should be avoided.

Similarly specifying FormatMessage with FORMAT_MESSAGE_ALLOCATE_BUFFER is a bad idea.

Then it is better to do it in a two stage processing where you first call FormatMessage to have it return the length of the buffer needed and then doing a new char[length + 1] and then calling FormatMessage again with the same arguments (well, buffer is added instead of the null pointer first time) and then using that buffer and free it after.

However, FormatMessage is a bad idea unless you really have message to format. If all you want is to get a string of data from file and then process that string then FormatMessage is really not the right choice, it's like trying to get an airplane in order to go on a hiking trip in the mountains (assuming those mountains are just outside your home and you don't have to fly to get there). It solves a problem but not exactly the problem you have at hand.

Alf
Funny You ask. I actually agree! :]
Windows takes QUITE A FEW parameters in its simple functions. And I know it's not a case for beginners. I was just curious if people might consider this useful to check all those assertions and stuff. Might be good for debugging though. Now, if a customer of ours calls us saying that the program crashes saying that "the library called ...dll could not be opened" - we know exactly what happened, even if the person claims the file is there to read... which happens

--Filip
xyzzer, press the Reload Question Button which is located at the top left of this page after posting. Otherwise refreshing the page will generate a duplicate post, this is also why the board gets flooded by duplicate questiosn from time to time.

Exceter
Avatar of packman25

ASKER

Thanks for the quick responses guys, it is working now.  If it was up to me i would have used a string instead.
You are most welcome.
Sorry for that doubled message. I'm experiencing problems refreshing the page.
Thanks for that note about two staged usage of FormatMessage.
It's a function a use for our company's application in many places, so it might be useful to correct it.
Know any drawbacks of using LocalAlloc in such conditions?

--Filip