C - Strange values while reading text file with fstream - c++

I wrote a function to read a text file, create an array from the integer values in the file and return the reference of that array to main function. The code I wrote(in VS2010):
//main.cpp
void main(){
int T_FileX1[1000];
int *ptr=readFile("x1.txt");
for(int counter=0; counter<1000; counter++)
cout<<*(ptr+counter)<<endl;
}
and the function is:
//mylib.h
int* readFile(string fileName){
int index=0;
ifstream indata;
int num;
int T[1000];
indata.open("fileName");
if(!indata){
cerr<<"Error: file could not be opened"<<endl;
exit(1);
}
indata>>num;
while ( !indata.eof() ) { // keep reading until end-of-file
T[index]=num;
indata >> num; // sets EOF flag if no value found
index++;
}
indata.close();
int *pointer;
pointer=&T[0];
return pointer;
}
the data in the file contains positive numbers like
5160
11295
472
5385
7140
When I write each value in "readFile(string)" function, it writes true. But when I wrote it to screen as U wrote in "main" function, it gives values strangely:
0
2180860
1417566215
2180868
-125634075
2180952
1417567254
1418194248
32
2180736
irrelevant to my data. I have 1000 numbers in my file and I guess it raves these irrelevant values after a part of true writing. E.g. it writes first 500 values true, and then it writes irrelevant values to my data. Where is my fault?

int T[1000];
...
pointer=&T[0];
you are returning a pointer to a local stack variable which is going to get destructed.
I think what you want to do is to pass in the array T_FileX1 that you have defined to the function and use that directly to read the data into.

You return a pointer to the first element of an array which is allocated on the stack and gets destroyed after your function returns. Try using a vector instead:
vector<int> readFile(string fileName) {
ifstream indata;
int num;
vector<int> T;
indata.open("fileName");
if(!indata){
cerr<<"Error: file could not be opened"<<endl;
exit(1);
}
indata>>num;
while ( !indata.eof() ) { // keep reading until end-of-file
T.push_back(num);
indata >> num; // sets EOF flag if no value found
}
indata.close();
return T;
}

This is a case of undefined behavior. You return a pointer to a local variable, when the function returns the part of the stack used by the function is no longer valid.
Pass the array as an argument to the function instead.

Related

Reading a text file into an array of integers

Given a file with some empty lines, some lines containing only integers, how would I make an array containing all of the integers? I have found methods for strings, but I need a list of integers. I want to do this using getline, but getline gives a string for "line"
A nonfunctioning example which returns the number of integers in the file and modifies a given array:
int getLinesFromFile(string fileName, int arr[], int arrLen) {
ifstream userFile;
userFile.open(fileName);
if (userFile.is_open()) {
int line;
int arrCount = 0;
while (getline(userFile, line)) {
if (tline.length() != 0 && arrCount < arrLen) {
arr[arrCount] = line;
arrCount++;
}
}
return arrCount;
}
else {
return -1;
}
userFile.close();
}
You can just use the >>-operator to read values. It will ignore any whitespace, including empty lines, between values. Here is a modified version of your function that uses it:
int getLinesFromFile(std::string fileName, int arr[], int arrLen) {
std::ifstream userFile(fileName);
int count = 0;
while(count < arrLen) {
int value;
userFile >> value;
if (!userFile.good())
return -1;
arr[count++] = value;
}
return count;
}
Note that you don't need to open and close the file manually, RAII will take care of that for you. Also, if the file could not be opened successfully, or if any other error occured while reading the file, userFile.good() will return false, so you can use that to detect and return an error. It's unclear if your function is supposed to read exactly arrLen values or if less is also valid. But at least you should take care not to write past the end of the provided array.

ifstream wont read all integer

