How to read a txt file into a 2d array - c++

Hey guys I am new to reading txt files to arrays, so I need to read this txt file temperature.txt to a two dimensional array. Here is the file I need to read, and the code I tried writing up it complies but Im not sure if it is reading it correctly
T(F) R1 R2 R3 R4
95.0 95.20 66.10 43.10 29.00
96.0 96.10 67.60 43.50 31.20
97.0 97.40 67.00 43.70 30.50
98.0 97.20 69.10 44.10 30.70
99.0 98.90 68.00 44.70 32.80
100.0 99.50 71.10 45.10 31.50
101.0 101.00 71.20 45.30 31.60
102.0 101.60 71.00 45.70 30.50
103.0 101.80 73.10 46.30 32.50
104.0 103.70 73.50 46.60 32.70
105.0 105.60 72.80 47.10 33.60
UPDATE I re did this again without looking at your answers but will this work ?
using namespace std;
#include<fstream>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<stdlib.h>
int main ()
{
char temp[11] [5];
ifstream tempin ("c:\\mydoc2\\temperaturedata.txt");
tempin>>temp[0]>>temp[1]>>temp[2]>>temp[3]>>temp[4]>>temp[5]>>temp[6]>>temp[7]>>temp[8]
>>temp[9]>>temp[10];
while(!tempin.fail())
{
cout<< temp[0] << " " << temp[1] << " " << temp[2] << " " << temp[3]<< " " << temp[4]<< " " << temp[5] << " " << temp [6] <<
" " << temp [7] << " " << temp[8] << " " << temp[9] << " " << temp[10];
tempin>>temp[0]>>temp[1]>>temp[2]>>temp[3]>>temp[4]>>temp[5]>>temp[6]>>temp[7]
>>temp[8]>>temp[9]>>temp[10];
}
cout << endl << endl;
system("pause");
return 0;
}

You have a string myArray[5]; but you're reading 55 elements - that should not work!

There are lots of errors in your code.
1) You have written a read function but you never call it, so it never executes.
2) There is no 2D array in your code. 2D arrays look like this double myArray[10][10];. (that's a 10 by 10 2D array of doubles).
3) You're trying to read floating point numbers, but your array is an array of strings.
4) Your array is size 5 but you try and read 55 items into it.
5) After you open the file you have an infinite loop which just prints out "No file\n". Not sure why you want to print out error messages in a loop. Normally you just print an error message once.
I could go on, but I think the main point is that you're a beginner, and you currently aren't able to write three lines of code without introducing an error (sorry to be harsh but based on the above that is true). So the important lesson is that you should not try to write more than three lines of code at once.
Try something like this
a) Write some code which opens a file, test it and check that it does open the file
b) Add some code to a) to read one number, test it and check that it does read one number.
c) Replace the read one number code with code that reads a 1D array of numbers. Test it and check that it works.
etc. etc.
The point is to build up gradually to the program you want, and test each stage as you go. I can't emphasise how important that is. Every professional programmer works like this, but because you're a beginner the steps you have to take are much smaller than an experienced programmer.

Try something like this:
#include <stdlib.h>
#include <fstream>
#include <sstream>
#include <string>
#include <iostream>
using namespace std;
int main() {
string line;
ifstream myfile ("C:/temps.txt");
int dim_x = 12;
int dim_y = 5;
double temps[dim_x][dim_y] ;
//init the array if neccesary
for(int x = 0;x<dim_x;x++)
for(int y = 0; y<dim_y;y++)
temps[x][y]=0;
if (myfile.is_open()){
for ( int x=0; getline (myfile,line); x++ ){
int y=0;
istringstream iss(line);
while(iss){
string sub;
iss >> sub;
temps[x][y] = ::atof(sub.c_str());
y++;
}
}
myfile.close();
}
cout << "TEMPS:" << endl;
for(int x = 0;x<dim_x;x++){
for(int y = 0; y<dim_y;y++)
cout<<temps[x][y]<<" ";
cout<<endl;
}
return 0;
}

I made some improvements
#include <fstream>
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
void read ();
int main ()
{
read();
return 0;
}
void read()
{
ifstream indata(".\\temperaturedata.txt");
if(indata == NULL)
{
cout<< "Opening file failed."<< endl;
return;
}
const int columns = 5;
const int rows = 11;
double myArray[rows][columns];
string tmp;
getline(indata, tmp);
for(int i = 0; i < rows; ++i)
{
for (int j = 0; j < columns; ++j)
{
cout << "\t" << flush;
indata >> myArray[i][j];
cout.setf(ios::fixed);
cout << setprecision(2) << myArray[i][j] <<flush;
}
cout << endl;
}
indata.close();
}

