Getting input from a file C++ (Matrix Array Input) - c++

I will have user input a file which will contain some data like this :
numRows
numCols
x x x ... x
x x x ... x
.
..
...
Now I am having trouble reading data from a file like this. I am not understanding what should I do to read each integer from each line. This is what I have so far:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class my_exception : public std::exception {
virtual const char *what() const throw() {
return "Exception occurred!!";
}
};
int main() {
cout << "Enter the directory of the file: " << endl;
string path;
cin >> path;
ifstream infile;
cout << "You entered: " << path << endl;
infile.open(path.c_str());
string x;
try
{
if (infile.fail()) {
throw my_exception();
}
string line;
while (!infile.eof())
{
getline(infile, line);
cout << line << endl;
}
}
catch (const exception& e)
{
cout << e.what() << endl;
}
system("pause");
return 0;
}
Also what I want is to store data at each line! That means after the first line I want to store data into the corresponding variable and each cell value.
I am confused as to how can I get each integer and store them in a unique(numRows and numCols) variable?
I want to save first two lines of the file into numRows and numCols respectively, then after each line's each integer will be a cell value of the matrix. Sample input :
2
2
1 2
3 4
TIA

Try this out. The first line reads in the path. Then, using freopen we associate the file provided with stdin. So now we can directly use cin operations as if we are directly reading from stdin and as if the input from the file is typed line for line into the console.
Following this, I create two variables corresponding to numRows and numCols and create a matrix of this dimension. Then I create a nested for loop to read in each value of the matrix.
string path;
cin >> path;
freopen(path.c_str(),"r",stdin);
int numRows, numCols;
cin >> numRows >> numCols;
int matrix[numRows][numCols];
for(int i = 0; i < numRows; i++){
for(int j = 0; j < numCols; j++){
cin >> matrix[i][j];
}
}
Alternatively you can use this to create your matrix
int** matrix = new int*[numRows];
for(int i = 0; i < numRows; i++)
matrix[i] = new int[numCols];
See this for more reference.

Related

.txt file into 2D Char* Array

I'm fairly new to C++ and I'm working on point of sale program from a class in which I will need to read in the menu option along with the price. I'm attempting to read in a .txt file into a 2D Char* but I keep on getting the error message
Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
from line containing
inFile >> array[i][j];
I'm assuming this error is arising due to the way that I'm trying to assign values to each element in the array. I'm sure how to accomplish it.
// Main function
int main (){
char *array[4][3];
string fileName;
vector<string>order;
fileName = fileLoc();
getMenu(fileName, array);
return 0;
}
string fileLoc(){
string file;
cout << "Enter file name or location: ";
cin >> file;
return file;
}
void getMenu(string fileName, char *array[][3]){
ifstream inFile(fileName.c_str());
if (!inFile){
cout << "File failed to open\n";
}
for (int i = 0; i < 4; ++i){
for (int j = 0; j < 3; ++j){
inFile >> array[i][j];
cout << array[i][j] << endl;
}
}
inFile.close();
}
The .txt file I am reading from looks like such
B Burger 3
S Soda 1
F Fries 2
C Chips 1.5

Printing out a vector produces different results every time. It also prints random code that isn't in the vector

