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,2 0,'\n');
thanks in advance
char arrayName[20];
ifstream infile; //input file object
infile.open("address.txt")
infile.getline(arrayName,2
thanks in advance
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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
In other words, if every line is 19 characters or less the getline(arrayName,20,'\n')
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.
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_BU FFER | 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(GetFileInformatio nByHandle( 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_FI XED, 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(FileH andle),"Pr oblems closing the file!");
return ReadBuffer;
//Remember to GlobalFree the obtained buffer like:
// MYASSERT(!GlobalFree((HGLO BAL)ReadBu ffer), "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.
#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_BU
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
LocalFree(lpMsgBuf);
}
char *ReadFile(char *FilePath)
{
HANDLE FileHandle;
BY_HANDLE_FILE_INFORMATION
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(GetFileInformatio
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_FI
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(FileH
return ReadBuffer;
//Remember to GlobalFree the obtained buffer like:
// MYASSERT(!GlobalFree((HGLO
}
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
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
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_BU FFER 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
Similarly specifying FormatMessage with FORMAT_MESSAGE_ALLOCATE_BU
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
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
Exceter
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
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
-bcl