If the content of your file is like this:
95.0 95.20 66.10 43.10 29.00
96.0 96.10 67.60 43.50 31.20
97.0 97.40 67.00 43.70 30.50
98.0 97.20 69.10 44.10 30.70
99.0 98.90 68.00 44.70 32.80
100.0 99.50 71.10 45.10 31.50
101.0 101.00 71.20 45.30 31.60
102.0 101.60 71.00 45.70 30.50
103.0 101.80 73.10 46.30 32.50
104.0 103.70 73.50 46.60 32.70
105.0 105.60 72.80 47.10 33.60
then, it's quite easy for you to get these values. But there are some errors in your code:
while(!indata.fail()) : This line will cause a dead loop. Use if(!indata) instead.
You will need a 2-dimension array of type double instead of string
Here is what could work:
#include<fstream>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<stdlib.h>
using namespace std;
void read ();
int main ()
{
read();
system("PAUSE");
return 0;
}
void read()
{
ifstream indata("E:\\temperature.txt"); //that's my path,you should use yours.
if(!indata)
{
cout<<"No file."<< endl;
}
if(indata.is_open())
{
double myArray[11][5];
for(int i = 0; i < 11; ++i)
{
for(int j = 0; j < 5; ++j)
{
indata >> myArray[i][j];
//cout<<myArray[i][j]<<"\t";
}
//cout<<endl;
}
}
}
This could work when your txt file doesn't include the first line:T(F) R1 R2 R3 R4, if this line did exit,you should use getline() to move your file pointer to the second line, where you could read the data.

Related

Struct not reading properly C++ Code::Blocks 13.12

I have this problem where I must read data from n books: title, author, price( the pret variable), the number of copies (the nr variable). The variable val represents the "value" of the book, which is price* number of copies.
We only use arrays in school, not vectors of strings therefore all of our problems have fixed-sized strings. Example of the file we are reading from:
3
Ion
Liviu Rebreanu
100
10
Mara
Ioan Slavici
50
3
Poezii
Mihai Eminescu
60
20
I need to print out the data read for every book and also the "value" of it. And I also need to print the data of the book with the highest value afterwards. I'm working in Code::Blocks 13.12 because it'a school assignment. I have no idea why, but it reads only the data for my first book. So therefore it prints a lot of nonsense after that reading. What's wrong with it?
#include <iostream>
#include <string.h>
#include <fstream>
using namespace std;
struct carte
{
char t[50], a[50];
int pret, nr, val;
} v[100];
int main()
{
int n, i, maxx=0, x, j;
ifstream fin ("carte.txt");
fin>>n;
fin.get();
for (i=1; i<=n; i++)
{
fin.get(v[i].t, 50); cout<<v[i].t<<" ";
fin.get();
fin.get(v[i].a, 50);
fin.get(); cout<<v[i].a<<" ";
fin>>v[i].pret>>v[i].nr; cout<<v[i].pret<<" "<<v[i].nr<<endl;
v[i].val=v[i].pret*v[i].nr;
if(v[i].val>maxx)
{
maxx=v[i].val;
x=i;
}
}
for(i=1; i<=n; i++)
{
cout<<v[i].t<<" "<<v[i].a<<" "<<v[i].pret;
cout<<" "<<v[i].nr<<" "<<v[i].val<<endl;
}
cout<<v[x].t<<endl;
return 0;
}
Before you compute the total number of copies (pret * nr) you should make an extra call to fin.get() to deal with what I think is a carriage return. I noticed this after reformatting the code a bit to show the output in terms of a line of comma separated values, or csv.
#include <iostream>
#include <string.h>
#include <fstream>
using namespace std;
struct carte
{
char t[50], a[50];
int pret, nr, val;
} v[100];
int main()
{
int n, i, maxx=0, x, j;
ifstream fin ("carte.txt");
fin>>n;
fin.get();
cout << "Read: " << n << endl;
cout << "Title, Author, Price, Copies" << endl;
for (i=1; i<=n; i++) {
fin.get(v[i].t, 50); cout<<v[i].t<<",";
fin.get();
fin.get(v[i].a, 50);
fin.get(); cout<<v[i].a<<",";
fin>>v[i].pret>>v[i].nr; cout<<v[i].pret<<","<<v[i].nr<<endl;
fin.get();
v[i].val=v[i].pret*v[i].nr;
if(v[i].val>maxx) {
maxx=v[i].val;
x=i;
}
}
cout << "Output: " << endl;
for(i=1; i<=n; i++) {
cout<<v[i].t<<" "<<v[i].a<<" "<<v[i].pret;
cout<<" "<<v[i].nr<<" "<<v[i].val<<endl;
}
cout<<v[x].t<<endl;
return 0;
}
Read: 3
Title, Author, Price, Copies
Ion,Liviu Rebreanu,100,10
Mara,Ioan Slavici,50,3
Poezii,Mihai Eminescu,60,20
Output:
Ion Liviu Rebreanu 100 10 1000
Mara Ioan Slavici 50 3 150
Poezii Mihai Eminescu 60 20 1200
Poezii

