getline and files

K

KL

I am so lost. I am in a college course for C++, and first off let me
state I am not asking for anyone to do my assignment, just
clarification on what I seem to not be able to comprehend. I have a
..txt file that I want to read into a multi-dimensional string array.
Each line of the file needs to be read into the array. OK..sounds easy
enough, but I can't get the getline(file_name array_name) to work.
So...I am thinking it is definitely operator error here on my part.
Any advice on what I am doing wrong?

KL
 
K

KL

CrayzeeWulf said:
Please post your code.

Yeah that probably would be helpful! Sorry!

#include<iostream>
#include<fstream>
#include<cstdlib>
#include<string>
using namespace std;
int main(){
char question[50];
char string[50];
ifstream questions;
questions.open("qs.txt");//Opens file to read questions from
getline(questions,string);
while(!questions.eof()){
for(int x=0; x<20; x++){
question[x]=string;
getline(questions,string);
}

questions.close();
for(int ind=0; ind<20; ind++){
cout << question[ind];
}
}

And... I still can't get it to build without errors...I keep getting a
message of: c:\Documents and Settings\Kari-Lyn Bjorn\My
Documents\UA\2005 Spring\CS114\Assignments\Project 7\Project
7\10435569.cpp(33): error C2784: 'std::basic_istream<_Elem,_Traits>
&std::getline(std::basic_istream<_Elem,_Traits>
&,std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce
template argument for 'std::basic_istream<_Elem,_Traits> &' from
'std::ifstream'

Which means nothing to me. I leave it to you experts to point out my
errors in logic, etc. (including typos, as I have done that before
too! )

KL
 
C

CrayzeeWulf

KL said:
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<string>
using namespace std;
int main(){
char question[50];
char string[50];
Hi KL,

It is probably not a good idea to name a variable "string" here because the
C++ STL contains a template with the same name (std::string). However, this
is a minor point and not a problem with your program.
ifstream questions;
questions.open("qs.txt");//Opens file to read questions from
getline(questions,string);
You are using "getline()" function here instead of using the corresponding
method of "ifstream". The function "getline()" does not take an "ifstream"
as its first argument. You should consider using something like:

questions.getline( string, 50 ) ;
while(!questions.eof()){
for(int x=0; x<20; x++){
question[x]=string;
In the last line above, "question[x]" has a type of "char" while the type of
"string" is "char *". You cannot assign a value of type "char *" to a
"char". What are you trying to do through the above loop ?

getline(questions,string);
}
Once again, use ifstream::getline() here.

questions.close();
This is a bad idea. You are closing the ifstream inside a "while()" loop
that might attempt to read more data from it. You should close the ifstream
once you are done with the "while()" loop.


Hope that helps.
 
K

KL

CrayzeeWulf said:
KL said:
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<string>
using namespace std;
int main(){
char question[50];
char string[50];
Hi KL,

It is probably not a good idea to name a variable "string" here because the
C++ STL contains a template with the same name (std::string). However, this
is a minor point and not a problem with your program.
ifstream questions;
questions.open("qs.txt");//Opens file to read questions from
getline(questions,string);
You are using "getline()" function here instead of using the corresponding
method of "ifstream". The function "getline()" does not take an "ifstream"
as its first argument. You should consider using something like:

questions.getline( string, 50 ) ;
while(!questions.eof()){
for(int x=0; x<20; x++){
question[x]=string;
In the last line above, "question[x]" has a type of "char" while the type of
"string" is "char *". You cannot assign a value of type "char *" to a
"char". What are you trying to do through the above loop ?

getline(questions,string);
}
Once again, use ifstream::getline() here.

questions.close();
This is a bad idea. You are closing the ifstream inside a "while()" loop
that might attempt to read more data from it. You should close the ifstream
once you are done with the "while()" loop.


Hope that helps.

OK so now I got:
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<string>
using namespace std;

int main(){
char question[50];
char qstring[50];
ifstream questions;
questions.open("qs.txt");//Opens file to read questions from
questions.getline( qstring, 50 ) ;
while(!questions.eof()){
for(int x=0; x<20; x++){
question[x]=qstring;
questions.getline( qstring, 50 ) ;
}
}

questions.close();

for(int ind=0; ind<20; ind++){
cout << question[ind];
}
}

I think part of my problem is that I am not understanding the array v.
string thing. I am trying to build an array of 20 strings. Each
string should be about 50 chars. Am I totally trying to do the
impossible, or am I just going about it wrong? AND I haven't even
started looking at the answers which should be a multidimensional array
of 20 by 6...with a total 0f 120 strings.

KL
 
J

Jon Bell

[...] I have a
.txt file that I want to read into a multi-dimensional string array.
Each line of the file needs to be read into the array.

Oh dear. Let me guess... each line of the file contains one question, and
you're supposed to set up a two-dimensional array of *characters* where
each "row" stores one question?
OK..sounds easy
enough, but I can't get the getline(file_name array_name) to work.

Unfortunately, you've got more problems than just the getline(), if my
guess as to your task is correct. Dealing with character strings as
arrays of characters, and with collections of strings as two-dimensional
arrays of characters, is actually rather tricky and error-prone.

I'm not going to help you with doing it that way, because I wouldn't do it
that way even if someone held a gun to my head. C++ provides much better
tools for this, for six or seven years now, and instructors should not be
foisting the old methods on beginning students. Real programmers do need
to deal with this stuff in old code, but IMHO students should get a firm
grasp of the modern methods first.

Anyway, I'll content myself with presenting a modern C++ solution to your
problem, so you can compare it with the character-array solution when you
finally get it working, and hopefully you'll ask your school why your
instructor isn't staying up to date.


#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

int main ()
{
//-- 'string' is the standard C++ data type for storing character
//-- strings. It is provided for you via the <string> header. It is
//-- much nicer than an array of char for storing character strings,
//-- because it automatically grows or shrinks according to how many
//-- characters it needs to accommodate, so you don't declare it with
//-- a specific size, and you don't have to worry about overflowing it.

string line; // for holding each line in turn as we read it

//-- 'vector' is a standard C++ "container" which is similar to an array,
//-- but is nicer in many ways. For example, you can add data to it in
//-- such a way that it automatically expands as necessary; unlike an
//-- array, where you have to anticipate the amount of data it will need
//-- to store, and declare it with that specific size.

//-- You can declare a vector to have a specific size initially, but here
//-- we don't know how many items we're going to put in it, so we'll let
//-- it have zero size initially and let it expand as necessary.

vector<string> questions;

ifstream questionFile;
questionFile.open ("qs.txt");

//-- All C++ input operations, including getline(), can be used as a loop
//-- condition; if the input succeeds, getline() evaluates as 'true' in
//-- the context of the 'while' statement, and you enter or continue the
//-- loop. If the input fails, getline() evaluates as 'false' and the
//-- loop terminates.

//-- Inside the loop, we take the line that we just read from the file,
//-- and use the vector's push_back() member function to append it to the
//-- end. The vector automatically "grows" as necessary.

while (getline (questionFile, line))
{
questions.push_back (line);
}
questionFile.close();

//-- A vector's size() member function tells us how many items it contains.

for (int k = 0; k < questions.size(); ++k)
{
cout << questions[k] << endl;
}

return 0;
}
 
C

CrayzeeWulf

KL said:
OK so now I got:
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<string>
using namespace std;

int main(){
char question[50];
char qstring[50];
ifstream questions;
questions.open("qs.txt");//Opens file to read questions from
questions.getline( qstring, 50 ) ;
while(!questions.eof()){
for(int x=0; x<20; x++){
question[x]=qstring;
You are getting there. The statement above is still not right. Both
"question" and "qstring" are "arrays of characters". The expression
"question[x]" refers to a single element of the array "queston". This
element is a single character. When you use the statement
"question[x]=qstring", you are sorta trying to put an entire array into
something that can only hold a single character. The best you can do is
"question[x]=qstring[x]". I would suggest that you read more about arrays
and pointers in your text book and work through the examples and problems
to understand them better.
I think part of my problem is that I am not understanding the array v.
string thing. I am trying to build an array of 20 strings. Each
string should be about 50 chars. Am I totally trying to do the
impossible, or am I just going about it wrong? AND I haven't even
started looking at the answers which should be a multidimensional array
of 20 by 6...with a total 0f 120 strings.
Yes. Thinking about multidimensional arrays is the right direction. However,
a much better way of doing this in C++ is to use containers provided by the
C++ Standard Template Library. You should consider using std::vector and
std::string whenever you need arrays and strings.

Hope that helps.
 
K

KL

Jon said:
[...] I have a
.txt file that I want to read into a multi-dimensional string array.
Each line of the file needs to be read into the array.

Oh dear. Let me guess... each line of the file contains one question, and
you're supposed to set up a two-dimensional array of *characters* where
each "row" stores one question?
OK..sounds easy
enough, but I can't get the getline(file_name array_name) to work.

Unfortunately, you've got more problems than just the getline(), if my
guess as to your task is correct. Dealing with character strings as
arrays of characters, and with collections of strings as two-dimensional
arrays of characters, is actually rather tricky and error-prone.

I'm not going to help you with doing it that way, because I wouldn't do it
that way even if someone held a gun to my head. C++ provides much better
tools for this, for six or seven years now, and instructors should not be
foisting the old methods on beginning students. Real programmers do need
to deal with this stuff in old code, but IMHO students should get a firm
grasp of the modern methods first.

Anyway, I'll content myself with presenting a modern C++ solution to your
problem, so you can compare it with the character-array solution when you
finally get it working, and hopefully you'll ask your school why your
instructor isn't staying up to date.


#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

int main ()
{
//-- 'string' is the standard C++ data type for storing character
//-- strings. It is provided for you via the <string> header. It is
//-- much nicer than an array of char for storing character strings,
//-- because it automatically grows or shrinks according to how many
//-- characters it needs to accommodate, so you don't declare it with
//-- a specific size, and you don't have to worry about overflowing it.

string line; // for holding each line in turn as we read it

//-- 'vector' is a standard C++ "container" which is similar to an array,
//-- but is nicer in many ways. For example, you can add data to it in
//-- such a way that it automatically expands as necessary; unlike an
//-- array, where you have to anticipate the amount of data it will need
//-- to store, and declare it with that specific size.

//-- You can declare a vector to have a specific size initially, but here
//-- we don't know how many items we're going to put in it, so we'll let
//-- it have zero size initially and let it expand as necessary.

vector<string> questions;

ifstream questionFile;
questionFile.open ("qs.txt");

//-- All C++ input operations, including getline(), can be used as a loop
//-- condition; if the input succeeds, getline() evaluates as 'true' in
//-- the context of the 'while' statement, and you enter or continue the
//-- loop. If the input fails, getline() evaluates as 'false' and the
//-- loop terminates.

//-- Inside the loop, we take the line that we just read from the file,
//-- and use the vector's push_back() member function to append it to the
//-- end. The vector automatically "grows" as necessary.

while (getline (questionFile, line))
{
questions.push_back (line);
}
questionFile.close();

//-- A vector's size() member function tells us how many items it contains.

for (int k = 0; k < questions.size(); ++k)
{
cout << questions[k] << endl;
}

return 0;
}
USA

Thanks to you and Crazywulf...I think they are just trying to get us to
think and see arrays...I think this assignment isn't quite the way to
do it, but I am just the student. Both of your answers have been
helpful and I will try some more later this morning at school.

KL
 
H

Howard

KL said:
Please post your code.

Yeah that probably would be helpful! Sorry!

#include<iostream>
#include<fstream>
#include<cstdlib>
#include<string>
using namespace std;
int main(){
char question[50];
char string[50];
ifstream questions;
questions.open("qs.txt");//Opens file to read questions from
getline(questions,string);
while(!questions.eof()){
for(int x=0; x<20; x++){
question[x]=string;
getline(questions,string);
}

Aside from what you're discussing with CrayzeeWulf (if that *is* his real
name! :)), you also are not using eof() correctly. I know that many
schools teach a generic read loop as "while not end of file...", but that's
not how the eof() function actually works. That function is intended to
signal why a *previous* read operation failed. Your loop needs to check the
return value of questions.getline(), not questions.eof().

-Howard
 
K

KL

Jon said:
[...] I have a
.txt file that I want to read into a multi-dimensional string array.
Each line of the file needs to be read into the array.

Oh dear. Let me guess... each line of the file contains one question, and
you're supposed to set up a two-dimensional array of *characters* where
each "row" stores one question?
OK..sounds easy
enough, but I can't get the getline(file_name array_name) to work.

Unfortunately, you've got more problems than just the getline(), if my
guess as to your task is correct. Dealing with character strings as
arrays of characters, and with collections of strings as two-dimensional
arrays of characters, is actually rather tricky and error-prone.

I'm not going to help you with doing it that way, because I wouldn't do it
that way even if someone held a gun to my head. C++ provides much better
tools for this, for six or seven years now, and instructors should not be
foisting the old methods on beginning students. Real programmers do need
to deal with this stuff in old code, but IMHO students should get a firm
grasp of the modern methods first.

Anyway, I'll content myself with presenting a modern C++ solution to your
problem, so you can compare it with the character-array solution when you
finally get it working, and hopefully you'll ask your school why your
instructor isn't staying up to date.


#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

int main ()
{
//-- 'string' is the standard C++ data type for storing character
//-- strings. It is provided for you via the <string> header. It is
//-- much nicer than an array of char for storing character strings,
//-- because it automatically grows or shrinks according to how many
//-- characters it needs to accommodate, so you don't declare it with
//-- a specific size, and you don't have to worry about overflowing it.

string line; // for holding each line in turn as we read it

//-- 'vector' is a standard C++ "container" which is similar to an array,
//-- but is nicer in many ways. For example, you can add data to it in
//-- such a way that it automatically expands as necessary; unlike an
//-- array, where you have to anticipate the amount of data it will need
//-- to store, and declare it with that specific size.

//-- You can declare a vector to have a specific size initially, but here
//-- we don't know how many items we're going to put in it, so we'll let
//-- it have zero size initially and let it expand as necessary.

vector<string> questions;

ifstream questionFile;
questionFile.open ("qs.txt");

//-- All C++ input operations, including getline(), can be used as a loop
//-- condition; if the input succeeds, getline() evaluates as 'true' in
//-- the context of the 'while' statement, and you enter or continue the
//-- loop. If the input fails, getline() evaluates as 'false' and the
//-- loop terminates.

//-- Inside the loop, we take the line that we just read from the file,
//-- and use the vector's push_back() member function to append it to the
//-- end. The vector automatically "grows" as necessary.

while (getline (questionFile, line))
{
questions.push_back (line);
}
questionFile.close();

//-- A vector's size() member function tells us how many items it contains.

for (int k = 0; k < questions.size(); ++k)
{
cout << questions[k] << endl;
}

return 0;
}
USA

This has been very helpful, but still in need of a bit of info. Can I
use this as a separate void function to call? And if so, what would be
the parameters? I am almost there...but getting a tad lost in the
finer points. Sigh.

KL
 
J

Jon Bell

This has been very helpful, but still in need of a bit of info. Can I
use this as a separate void function to call? And if so, what would be
the parameters?

Sure, simply change the "int main ()" to, say, "void ShowQuestions ()",
remove the "return 0;" at the end (because now it's no longer a function
that returns an int), and write a new main function after it:

int main ()
{
ShowQuestions ();
return 0;
}

As for parameters, that depends on the context of your new main()
function: what information does it want to specify to your function, and
what information does it expect to get back? It depends on your "grand
design" for the entire program.

As it stands right now, the ShowQuestions() function is completely
self-contained, and doesn't *need* any parameters. I could imagine
turning it into a function that receives the name of the file as a
parameter.

int main ()
{
string fileName = "qs.txt"; // or get the name some other way,
// this is just to set up a parameter
ShowQuestions (fileName);
return 0;
}

and then the function would start off with something like

void ShowQuestions (string questionFileName)

and then when you actually open the file, you would use the name stored in
the parameter:

questionFile.open (questionFileName.c_str());

The "c_str()" bit comes about because open() expects to receive a pointer
to a char array, not a string, for historical reasons. The c_str() member
function of a string gives you such a pointer.
 
K

KL

Jon said:
Sure, simply change the "int main ()" to, say, "void ShowQuestions ()",
remove the "return 0;" at the end (because now it's no longer a function
that returns an int), and write a new main function after it:

int main ()
{
ShowQuestions ();
return 0;
}

As for parameters, that depends on the context of your new main()
function: what information does it want to specify to your function, and
what information does it expect to get back? It depends on your "grand
design" for the entire program.

As it stands right now, the ShowQuestions() function is completely
self-contained, and doesn't *need* any parameters. I could imagine
turning it into a function that receives the name of the file as a
parameter.

int main ()
{
string fileName = "qs.txt"; // or get the name some other way,
// this is just to set up a parameter
ShowQuestions (fileName);
return 0;
}

and then the function would start off with something like

void ShowQuestions (string questionFileName)

and then when you actually open the file, you would use the name stored in
the parameter:

questionFile.open (questionFileName.c_str());

The "c_str()" bit comes about because open() expects to receive a pointer
to a char array, not a string, for historical reasons. The c_str() member
function of a string gives you such a pointer.
USA

OK, so if I do it this way, am I able to use the vector elsewhere, or I
can only us it in that void function, is that correct? I know I will
need to call that vector again elsewhere. That is where I was having a
bit of trouble...making that vector available for further use. (I
actually have to pull from it randomly, so I have to do a randomizing
function too...but I got that all figured out already!)

KL
 
J

Jon Bell

OK, so if I do it this way, am I able to use the vector elsewhere, or I
can only us it in that void function, is that correct?

If you make the vector one of the parameters of the function, you can
use it in main(). The key is to make it a reference parameter (note the
'&' below) so that any changes that the function makes to the vector get
passed back to the calling function (main()).

void GetQuestions (string questionFileName, vector<string>& questions)
{
// ... read from the file into the vector like we did before
}

int main ()
{
string fileName = "qs.txt";
vector<string> myQuestions;
GetQuestions (fileName, myQuestions);
// now do what you want with myQuestions, maybe pass it to another
// function for further processing
return 0;
}

Actually what the '&' does is make 'questions' in the function and
'myQuestions' in main(), two names for one and the same vector.
'questions' in the function is a reference to (or alias for) 'myQuestions'
in main().
 
K

KL

Jon said:
If you make the vector one of the parameters of the function, you can
use it in main(). The key is to make it a reference parameter (note the
'&' below) so that any changes that the function makes to the vector get
passed back to the calling function (main()).

void GetQuestions (string questionFileName, vector<string>& questions)
{
// ... read from the file into the vector like we did before
}

int main ()
{
string fileName = "qs.txt";
vector<string> myQuestions;
GetQuestions (fileName, myQuestions);
// now do what you want with myQuestions, maybe pass it to another
// function for further processing
return 0;
}

Actually what the '&' does is make 'questions' in the function and
'myQuestions' in main(), two names for one and the same vector.
'questions' in the function is a reference to (or alias for) 'myQuestions'
in main().
USA


It probably isn't correct wordage and all, but I think of it as tying
them together. Nothing happens to the one in the function without the
same thing happening to the one in the main.

I do appreciate all your help. I am learning a lot. I was wondering
though, is a vector just another way of thinking of an array? Could
you maybe expound a bit on just what a vector is and what the
difference is between a vector and an array?

KL
 
J

Jon Bell

[...] is a vector just another way of thinking of an array?

Vectors and arrays are two different ways of implementing the same basic
concept: storing a bunch of items of the same type in a contiguous chunk
of memory, allowing you to access individual items quickly by specifying
an index in square brackets.

C++ has had arrays from the beginning. It "inherited" them from C.
Arrays give you the basic concept described above, but not much else.
They don't behave like ordinary variables in many ways, for example you
can't copy one array to another simply by writing a statement like
"b = a;" you have to write a loop that copies each item one at a time.

Vectors came in with the first C++ standard in 1998. Before that, there
were third-party libraries that had vectors. They behave mostly like
ordinary variables do (so you *can* use "b = a" to copy one vector to
another, for example). And they have features that ordinary arrays don't
have, like being able to tell you their size like in my example, or being
able to "grow" automatically as you push_back() data onto them.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,665
Latest member
salkete

Latest Threads

Top