Ok, I'm a rookie at this and here is what I've been sitting here for a while scratching my head doing.
My goal is to read in a file from a command line argument and store the contents of the file in an array strings of which each element is a line from the file. I need the whole line including white spaces. And I need to cycle through the whole text file without knowing how large/small it is.
I'm fairly sure that key.eof() here is not right, but I've tried so many things now that I need to ask for help because I feel like I'm getting further and further from the solution.
ifstream key(argv[2]);
if (!key) // if file doesn't exist, EXIT
{
cout << "Could not open the key file!\n";
return EXIT_FAILURE;
}
else
{
vector<string> lines;
for (unsigned i = 0; i != key.eof(); ++i)
{
getline(key, lines[i]);
}
for (auto x : lines)
cout << x;
If anyone could point me in the right direction, this is just the begging of what I have to do and if feel clueless. The goal is for me to be able to break down each line into a vector(or whatever I need) of chars INCLUDING white spaces.
I think you want something like this:
vector<string> lines;
string line;
while(getline(key, line)) // keep going until eof or error
lines.push_back(line); // add line to lines
To continuous read lines from file and keep it in array, I would do something like this using a while loop instead of a for loop.
int counter = 0;
while (getline(key, lines[counter]) {
counter++;
}
Related
Is there an efficient way to read the last line of a text file? Right now i'm simply reading each line with code like below. Then S holds the last line read. Is there a good way to grab that last line without looping through entire text file?
TStreamReader* Reader;
Reader = new TStreamReader(myfile);
while (!Reader->EndOfStream)
{
String S = Reader->ReadLine();
}
Exactly as Remy Lebeau commented:
Use file access functions FileOpen,FileSeek,FileRead
look here for example of usage:
Convert the Linux open, read, write, close functions to work on Windows
load your file by chunks from end into memory
so make a static buffer and load file into it from end by chunks ...
stop on eol (end of line) usually CR,LF
just scan for 13,10 ASCII codes or their combinations from end of chunk. Beware some files have last line also terminated so you should skip that the first time ...
known eols are:
13
10
13,10
10,13
construct line
if no eol found add whole chunk to string, if found add just the part after it ...
Here small example:
int hnd,siz,i,n;
const int bufsz=256; // buffer size
char buf[bufsz+1];
AnsiString lin; // last line output
buf[bufsz]=0; // string terminator
hnd=FileOpen("in.txt",fmOpenRead); // open file
siz=FileSeek(hnd,0,2); // obtain size and point to its end
for (i=-1,lin="";siz;)
{
n=bufsz; // n = chunk size to load
if (n>siz) n=siz; siz-=n;
FileSeek(hnd,siz,0); // point to its location (from start)
FileRead(hnd,buf,n); // load it to buf[]
if (i<0) // first time pass (skip last eol)
{
i=n-1; if (i>0) if ((buf[i]==10)||(buf[i]==13)) n--;
i--; if (i>0) if ((buf[i]==10)||(buf[i]==13)) if (buf[i]!=buf[i+1]) n--;
}
for (i=n-1;i>=0;i--) // scan for eol (CR,LF)
if ((buf[i]==10)||(buf[i]==13))
{ siz=0; break; } i++; // i points to start of line and siz is zero so no chunks are readed after...
lin=AnsiString(buf+i)+lin; // add new chunk to line
}
FileClose(hnd); // close file
// here lin is your last line
1.i am trying to check whether the cin.get() leaves the end line character in stream and considered it for next input.
i have tried this code in code blocks but unable to provide input for next string,i am attaching code i have tried and the output .could anyone please explain.
#include<iostream>
using namespace std;
int main()
{
char s1[10];
char s2[10];
cout << "enter the first string: ";
cin.get(s1, 10);
cout << "enter the second string: ";
cin.getline(s2, 10);
cout << s1 << " " << s2;
return 0;
}
enter the first string: hello
enter the second string: hello
please explain the output
This get function reference says that your overload is
Same as get(s, count, widen('\n'))
And that overload of the function reads until (among other things)
the next available input character c equals delim, as determined by Traits::eq(c, delim). This character is not extracted (unlike basic_istream::getline())
[Emphasis mine]
So the newline is left in the input buffer, for the getline call to read as an "empty" line.
If you want to read lines, I suggest you use std::string and std::getline (which does read, and throw away, the newline).
cin.get() grabs the newline character by default. It will not leave the newline in the stream.
I am having trouble understanding the output of my very little program which should read characters from a text file until it finds a new line.
It correctly outputs the characters and stops, but I don't understand why it still outputs the newline ('\n) character in the terminal and doesn't end before getting to it.
I know that I could use getline() or find another way but I would really understand the reason behind this behaviour.
Thank you in advance!
Edo
Code:
int main() {
std::ifstream in_file;
in_file.open("../responses.txt");
char c;
while(c != '\n'){
in_file.get(c);
std::cout << c << std::endl;
}
return 0;
}
Output:
A
B
C
D
E
Time elapsed: 000:00:000
The
Quick question: I have a csv file that contains 360 rows and 3 columns. Each cell or matrix entry is a type double (for example: 1.0000000, 0.9314933, 0.9866587). I was thinking the following code would get the entries:
//construct 2-d array
float CDF_inputs[360][3];
std::ifstream file("filename");
for(int row = 0; row < 360; ++row)
{
std::string line;
std::getline(file, line);
if ( !file.good() )
break;
std::stringstream iss(line);
for (int col = 0; col < 3; ++col)
{
std::string val;
std::getline(iss, val, ',');
if ( !iss.good() )
break;
std::stringstream convertor(val);
convertor >> CDF_inputs[row][col];
}
}
The file only contains doubles, no other characters (than the commas). I run the code, it builds (visual studio c++) and there are no errors. However I do not believe it is working correctly.
Is the given code correct?
How can I debug, or "print to console" either the array or an error message if the file is bad, or if the array fails to "load"?
Thanks first post for me.
I think you are learning. Well, you can place breakpoint by hitting F9 on a appropriate source code line and execute your code line-by-line by pressing F10 button. So, while debugging, you can hold mouse pointer on variables to see what they contain.
I have assumed that you are using Visual Studio.
Good Luck.
I'd like to read a file line-by-line. I have fgets() working okay, but am not sure what to do if a line is longer than the buffer sizes I've passed to fgets()? And furthermore, since fgets() doesn't seem to be Unicode-aware, and I want to allow UTF-8 files, it might miss line endings and read the whole file, no?
Then I thought I'd use getline(). However, I'm on Mac OS X, and while getline() is specified in /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/usr/include/stdio.h, it's not in /usr/include/stdio, so gcc doesn't find it in the shell. And it's not particularly portable, obviously, and I'd like the library I'm developing to be generally useful.
So what's the best way to read a file line-by-line in C?
First of all, it's very unlikely that you need to worry about non-standard line terminators like U+2028. Normal text files are not expected to contain them, and the very overwhelming majority of all existing software that reads normal text files doesn't support them. You mention getline() which is available in glibc but not in MacOS's libc, and it would surprise me if getline() did support such fancy line terminators. It's almost a certainly that you can get away with just supporting LF (U+000A) and maybe also CR+LF (U+000D U+000A). To do that, you don't need to care about UTF-8. That's the beauty of UTF-8's ASCII compatibility and is by design.
As for supporting lines that are longer than the buffer you pass to fgets(), you can do this with a little extra logic around fgets. In pseudocode:
while true {
fgets(buffer, size, stream);
dynamically_allocated_string = strdup(buffer);
while the last char (before the terminating NUL) in the buffer is not '\n' {
concatenate the contents of buffer to the dynamically allocated string
/* the current line is not finished. read more of it */
fgets(buffer, size, stream);
}
process the whole line, as found in the dynamically allocated string
}
But again, I think you will find that there's really quite a lot of software out there that simply doesn't bother with that, from software that parses system config files like /etc/passwd to (some) scripting languages. Depending on your use case, it may very well be good enough to use a "big enough" buffer (e.g. 4096 bytes) and declare that you don't support lines longer than that. You can even call it a security feature (a line length limit is protection against resource exhaustion attacks from a crafted input file).
Based on this answer, here's what I've come up with:
#define LINE_BUF_SIZE 1024
char * getline_from(FILE *fp) {
char * line = malloc(LINE_BUF_SIZE), * linep = line;
size_t lenmax = LINE_BUF_SIZE, len = lenmax;
int c;
if(line == NULL)
return NULL;
for(;;) {
c = fgetc(fp);
if(c == EOF)
break;
if(--len == 0) {
len = lenmax;
char * linen = realloc(linep, lenmax *= 2);
if(linen == NULL) {
// Fail.
free(linep);
return NULL;
}
line = linen + (line - linep);
linep = linen;
}
if((*line++ = c) == '\n')
break;
}
*line = '\0';
return linep;
}
To read stdin:
char *line;
while ( line = getline_from(stdin) ) {
// do stuff
free(line);
}
To read some other file, I first open it with fopen():
FILE *fp;
fp = fopen ( filename, "rb" );
if (!fp) {
fprintf(stderr, "Cannot open %s: ", argv[1]);
perror(NULL);
exit(1);
}
char *line;
while ( line = getline_from(fp) ) {
// do stuff
free(line);
}
This works very nicely for me. I'd love to see an alternative that uses fgets() as suggested by #paul-tomblin, but I don't have the energy to figure it out tonight.