C++: How to output a string two letters at a time?

I am trying to read from a file that contains sentences and output them two letters at a time.
IE:
>hello world
Output:
he ll ow or ld
Here is what I have.
#include<iostream>
#include<string>
#include<fstream>
#include<vector>
using namespace std;
int main()
{
string input;
ifstream infile;
infile.open("wordpairs.txt");
while(!infile.eof())
{
getline(infile, input);
for(int i = 0; i < input.length(); i++) //accidentally posted wrong code last time. My apologies.
{
cout << input[i] << input[i+1] << " ";
}
cout << endl;
}
infile.close();
return 0;
}
Edit & Run
and this is what it currently outputs for lets say for example, "hello world"
output:
h he el ll lo ow eo or rl ld d
How do I fix it? I figure it has something to do with my for loop calling input[i + 1], but i dont know how to combine words other than doing that.
This will print anything in pairs of 2 letters:
#include <iostream>
int main()
{
std::string input = "lo zpxcpzx zxpc pzx cpxz c lol";
for (size_t i = 0, printed = 0; i < input.length(); ++i)
{
if (isspace(input[i]))
continue;
std::cout << input[i];
printed++;
if (printed % 2 == 0)
std::cout << " ";
}
return 0;
}
Prints:
lo zp xc pz xz xp cp zx cp xz cl ol
try to modify i++ to i+=2, because you need to skip the second as first
The following takes two characters at a time and prints them. It uses the for syntax to initialize the chars and then to only proceed if reading two characters was successful.
for(char c1{}, c2{}; infile >> c1 >> c2;) {
std::cout << c1 << c2 << ' ';
}
try to use this instead i+=2, in order to avoid repetition.
if it reaches length() , then try using i<s.length().
i have taken s as the string here

C++ code runs forever and eats memory

