Struggling to store data from file in an 2D int array - c++
I'm working on a project where I'm supposed to be reading sets of parameters from a txt file to then print multiple circles within the command prompt. Here is the format of the file:
10 10 14 15
50 20 5 15
This is just the constructor I've made for the Circle Class, but while it seems to read the file properly, something must be going wrong with my nested for loops. I ran the program with it printing what it was reading from the file during the loops and then what was stored after and it only seems to be saving the last two numbers of the first line (the array seems to hold 14 14 14 14 15 15 15 15). This is only my second semester working on C++, so I can't help but wonder if there's something obvious I'm missing, but I could use some help here trying to figure out what's wrong with my loops/array so I can fix it and move on to the printing of the circles code which I'm also struggling with and running out of time to wrap my head around.
Circle::Circle(string fileAdd) //constructor function
{
int num; //variable for holding the file data in loops
cirCount = 0; //making sure this variable doesn't have junk value
cirStats = nullptr; //making sure this variable doesn't have junk value
string line;
ifstream userFile; //creating a filestream object
userFile.open(fileAdd); //opening the file
if (userFile.is_open()) //confirming the file has properly been opened
{
while (getline(userFile, line)) //the number of circles is stored in a separate variable by this loop
{
if (line.length() != 0) //this if statement checks whether the line is blank or not, and skips it if that's the case
{
cirCount++;
}
}
userFile.clear();
userFile.seekg(0);
cirStats = new int[STATS, cirCount]; //a dynamically allocated array is created in order to store the file data
for (int i = 0; i < cirCount; i++) //these nested loops store the data in a 2 dimensional array
{
for (int j = 0; j < STATS; j++)
{
userFile >> num;
cirStats[j, i] = num;
}
}
userFile.close(); //the file is closed to prevent issues down the line
cout << cirCount << endl;
}
//if the file has not been properly loaded, then this code will run and exit the program
else
{
cout << "User file failed to load. Please reset and try again.";
exit(0);
}
for (int i = 0; i < cirCount; i++) //these nested loops are just for testing what has been saved in the array
{
for (int j = 0; j < STATS; j++)
{
cout << cirStats[j, i] << endl;
}
}
};
The solution is in #Armin_Montigny's comment. Instructions like
cirStats[j, i] = num;
should, in fact, be written this way:
cirStats[j][i] = num;
that is, without the comma operator.
Related
Arrays Outputting the Wrong Numbers in C++
My goal is to have a player input a bunch of numbers for an array then that array is written into a text file. Another part of it is to be able to receive a bunch of numbers from a text file and put them into a sorted array of highest to lowest then output that array. But for some reason, I'm getting a lot of errors, ones that i feel like with some research I can fix. Unfortunately, there is one very confusing situation where I test to make sure the unsorted array is correct by outputting each element of the array. This is not a part of the final program but a test for now. I have a for loop that does so and it works perfectly, outputting each number as expected. Then in the next for loop, the exact same thing is supposed to happen but the numbers being outputted are all messed up. I do not understand how. Code below void readFile(string fName) { string fileName = fName + ".txt"; ifstream myFile(fileName); char c; string num; int count = 0; // Bring the array from file to int array while (!myFile.eof()) { myFile.get(c); if (isspace(c) && num != "") { int n = stoi(num); intArray[count] = n; count++; num = ""; continue; } if (!myFile.eof()) { num += c; } } for (int i = 0; i < 10; i++) { cout << intArray[i] << endl; } // Sort the array higest to lowest for (int i = 0; i < 10; i++) { cout << intArray[i] << " "; for (int j = 9; j >= i; j--) { if (j == 0) { continue; } if (intArray[j] > intArray[j - 1]) { int temp = arr[j]; intArray[j] = intArray[j - 1]; intArray[j - 1] = temp; } } cout << endl; } } sorry about the formatting above, its being weird so imagine the code is within the function. This is what this outputs: 1 2 3 4 5 6 7 8 99 234 1 1 1 1 1 1 1 1 1 1 The numbers before the series of 1's is the actual array, the 1's is what is apparently the array according the cout in the last section of code where it says cout << intArray[i]
Your array does appear to be sorted. The reason for all the ones being printed is due to the location of the cout << within the outer loop. Consider what your array looks like after your first iteration through the inner loop: 234,1,2,3,4,5,6,7,8,99 Now consider that you've incremented i to 1 in the outer loop. When you index your array intArray[i], the ith element is now 1 because you correctly moved it there. Each time, you're moving your smaller elements up one position in the array, then indexing to the position where the 1 is. Don't try to print the sorted array while you're sorting it. Instead loop over it and print it after the sort.
2d array displaying unwanted characters
I have a problem with displaying the contents of a 2d array, I have searched on here for solutions but as I'm not entirely sure what my problem is, I'm not sure I'm asking the right question. I am writing a program that lets the user open a .txt file which will always contain 30 by 30 characters all separated by a comma and the first line and row will be 0,1,2,3,,,9,0,1,2,3,,,9 and the end of each line will be a new line. The programme should display the contents of the .txt file on the screen without the commas then go on to allow the user to search the location of characters in the file. I thought the best way to do this would be to use the getline function with a delimiter to populate a 2d array, this seems to have worked except when I display the content of the array, the last character is repeated and I'm not sure if it's due to the way I am populating the array or the way in which I am displaying the array. while(!inputFile.eof()) { for (int i = 0; i < SIZE; ++i) // SIZE is defined 30 { for (int j = 0; j < SIZE; ++j) { getline(inputFile, line,','); aArray[i][j] = line; // aArray and line are declared as strings std::cout << aArray[i][j]; } } cout << endl; } This is my input: 0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9 1,*,!,8,0,;,*,a,b,0,8,0,.,y,Z,c,4,4,8,8,8,8,y,y,y,4,–,6,8,! 2,0,0,0,0,0,0,0,0,0,0,1,1,1,2,2,0,0,0,5,5,J,J,J,J,J,J,J,J,j 3,9,8,7,0,8,0,8,0,A,c,4,4,*,F,F,6,F,K,J,H,G,5,s,H,U,P,2,2,0 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 5,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 6,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,Y,Y,Y,0,0,0,0,0,0,0 7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 9,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,Y,Y,Y,0,0,0,0,0,0,0 0,0,1,1,2,2,D,D,5,5,$,£,!,a,A,a,A,a,A,a,A,a,A,a,A,a,A,a,A,8 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 2,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 3,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,Y,Y,Y,0,0,0,0,0,0,0 4,0,1,1,2,2,D,D,5,5,$,£,!,a,A,a,A,a,A,a,A,a,A,a,A,a,A,a,A,8 5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 6,0,8,0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 7,P,0,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,Y,Y,Y,0,0,0,0,0,0,0 8,0,1,1,2,2,D,D,5,5,$,£,!,a,A,a,A,a,A,a,A,a,A,a,A,a,A,a,A,8 9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 1,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,Y,Y,Y,0,0,0,0,0,0,0 2,0,1,1,2,2,D,D,5,5,$,£,!,a,A,a,A,a,A,a,A,a,A,a,A,a,A,a,A,8 3,0,1,1,2,2,D,D,5,5,$,£,!,a,A,a,A,a,A,a,A,a,A,a,A,a,A,a,A,8 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 5,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 6,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,Y,Y,Y,0,0,0,0,0,0,0 7,0,1,1,2,2,D,D,5,5,$,£,!,a,A,a,A,a,A,a,A,a,A,a,A,a,A,a,0,8 8,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,Y,Y,Y,0,0,0,0,0,8,0 9,0,1,1,2,2,D,D,5,5,$,£,!,a,A,a,A,a,A,a,A,a,A,a,A,a,A,a,0,8 This is my output: 012345678901234567890123456789 1*!80;*ab080.yZc448888yyy4–68! 200000000001112200055JJJJJJJJj 398708080Ac44*FF6FKJHG5sHUP220 400000000000000000000000000000 588888888888888888888888888888 6PPPPPPPPPPPPPPPPPPPYYY0000000 700000000000000000000000000000 888888888888888888888888888888 9PPPPPPPPPPPPPPPPPPPYYY0000000 001122DD55$£!aAaAaAaAaAaAaAaA8 100000000000000000000000000000 288888888888888888888888888888 3PPPPPPPPPPPPPPPPPPPYYY0000000 401122DD55$£!aAaAaAaAaAaAaAaA8 500000000000000000000000000000 608088888888888888888888888888 7P0PPPPPPPPPPPPPPPPPYYY0000000 801122DD55$£!aAaAaAaAaAaAaAaA8 900000000000000000000000000000 088888888888888888888888888888 1PPPPPPPPPPPPPPPPPPPYYY0000000 201122DD55$£!aAaAaAaAaAaAaAaA8 301122DD55$£!aAaAaAaAaAaAaAaA8 400000000000000000000000000000 588888888888888888888888888888 6PPPPPPPPPPPPPPPPPPPYYY0000000 701122DD55$£!aAaAaAaAaAaAaAa08 8PPPPPPPPPPPPPPPPPPPYYY0000080 901122DD55$£!aAaAaAaAaAaAaAa0888888888888888888888888888888 As you can see the last character is repeated which is not what I want. I am new to C++ so I'm not sure if I'm even using the best method, I spent nearly 2 days trying to solve a problem I created by mistakingly putting cout << endl; within my for loop so I am reaching out to the fine members if stack overflow for some much needed guidance.
To expand on the comment by #WhozCraig, you shouldn't use iostream::eof inside the loop condition, since it won't return true until after the end of the file is read. Instead, something like this should suffice (note there are many ways to do this): #include <iostream> #include <string> #include <fstream> #include <sstream> #define SIZE 30 int main() { std::string line; std::string aArray[SIZE][SIZE]; std::ifstream inputFile("file2.txt"); for (int i = 0; getline(inputFile, line) && i < SIZE; ++i) { std::istringstream lineStream(line); std::string token; for (int j = 0; getline(lineStream, token, ',') && j < SIZE; ++j) { aArray[i][j] = token; std::cout << aArray[i][j]; } std::cout << std::endl; } } Which will provide the desired output: 012345678901234567890123456789 1*!80;*ab080.yZc448888yyy4–68! 200000000001112200055JJJJJJJJj 398708080Ac44*FF6FKJHG5sHUP220 400000000000000000000000000000 588888888888888888888888888888 6PPPPPPPPPPPPPPPPPPPYYY0000000 700000000000000000000000000000 888888888888888888888888888888 9PPPPPPPPPPPPPPPPPPPYYY0000000 001122DD55$£!aAaAaAaAaAaAaAaA8 100000000000000000000000000000 288888888888888888888888888888 3PPPPPPPPPPPPPPPPPPPYYY0000000 401122DD55$£!aAaAaAaAaAaAaAaA8 500000000000000000000000000000 608088888888888888888888888888 7P0PPPPPPPPPPPPPPPPPYYY0000000 801122DD55$£!aAaAaAaAaAaAaAaA8 900000000000000000000000000000 088888888888888888888888888888 1PPPPPPPPPPPPPPPPPPPYYY0000000 201122DD55$£!aAaAaAaAaAaAaAaA8 301122DD55$£!aAaAaAaAaAaAaAaA8 400000000000000000000000000000 588888888888888888888888888888 6PPPPPPPPPPPPPPPPPPPYYY0000000 701122DD55$£!aAaAaAaAaAaAaAa08 8PPPPPPPPPPPPPPPPPPPYYY0000080 901122DD55$£!aAaAaAaAaAaAaAa08
Read Strings from a text file and place in 2D Array
I've spent the past two hours search this and other forums for pointers & guidance on how I can read a txt file, line by line, and store them in a 2D array that I can manipulate with other functions and then later save the array back to the text file; with little luck. Hopefully some bright spark can point me in the right direction. Currently my text file contains data, separated by spaces, that looks like this: Number1 Number2 Number3 Colour1 Colour2 Colour3 Letter1 Letter2 Letter3 ... The "getting and setting" of the 2D Array needs to be done in a separate function, and I think the array's need to be global because they will later be manipulated by other functions (i.e. add a new row, delete a row, etc.) I know the start to the function will need to look something like this: void getAndSetData() { fstream file1; file1.open("1.txt", ios::in); } And will contain a nested for loop that will in turn, set the elements in the 2D array 1 by one. However, I'm really at a loss as how to go about this. Thank you in-advance.
Hello here is example code how I did it ifstream in("test.txt"); // input file string my_array[3][200]; void read_into_array() { if(in.is_open()) { for(int i = 0; i < 200; ++i) // number of rows { for(int j = 0; j < 3; ++j) // number of columns { in >> my_array[i][j]; cout<<my_array[i][j]<<"\t"; } cout<<endl; } } }
Properly handling input when file has less numbers than expected
I'm attempting to read in a file with 3 floating point numbers per line. Right now, I have this implemented as: std::ifstream inFile(inName.c_str()); if (!inFile) { prterr("in ASCII file could not be opened!\n"); return -1; } std::vector<double> xData, yData, zData; xData.resize(nPoints); yData.resize(nPoints); zData.resize(nPoints); inFile.precision(std::numeric_limits<double>::digits10+1); for (int i = 0; i < nPoints; ++i) { inFile >> xData[i] >> yData[i] >> zData[i]; inFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); } so that the program successfully runs even if the user inputs more than 3 numbers per line. However, sometimes a user tries to run the program with <3 numbers per line. When this happens, the parser will obviously store the data incorrectly. I would like to either (a) throw an error if the file has less than 3 numbers per line, or (b) Only store the first N numbers per line in their respective vectors if only N numbers per line are present in the file. The trick is, I want to do this as quickly as possible, as my datasets can be several GBs. I can be guaranteed that my file has the exact same amount of numbers per line. Is there a graceful and efficient way to perform (b)? I know I could implement (a) just by reading the first line as a string separately before the for loop, but that seems quite ugly. Is there a better way to do this?
I know you dd not want to read in the first line as a std::string but you need someway to find out how many white space separated columns there are and unfortunately a newline is treated like white space. If you are okay with doing that though then you can see how man columns you have with std::ifstream inFile(inName.c_str()); std::vector<int> columns_in_file; std::string temp; std::getline(inFile, temp); std::stringstream ss(temp); int number; while (ss >> number) columns_in_file.push_back(number); Then what we need to do is set up a 2d vector that will have the correct number of columns and rows. // get number of columns. 3 max int columns = columns_in_file.size() <= 3 ? columns_in_file.size() : 3; std::vector<std::vector<int>> data(nPoints, std::vector<int>(columns)); // now we add the data we already read for (int i = 0; i < columns; i++) data[0][i] = columns_in_file[i]; Now we have a vector that is the same size as the file unless the file has more then 3 columns and has the first line of data in it. Now we have a decision to make, since you will only ever need to call inFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); while reading if columns_in_file.size() > 3, then we don't want to call it if it is not needed. We could either have the reading code in two different functions or in two different blocks in an else if statement. The latter is what I will show but know you could refactor it into function calls. So to actually read the file we would have something like if (columns <= 3) { for (int i = 0; i < nPoints; i++) { for(int j = 0; j < columns; j++) { infile >> data[i][j]; } } } else { for (int i = 0; i < nPoints; i++) { for(int j = 0; j < columns; j++) { infile >> data[i][j]; inFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); } } }
You can first get the number of columns in the file while reading the first set of values,as a string, and then use the count with another loop inside the first for loop: [EDIT] As per the comments given(and the learning continues again), instead of making the all vectors resize initially, you can resize them depending on the available columns. this will avoid unnecessary space consumption for the unused vectors. std::vector<double> Data[3];//the x,y,z data set(Assuming the maximum number of columns can't be >3) //you can decide which of the vectors(x,y,z) are used by looking at the column count inFile.precision(std::numeric_limits<double>::digits10+1); int count=0;//count the number of columns string first_line; double temp; getline(inFile,first_line); istringstream ss(first_line); while(ss>>temp && count<3) { Data[count].resize(nPoints); Data[count][0]=temp; count++; } for(int i=1; i<nPoints&& inFile.peek() != EOF ; i++) { for(int j=0;j<count;j++) { inFile>>temp; Data[j][i]=temp; } inFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); }
Assigning Symbols to Numbers in a 2D Array
I'm working on a program in C++ that is supposed to read in a file, store the content of the file into a 2D array, assign characters to each of the numbers in the array and store in a char array, and print both of these arrays. It's then supposed to go through the initial array and make sure that each number doesn't differ in value from it's neighboring numbers by more than 1, correct these errors by replacing these numbers with the value of the average of their neighbors, assign characters to this corrected array as it did before, and print both arrays. The character assignments go as follows: 0=blank 1=. 2=, 3=_ 4=! 5=+ 6=* 7=# 8=$ 9=& I have the code written that opens the file and loads the array, but I have no idea where to go from there. To me the obvious, although probably not best, way to do the assignments is to go through the array with a for loop and use a series of if statements to check for the value of the number at each index and assign the appropriate symbol. I'm sure there's a better way to accomplish this. Here is the code I have so far: #include <iostream> #include <fstream> using namespace std; int main() { ifstream prog; prog.open("../prog1.dat"); //If file can't be opened, exit if (!prog) { cerr << "File could not be opened" << endl; exit(EXIT_FAILURE); } else { while (!prog.eof()) { int size = 100, i, j; prog >> size; int **numArray = new int* [size]; for(i = 0; i < size; i++) { numArray[i] = new int[size]; for(j = 0; j < size; j++) { prog >> numArray[i][j]; } cout << endl; } for(i = 0; i < size; i++) { for(j = 0; j < size; j++) { cout <<numArray[i][j] << " "; } cout << endl; } prog.close(); return 0; } } } I'm extremely new to this programming language, this is actually my first program I've done in C++ and I'm literally learning as I go. Any suggestions would be greatly appreciated.
In this code You have not put a check on the difference with neighbour. Moreover their is no need for 2 nested for loops that is a very big overhead. You could have printed the numArray in the first nested for loop. According to you it is your first programming assignment and you are already using double pointers and nested loops and also the way you checked the file is opened or not. Are you sure it's your first assignment