So I am reading in a file of zeros and ones.
1,1,1,0,0,0,0,0
1,1,1,0,1,1,0,0
1,1,1,0,1,1,0,0
1,1,1,0,0,0,1,0
1,1,1,0,0,0,1,0
1,1,1,0,0,0,1,0
1,1,1,0,0,1,1,0
1,1,1,0,0,0,0,0
I read in this file and store it into a 2d vector. I then print this 2D vector and get these results as output.
\311[\240\3778\311[\240\377P\311[\240\377h\311[\240\377\200\311[\240\377\230\311[\240\377\260\311[\240\377\310\311[\240\377\340\311[\240\377\370\311[\240\377\312[\240\377(\312[\240\377#\312[\240\377X\312[\240\377p\312[\240\377\210\312[\240\377\240\312[\240\377\270\312[\240\377\320\312[\240\377\350\312[\240\377\313[\240\377\313[\240\3770\313[\240\377H\313[\240\377`\313[\240\377x\313[\240\377\220\313[\240\377\250\313[\240\377\300\313[\240\377\330\313[\240\377\360\313[\240\377\314[\240\377 \314[\240\3778\314[\240\377P\314[\240\377h\314[\240\3771110+2+,0,+a_0co0%We0Enab1AK1ages1eKey0r_1ons_1rvic0_000069631Ap1SUse1co0PKSe1NSLi1e_0"NSA0led_1tion1NSPr1DMSE0ging0mptD0ionE1sDat0appl1A_001D6961y_0mati0$NSA0able1nEna0sRequested_Microsoft Controller_#NSAutomaticQuoteSubstitutionEnabled\Dell S2830dn_AppleMiniaturizeOnDoubleClickQ1 \2410Uen-US3A\300\274\265\302\317+w\32134VdirMap\320 U10.14\241:\323;<=>?#WreplaceTwithRonSomwZOn my way!"?\2003A\300\321i\245z% XMaximizeUen_US\321GH_NSWebServicesProviderW,\200\306IJKL_qDisplayName_NSProviderIdentifierVGoogle^com.google.www 3A\300\321j
\273\375 3A\300\320Sa.$p\245RSTUV_0~/Desktop/CompSci 2100/2100Project3/2100Project3_ ~/Desktop/CompSci 2100/Project_2_~/Desktop/CompSci 2100_#~/Desktop/CompSci 2110/2210project2_0~/Desktop/CompSci 2110/2210Project3/2210Project3#?\340TDark \244]E^_RenRtrRfr _{\233\303\333\361 =_s\221\300\333\3709Y}\232\277\322\355\371*Hc\206\241\265\3223Z\201\244\306\335023457=FIPQRTZ\^emruy\204\206\213\224\225\236\244\247\310\315\344\373%+^\201\232\300\363\374 binput1.txt
\377\377\377\377\377q\205<оa\310\214 CPX#\360dCFPreferencesMessages\340#
\360\200CFPreferencesShmemName\220apple.cfprefs.501v1CFPreferencesShmemIndex0\364CFPreferencesShmemState#\360\200CFPreferencesShmemName\220apple.cfprefs.501v1CFPreferencesShmemIndex0\245CFPreferencesShmemState#\360\200CFPreferencesShmemName\220apple.cfprefs.501v1CFPreferencesShmemIndex0\343CFPreferencesShmemState#\360\200CFPreferencesShmemName\220apple.cfprefs.501v1CFPreferencesShmemIndex0YCFPreferencesShmemState#\360TCFPreferencesShmemName\220apple.cfprefs.501v1CFPreferencesPropertyList\200\255bplist00\337
234_com.apple.trackpad.version_.com.apple.trackpad.fourFingerHorizSwipeGesture_.com.apple.trackpad.fourFingerPinchSwipeGesture_.com.apple.trackpad.fiveFingerPinchSwipeGesture_com.apple.mouse.tapBehavior_ com.apple.trackpad.rotateGesture_com.apple.ColorSync.Devices_'com.apple.trackpad.enableSecondaryClick_com.apple.trackpad.pinchGesture_!com.apple.trackpad.scrollBehavior_5com.apple.trackpad.twoFingerFromRightEdgeSwipeGesture_)com.apple.trackpad.threeFingerDragGesture_(com.apple.trackpad.threeFingerTapGesture_/com.apple.trackpad.threeFingerHorizSwipeGesture_-com.apple.trackpad.fourFingerVertSwipeGesture_.com.apple.trackpad.threeFingerVertSwipeGesture_#PKSecureElementAvailableFlagsByHost_!com.apple.trackpad.momentumScroll_,com.apple.trackpad.twoFingerDoubleTapGesture \322+_0Device.cmra.63306330-3362-6536-3839-633063343435_0Device.mntr.C07EE717-D5E0-4933-131D-70E3DC02779B\322!_DeviceDescriptions_FactoryProfiles\321 Uen_USViPhone\322"#$*Y555810816_DeviceDefaultProfileID\322%&')_DeviceModeDescriptions_DeviceProfileURL\321(WDefault_[/System/Library/Frameworks/ICADevices.framework/Versions/A/Resources/Camera RGB Profile.iccY555810816\321,-^CustomProfiles\321./Q1_:/System/Library/ColorSync/Profiles/Generic RGB
it is actually a lot more than this but I think that would be too much for a question. It prints stuff like this sometimes only one sentence long sometimes forever. I have never experienced something like this I am just trying to print a 2D vector I have done this 1,000's of times with no problems. I am using xCode and here is my code for the whole project.
//read in the file into a double vector
#include <iostream>
#include <vector>
#include <string>
#include <stdlib.h>
#include <fstream>
#include <sstream>
using namespace std;
class OBJs{
public:
string Obj;
int numItemsInObj;
};
//vector to store all of the data for the grid and the row of the big vector
vector<OBJs> row;
vector<vector<OBJs>> grid;
//maybe create an object for the found parameters
OBJs tempObj;
//functions
void load(string fileName);
void printObjs();
int main(int argc, const char * argv[]) {
string file;
cout << "Please enter your filename here: ";
cin >> file;
load(file);
printObjs();
return 0;
}
void load(string fileName){
//read in a line and insert the line(string) into the second index of the vector
string line;
string zeroOrOne;
ifstream file;
file.open(fileName);
//basically a guard let function in swift
if(!file){
cout << "Could not open the file " << fileName << endl;
//exit(0);
}
// you have successfully entered the file specified
while(getline(file, line)){
//grabbing each line of the file into the var line
//delimit this line by , in getline
istringstream ss(line);
while(getline(ss, zeroOrOne, ',')){
//put it into the row vector.
tempObj.Obj = zeroOrOne;
tempObj.numItemsInObj = 0;
row.push_back(tempObj);
}
//put the row in the grid.
grid.push_back(row);
}
file.close();
}
void printObjs(){
for(int i =0; i < grid.size(); i++){
for(int j =0; j< row.size(); j++){
if(grid[i][j].Obj == ""){
//cout << "nothing in this element" << endl;
} else {
cout << grid[i][j].Obj;
}
}
cout << endl;
}
}
In printObjs() you are limiting the loop index j with row.rize():
for(int j =0; j< row.size(); j++)
but use it to index into grid with grid[i][j].Obj. There is no reason that the size of row should be equal to that of grid[i]. Therefore you probably are accessing out-of-bounds causing undefined behavior.
It should probably be for(int j =0; j< grid[i].size(); j++) instead.
You also shouldn't be using global variables if it is not necessary. Both tmpObj and row are only used in load. Therefore declare them there.
Similarly grid can be a local variable, passed around between the functions.
There are couple of problems in your code. Firstly:
while (getline(file, line)) {
istringstream ss(line);
while (getline(ss, zeroOrOne, ',')) {
tempObj.Obj = zeroOrOne;
tempObj.numItemsInObj = 0;
row.push_back(tempObj);
}
grid.push_back(row);
}
Notice what's happening. You read every number per single line, add it to row and then add row to grid. What happens when you read the second line? You read more numbers and add more numbers to row. Now your row contains numbers from both first and second lines. You want to clear the row after copying it to the next element in the grid, like so:
while (getline(file, line)) {
istringstream ss(line);
while (getline(ss, zeroOrOne, ',')) {
tempObj.Obj = zeroOrOne;
tempObj.numItemsInObj = 0;
row.push_back(tempObj);
}
grid.push_back(row);
row.clear();
// ^ notice the clear() call here
}
There is also another issue. Here:
for (int i = 0; i < grid.size(); i++) {
for (int j = 0; j < row.size(); j++) {
if (grid[i][j].Obj == "") {
//cout << "nothing in this vector" << endl;
} else {
cout << grid[i][j].Obj;
}
}
cout << endl;
}
you don't want to check for row.size(). You want to operate on the grid and you want the length of the ith row of the grid. Simply change it to:
for (int i = 0; i < grid.size(); i++) {
for (int j = 0; j < grid[i].size(); j++) {
// notice the change here ^^^
if (grid[i][j].Obj == "") {
//cout << "nothing in this vector" << endl;
} else {
cout << grid[i][j].Obj;
}
}
cout << endl;
}

printing weird symbols to output file, c++

I am writing a code that reads an input file of numbers, sorts them in ascending order, and prints them to output. The only thing printed to output is some really freaky symbols.
Here is my code
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
int i, y, temp, num[20];
char file_nameI[21], file_nameO[21];
ofstream outfile;
ifstream infile;
cout << "Please enter name of input file: ";
cin >> file_nameI;
infile.open(file_nameI);
if (!infile)
{
cout << "Could not open input file \n";
return 0;
}
cout << "Please enter name of output file: ";
cin >> file_nameO;
outfile.open(file_nameO);
if (!outfile)
{
cout << "Could not open output file \n";
return 0;
}
for (i = 0; i < 20; i++)
{
y = i + 1;
while (y < 5)
{
if (num[i] > num[y]) //Correction3
{
infile >> temp;
temp = num[i];
num[i] = num[y];
num[y] = temp;
//y++; //Correction4
}
y++;
}
}
for (i = 0; i < 5; i++)
outfile << "num[i]:" << num[i] << "\n";
return 0;
}
Here is my input
6 7 9 0 40
Here is the output
 „Ô,üþ 54
H|À°ÀzY „Ô,üþ 0
Problems with your code are already mentioned in the comments but again:
First problem is uninitialized elements of num[20] - elements of num have indeterminate values so accessing any of them triggers undefined behavior. You should first read them from the file or at least initialize them to some default value.
The part of code that should most likely do the sorting is just completely wrong. If you'd like to implement your own function for sorting, you can pick up some well-known algorithm like e.g. quicksort - but C++ Standard Library already provides sorting function - std::sort.
Besides obvious mistakes:
You are using char[] - in C++ it's almost always better to use std::string.
Your static array can only store 20 values and you are reading those from a file. You can use std::vector which can grow when you add more elements than its current capacity. It also automatically fixes the problem with uninitialized elements of num[20].
As mentioned in the comments you can organize your code and improve readability by splitting it into functions.
Here you've got it quickly rewritten. This code uses std::string instead of char[], std::vector to store the numbers and std::sort. If there is something you don't understand here, read SO documentation:
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> read_file(ifstream& in_file)
{
vector<int> vec;
int value;
while (in_file >> value)
{
vec.push_back(value);
}
return vec;
}
void write_file(ofstream& out_file, const vector<int>& values)
{
for (size_t i = 0; i < values.size(); ++i)
out_file << "value #" << i << ": " << values[i] << '\n';
}
int main()
{
string input_filename, output_filename;
ofstream out_file;
ifstream in_file;
cout << "Please enter name of input file: ";
cin >> input_filename;
in_file.open(input_filename);
if (!in_file)
{
cout << "Could not open input file\n";
return 0;
}
cout << "Please enter name of output file: ";
cin >> output_filename;
out_file.open(output_filename);
if (!out_file)
{
cout << "Could not open output file\n";
return 0;
}
auto numbers = read_file(in_file);
sort(begin(numbers), end(numbers));
write_file(out_file, numbers);
return 0;
}
You might forgot to store values in num array. Just update your code as follows and it will work.
infile.open(file_nameI);
if (!infile){
cout << "Could not open input file \n";
return 0;
} else{
i = 0;
while (infile >> num[i]){
i++;
}
}

How to edit values of images

I am having some trouble playing around with files. Here is what I am trying to accomplish. I am attempting to filter a PPM image by take the inverse of the blue value (every third value). I can successfully open and write files, but I am experiencing some issues. In my while (myfile.good()) loop, I think only the final 3 numbers get assigned to the variables r, g, and b. What I am trying to do is have every first( out of three) value assigned to the variable r, every second value assigned to g, and every third value assigned to b. However, I want to take 255 - the current b value, and set that as the new b value to apply to filter. Do I have to make 3 separate files (1 for each variable), and then open them all to write them in a 4 file which would serve as the final copy? Or is there a way to copy them all and assign it to a variable? Any help is much appreciated. I am new to c++ so please forgive me. Thank you for your assistance.
Example of values I am attempting to use: http://imgur.com/H6EDFIq
#include <iostream>
#include <cmath>
#include <fstream>
#include <cstdlib>
using namespace std;
int main()
{
char filename[50];
ifstream myfile;
cin.getline(filename, 50);
myfile.open(filename);
if(!myfile.is_open())
{
cout << "File cannot load.";
}
char r [50];
char g [50];
char b [50];
myfile >> r >> g >> b;
while (myfile.good())
{
myfile >> r >> g >> b;
}
myfile.close();
ofstream myfile2;
myfile2.open(filename);
//this is just to test to see what gets written onto the file
//for (int a=0; a<20; a++)
//{
// ** Is this even allowed?? int r = 255 - r;
//myfile2 << r << " " << g << " " << b;
//}
myfile2.close();
return 0;
}
Unless you have a particular need to store the data in memory then it's simpler to just write the data to a new file as you read it.
Here's an example that reads a P3 ppm with 8-bit color entries, inverts the blue channel as you requested, then writes a new file with that data. It doesn't do a ton of error checking but I didn't want to make it any longer than it already is. You'll want to add your own filename prompting and such.
#include <iostream>
#include <string>
#include <fstream>
int main()
{
std::ifstream inFile("lena.ppm");
if(!inFile)
{
std::cerr << "Could not open input file.\n";
return -1;
}
std::string type;
std::string comment;
int width = 0, height = 0, colors = 0;
std::getline(inFile, type);
if(type != "P3")
{
std::cerr << "File is not a P3 format PPM.\n";
return -1;
}
if(inFile.peek() == '#')
{
std::getline(inFile, comment);
}
inFile >> width >> height >> colors;
std::ofstream outFile("lena2.ppm");
if(!outFile)
{
std::cerr << "Could not open output file.\n";
return -1;
}
outFile << type << "\n";
if(!comment.empty())
{
outFile << comment << "\n";
}
outFile << width << " " << height << "\n" << colors << "\n";
for(int y = 0; y < height; ++y)
{
for(int x = 0; x < width; ++x)
{
int r = 0, g = 0, b = 0;
if(!(inFile >> r >> g >> b))
{
std::cerr << "File ended early.\n";
return -1;
}
b = (255 - b);
if(x != 0 && !(x % 5)) //Keep lines under 70 columns per spec.
{
outFile << "\n";
}
outFile << r << " " << g << " " << b << " ";
}
outFile << "\n";
}
return 0;
}
You'll want to check for a .ppm header which is the first line of the .ppm image. Check out .ppm magic numbers, either P3 or P6 and you'll need to check for that. Second line are the dimensions of the image, so you'll need to take that into consideration too.
This is something I worked on earlier so you can get an idea. It might not work immediately so just give it a read.
#include <iostream>
#include <fstream>
#include <sstream>
#include <exception>
int main() {
std::string filename = //whatever your file name is
std::ifstream input(filename.c_str(), std::ios::in | std::ios::binary);
if (input.is_open()) {
std::string line;
std::getline(input, line);
if (line != "P6" || line != "P3" ) { //you're going to want to check if you're using P3 or P6
//print out errors
}
std::stringstream image_dimensions(line);
try {
image_dimensions >> w //your width variable if you want to store it here
image_dimensions >> h //your height variable if you want to store it here
} catch (std::exception &e) {
std::cout << "Format error found in header " << e.what() << std::endl;
return;
}
int size = w*h;
std::getline(input, line);
std::stringstream max_value(line); //max colour value of the image
//you can initialise the vectors here if you want
std::vector<unsigned char> r;
std::vector<unsigned char> g;
std::vector<unsigned char> b;
//we know it max capacity so reserve that size for the vectors
r.reserve(size);
g.reserve(size);
b.reserve(size);
char read_rgb;
for (unsigned int i = 0; i < size; ++i) {
input.read(&read_rgb, 1);
r[i] = (unsigned char) read_rgb;
input.read(&read_rgb, 1);
g[i] = (unsigned char) read_rgb;
input.read(&read_rgb, 1);
b[i] = (unsigned char) read_rgb;
}
}
input.close();
}
You'll want to store r,g,b as arrays of your choosing. Once you've done that, you can just iterate over the array of B and edit it to apply your filter and then just write it to a ppm file.
Also, for error handling, you can always open up the .ppm file using Notepad or Notepad++ and read the image.

Read file from txt

I ve got a txt file with double matrix 50x8. The first two lines contains the array size
50
8
the 50x8 matrix. When i trid to read this file with the above code:
#include<iostream>
#include<fstream>
using namespace std;
int main() {
ifstream infile;
infile.open("C:/Users/zenitis/Desktop/BTHAI_2.3b-src/BTHAI/txtFiles/W1.txt");
double events[50][8];
while (!infile.eof())
{
for(int j=0;j<50;j++)
{
for(int k=0; k<8;k++)
{
infile >> events[j][k];
// infile.get(c
}
}
} //end while
infile.close();
for(int i = 0; i<50; i++){
for(int l=0; l<8; l++){
cout << events[i][l] << " ";
}
cout << "\n";
}
cout << events[0][0];
system("pause");
return 0;
}
Firstly when i print the results the first two elements of the events matrix are the last two of the file. Secondly any idea how to read just the two first elements which is in fact the size of the matrix????
You read the number of rows and columns like this:
int R, C;
infile >> R;
infile >> C;
You do it before the nested loops that read the rest of the file. Then you use the numbers from the file as your end-of-loop targets, rather than hard-coding 50 and 8.