It seems to be in MakeData function, as that is what breaks the execution. I am very unsure as to why this is not working, as my instructor and many of my classmates have almost identical execution and it is fine. I know for a fact that an almost identical version of this code, with windows file name, also does not run on windows. I have compiled the code. I have run debuggers. Nothing turns up. The debuggers I have run have just run the code until either very obscure errors turn up or it essentially indicates that the process is in some kind of an infinite loop. Any help would be appreciated!
/*
*Program Description:A program to sort a series of strings and scores from a file.
*
*Programmer:Timothy A. Gass
*Date:01/17/17
*/
#include <iostream>
#include <string>
#include <math.h>
#include <fstream>
#include <vector>
#include <ctime>
using namespace std;
void makeData(string);
void getData(vector<string> &, vector<int> &, string);
int main(){
srand(time(0));
string fname = "/home/tim/dev/c++/chpt9/data.txt";
vector<string> name;
vector<int> score;
makeData(fname);
getData(name, score, fname);
for(int i = 0; i < score.size(); i++){
cout << score[i] << endl;
cout << name[i] << endl;
}
cout << "Press enter to exit." << endl;
cin.ignore();
cin.get();
return 0;
}
void makeData(string fname){
int rand1, rand2, rand3;
const int SCORE_MAX_SIZE = 100;
ofstream make(fname);
const int PEOPLE_NUM = 50;
vector<string> firstNames = {
"Gus",
"Taneka",
"Shane",
"Rosella",
"Bennett",
"Filiberto",
"Khadijah",
"Mafalda",
"Rusty",
"Janiece",
"Shavonne",
"Azalee",
"Enedina",
"Heidy",
"Lavelle",
"Darleen",
"Ashton",
"Glynis",
"Gale",
"Norene",
"Madaline",
"Elvin",
"Jacqueline",
"Kristofer",
"Zachary",
"Lorretta",
"Jim",
"Shanelle",
"Tonja",
"Alethia",
"Kasha",
"Katheleen",
"Joyce",
"Kirstin",
"Neil",
"Belkis",
"Maisha",
"Doretha",
"Eliseo",
"Rhiannon",
"Annamarie",
"Latoria",
"Jerica",
"Betsey",
"Delinda",
"Pamula",
"Porsha",
"Fredia",
"Wilda",
"Belen"
};
vector<string> lastNames = {
"Best",
"Shields",
"Finley",
"Blankenship",
"Hobbs",
"Nichols",
"Mcneil",
"Robles",
"Moyer",
"Hays",
"Elliott",
"Ruiz",
"Ritter",
"Gamble",
"Zamora",
"Cole",
"Larson",
"Ibarra",
"Choi",
"Santana",
"Gray",
"Crane",
"Campos",
"Wright",
"Morris",
"Flores",
"Newman",
"Santos",
"Li",
"Archer",
"Chavez",
"Avery",
"Mora",
"Liu",
"Lutz",
"Miles",
"Stewart",
"Austin",
"Wu",
"Turner",
"Brennan",
"Ferrell",
"Mcmillan",
"Whitney",
"Odonnell",
"Conley",
"Maxwell",
"Stafford",
"Carlson",
"Peck"
};
for(int i = 0; i < PEOPLE_NUM; i++){
rand1 = rand()%50;
rand2 = rand()%50;
rand3 = rand()%(SCORE_MAX_SIZE+1);
make << firstNames.at(rand1) + " " + lastNames.at(rand2) << endl;
make << rand3 << endl;
}
}
void getData(vector<string> &name, vector<int> &score, string fname){
ifstream get(fname);
string str;
int num;
if(get.fail()){
cout << "File could not be opened!" << endl;
}
else
{
while(!get.eof())
{
getline(get, str);
get >> num;
cin.ignore();
name.push_back(str);
score.push_back(num);
}
}
}
The comment made by Xin Huang was correct. It turns out the use of getline and cin resulted in some form of infinite loop that would eat memory, until the computer would eventually crash. I still have no idea why there is no solution to this, or why using cin and getline together could have such terrible consequences, especially considering there were really no error codes. Even still, replacing cin with getline in the getData function and then converting back to integer yields a clean program.

std::cout not working inside a for-loop