When i read TestData.txt file it gives me wrong output. What am i doing wrong. I am using int array so i can do MergeSort after saving data into array.
TestData.txt
-------------------
31791 564974 477059 269094 972335
739154 206345 634644 227684 398536
910177 507975 589785 67117 395140
598829 372499 364165 450187 996527
700285 263407 918021 661467 457544
656297 846316 221731 240676 68287
913 141702 845802 477617 109824
{
int myArray[1000];
int i;
//reading givin data
const char* filename= "TestData.txt";
ifstream file(filename);
if(file.is_open())
{
for(i = 0; i <=999; ++i)
{
file >> myArray[i];//storing data to array
}
}
Need to check if you ifstream is end of file, in that case you get garbage value from out of the file bound.
With One modification, the code would be OK.
Change:
for(i = 0; i <=999; ++i)
to:
for(i = 0; i <=999 && !file.eof(); ++i)
You are reading 1000 enties from your file which contains clearly less than 1000 integers.
The first values of your array must be correct, but after you reach the end of your file the operator>> will not ready anything.
For example here is one way to write it:
const char* filename= "TestData.txt";
std::vector<int> myArray;
std::ifstream file(filename);
if(file.is_open())
{
int v;
while(file >> v) {
myArray.push_back(v);
}
}
int if I'm not wrong can keep data from -32768 to 32767.
So if u have bigger values than that (which you have, from your source file), you won't have the results you are expecting.
btw, it would be nice to know also what output you are getting.

Getting weird number when trying to read a number from file

I'm trying to read a number from a text file, and I'm not allowed to use a binary file.
I've tried two methods to do this, and both return a strange result.
The first method:
char *theNumber;
int i = 0;
while(data>>text)
{
theNumber[i] = text;
i++;
}
returns some weird accented characters.
The second
int theNumber;
while(data>>text)
{
theNumber = text; // I tried theNumber<<text; as well
}
When I cout the result of this one it returns some big number when the text file contained 123.
string filename;
char text;
int p; //first prime number
int q; //second prime number
unsigned long long toBeEncrypted;
cout<<"Enter name of file to encrypt: ";
cin>>filename;
ifstream data;
ofstream encryptedData;
encryptedData.open("RSA_cipher.txt");
cout<<"Please enter two prime numbers:"<<endl;
p = getPrime(1);
q = getPrime(2);
//doing stuff with file
int theNumber;
data >> theNumber;
//int i = 0;
/*while(data>>text)
{
theNumber[i] = text;
i++;
}*/cout<<theNumber;
...//other stuff unrelated to the problem
This code:
char *theNumber;
int i = 0;
while(data>>text)
{
theNumber[i] = text;
i++;
}
Has Undefined Behavior, because you are using theNumber[i] to access an array which you haven't even allocated. You should have done:
char theNumber[255]; // Buffer size depends on the particular application
int i = 0;
while(data>>text)
{
theNumber[i] = text;  
i++;
}
The second attempt:
theNumber = text;
May or may not work, depending on how you defined text. This is impossible to answer without knowing the definition of text.
Anyway, if you want to read in a number from an input stream, just do:
int number;
data >> number;
UPDATE:
In the last code snippet you updated, the data stream is constructed, but never open. It is not associated to any file. Therefore, attempting to read from that stream won't succeed, and nothing will be stored into number (which is uninitialized).
ifstream data;
// data is not associated to any file after construction...
int theNumber;
data >> theNumber;
This does not create storage for your number.
char *theNumber;
It's a pointer. It points somewhere arbitrary, since you haven't assigned an address to it.
Try this.
char theNumber[10]; // Whatever size you need.
Or this.
int theNumber;
You didn't allocate any memory for char *theNumber;.
The theNumber points to a random location and you are printing random characters

Trouble getting the info stored in the structures in the vector

I am having an issue with my function, it is supposed to print out the list of books stored
void PrintBooklist(vector<BookList>&book)
{
for(int i=0; i<book.size(); i++)
{
if (book[i].memNumBor = -1)
cout<<book[i].title<<endl;
}
}
but it prints out the word "Title;" a few times but leaves it blank. I check the size at the end to make sure whatever is added is being pushed back and it is, but I cannot read it out. Thanks in advance!
int main()
{
vector<BookList>book;
vector<MemInfo>member;
string memberfile;
string bookfile;
ofstream fout;
ifstream fin;
cout << "\n\t\t\tWelcome to Library Management Services!"<<endl<<endl;
Read_Member(member, fin, memberfile);
Read_Book(book, fin, bookfile);
SignIn(member, book, fin, fout, memberfile, bookfile);
return 0;
}
void Read_Member(vector<MemInfo> &member, ifstream &Fin, string &memberfile)
{
MemInfo temp;
cout<<"Please enter the name of the file that contains the member information: ";
getline(cin,memberfile);
Fin.open(memberfile.c_str());
if(Fin.fail())
{
cout<<endl<<"File containing the member information does not exist.\n"<<endl;
exit (0);
}
ReadInfoMem(Fin);
while (!Fin.eof())
{
member.push_back(temp);
ReadInfoMem(Fin);
}
Fin.close();
for (int i=0; i<member.size(); i++)
{
cout<<endl<<member[i].lName<<endl;
}
}
You line assigns memNumBor
if (book[i].memNumBor = -1)
What you want is equality check
if (book[i].memNumBor == -1) // note the double '=='
Update:
After the edit to add more code, I noticed the following:
MemInfo temp;
// ...snip...
ReadInfoMem(Fin); // presumably this reads the member info from 'Fin'?
while (!Fin.eof())
{
member.push_back(temp); // and you add an *empty* 'temp' object to 'member'
ReadInfoMem(Fin);
}
I expect what is happening is that you're reading from Fin in ReadInfoMem into a local MemInfo variable, but you're not returning the populated MemInfo to your enclosing function which adds it to your member vector.
I would suggest either a return-by-value, or a pass-by-reference.
return-by-value
MemInfo ReadInfoMem(ifstream& fs)
{
MemInfo temp;
// populate temp
return temp;
}
// in your calling code:
temp = ReadInfoMem(Fin);
pass-by-reference
void ReadInfoMem(ifstream& fs, MemInfo& temp)
{
// populate temp
}
// in your calling code:
ReadInfoMem(Fin, temp);

Why doesn't this for-loop execute?

I'm writing a program for an exercise that will read data from a file and format it to be readable. So far, I have a bit of code that will separate a header from the data that goes under it. Here it is:
int main() {
ifstream in("records.txt");
ofstream out("formatted_records.txt");
vector<string> temp;
vector<string> headers;
for (int i = 0; getline(in,temp[i]); ++i) {
static int k = -1;
if (str_isalpha(temp[i])) {
headers[++k] = temp[i];
temp.erase(temp.begin() + i);
}
else {
temp[i] += "," + headers[k];
}
}
}
(str_isalpha() is just a function that applies isalpha() to every character in a string.) Now, the for-loop in this program doesn't execute, and I can't figure out why. Does anybody know?
EDIT: As suggested, I changed it to
string line;
for (int i = 0; getline(in,line); ++i) {
temp.push_back(line);
Still skips the for-loop altogether.
vector<string> temp; makes an empty vector. When you then try to read into temp[0], that is undefined behavior. You should pass as getline's second argument a separate string variable, say string foo; before the loop, then temp.push_back(foo); as the first instruction in the loop's body.
If the loop still doesn't run after ensuring that you're reading into a valid string reference, then you should check that the stream you're reading from is valid. The stream will be invalid if the file doesn't exist or if you lack permission to read it, for instance. When the stream isn't valid, getline won't read anything. Its return value is the same stream, and when converted to bool, it evaluates as false. Check the stream's status before proceeding.
ifstream in("records.txt");
if (!in.is_open()) {
std::cerr << "Uh-oh.\n";
return EXIT_FAILURE;
}