I'm new to C++, and right now I'm learning from the book called Accelerated C++. I finished the third chapter (vectors), and I came to this exercise:
"Write a program to count how many times each distinct word appears in its input."
After some thinking, I started working on it. I wanted to test the program, but std::cout wasn't working. I put cout << "test"; on a few places in my code to see where's the problem, and the conclusion is that it doesn't work inside the first for-loop. Don't recommend me to use maps to solve the problem, because I'm working on vectors. The variables aren't in English, so I'll translate some for you to know what's going on:
recenica - the sentence; rijec - a word; vel_vektora - size of the vector; duz_recenice - length of the sentence; br_ponavljanja - number of times a word appears in the sentence;
#include <vector>
#include <iostream>
#include <string>
using std::string; using std::vector;
using std::cin; using std::cout;
using std::endl;
int main()
{
string rijec;
vector<string> recenica;
while (cin >> rijec) recenica.push_back(rijec);
cout << endl;
typedef vector<string>::size_type vel_vektora;
vel_vektora duz_recenice = recenica.size();
cout << "test0, ";
for (int i = 0; i < duz_recenice - 1; ++i)
{
cout << "test, !";
int br_ponavljanja = 1;
for (int j = i + 1; j < duz_recenice; ++j)
{
cout << "test2, ";
if (recenica[i] == recenica[j])
{
cout << "test3, ";
++br_ponavljanja;
recenica.erase(recenica.begin() + j);
}
cout << "test4, ";
}
cout << recenica[i] << ": " << br_ponavljanja << endl;
}
cout << "test5, ";
getchar();
return 0;
}
What's the problem with the std::cout?
Add << flush to flush your output buffer (each place).
Or use << endl, which both adds newline and flushes.
There are problems with the code, especially for empty input, but that's what you're out to learn about, so I'll leave you to it! :-)
Cheers & hth.,
I'm afraid the language eludes me in terms of variable names, but this "Works for Me™".
Here is my output (First 3 lines input:)
ytreyert
tyryteter
gdhdfgdf
^Z
test0, test, !test2, test4, test2, test4, ytreyert: 1
test, !test2, test4, tyryteter: 1
test5,
You should definitely try flushing the cout buffers after printing (as per Alf's answer).
I notice that gdhdfgdf is not counted, this is because of this line:
for (int i = 0; i < duz_recenice - 1; ++i)
If you only give 1 input word, this loop will not run, as you do duz_recenice = recenica.size(); before looping.
Changing this line to
for (int i = 0; i < duz_recenice; ++i)
solves this problem.

Why can't I input the integers from a file?

I'm trying to get this C++ code to input a series of numbers from a text file:
int x = 0;
cin >> x;
ifstream iffer;
int numbers[12];
iffer.open("input.txt");
for (int i = 0; i < 12; i++){
iffer >> numbers[i];
}
This doesn't seem to work on the Mac.
Every cell will equal to 0 regardless of the values in the text file. In other words, the ifstream isn't assigning the numbers.
How can I make this work? Is it a Mac issue and if so, how can I get it to work?
Thanks!
Anthony Glyadchenko
Maybe opening the file failed?
You can check if the failbit of iffer is set with fail()
if(iffer.fail())
{
cout << "Failed to open file." << endl;
}
Tried (VC9.0):
#include <iostream>
#include <fstream>
int main()
{
using namespace std;
int x = 0;
cin >> x;
ifstream iffer;
int numbers[12];
iffer.open("input.txt");
for (int i = 0; i < 12; i++){
iffer >> numbers[i];
}
for (int i = 1; i < 12; i++){
numbers[i] = i;
}
return 0;
}
That worked, but the second loop is wrong.
It should work, but be aware, that "get" will always just read one character. This is what I tested, also on Mac OSX, but this has nothing to do with your OS, since it is standard C++:
#include <iostream>
#include <fstream>
using namespace std;
int main(){
ifstream iffer;
iffer.open("input.txt");
char numbers[12];
int i = 0;
while (iffer.good()){
numbers[i] = iffer.get();
i++;
}
for (int n = 0; n < 8; n++){
cout << numbers[n];
}
cout << endl;
iffer.close();
}
The file "input.txt" I am reading in. Make sure this file is in your working directory!:
12345678
While reading the file every character will be stored in your array. So when you have a file like
1 2 3 4 5 6
your array will contain
numbers[0] = '1'
numbers[1] = ' '
numbers[2] = '2'
numbers[3] = ' '
...
I tried your code, slightly modified, on both Linux (g++ 3.4.4) and Mac (g++ 4.0.1) and it works just fine!
With respect to Chuck, if input.txt does not exist, iffer.fail() is true. Since you say that's not the case...
Another possibility is a different input.txt file than what you expected. If it had too few numbers, you'd see zeros (or other garbage values). (You could test with iffer.eof(), though that might be set (appropriately) after reading the last number if there's no trailing whitespace (like a newline). So test eof() before reading!)
Alternatively, you could have a dangling pointer elsewhere in your code trashing something inappropriately. Sometimes adding and removing large chunks of code will permit you to manually "binary search" for where such problems actually lie.
#include <iostream>
#include <fstream>
using namespace std;
#define SHOW(X) cout << # X " = \"" << (X) << "\"" << endl
int main()
{
int x = 0;
cin >> x;
ifstream iffer;
int numbers[12];
iffer.open("input.txt");
SHOW( iffer.fail() );
SHOW( iffer.eof() );
for (int i = 0; i < 12; ++i)
{
SHOW(i);
SHOW(numbers[i]);
iffer >> numbers[i];
SHOW(numbers[i]) << endl;
}
for (int i = 0; i < 12; ++i)
SHOW(numbers[i]);
SHOW( iffer.fail() );
SHOW( iffer.eof() );
}
This sounds like a path issue. You have an "input.txt" file somewhere, but not in the current directory. If this is in a GUI application, keep in mind that the current directory is somewhat unpredictable and you should either give an absolute path or a path relative to some known path (e.g. the path to the current application CFBundle).
Just to test, I just created a Unix program including your precise code wrapped in the following code:
#include <iostream>
#include <fstream>
using namespace std;
int main() {
int x = 0;
// your code
cout << numbers[5] << endl;
return 0;
}
It worked, so if this is in a command-line program and you launched it from the right directory, you must be changing the current directory somewhere in your app.