Access/modify specific row/column of text file - c++
I'm doing some practice in understanding how fstream works, and I've hit a brick wall.
I've initialised a 3x3 text file with each element being 'temp'
I want to be able to access a specific "element", delete it, and then replace it with a string (could be larger or smaller than the current size) but enclosed by the tab characters.
i.e. simulating an edit of a text file
I've been doing some research online, like here: http://www.cplusplus.com/doc/tutorial/files/ but I struggle a lot with implementing it myself.
So the text file, "example.txt" contains:
temp temp temp
temp temp temp
temp temp temp
I'd like to open it for writing, seek the position of say, row 2, column 2 (i.e. corresponding to \n and \t characters), replace it with another string, for example "thisisareplacement"
temp temp temp
temp thisisareplacement temp
temp temp temp
From my understanding, this may not be possible as I'm inputting a much larger size of characters. However I believe somehow defining these \n and \t characters to enclose my strings could give me an opportunity.
Here's my code:
#include <iostream>
#include <fstream>
using namespace std;
int main () {
int numRows = 3;
ofstream myfile ("example.txt");
if (myfile.is_open())
{
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numRows; j++) {
myfile << "temp\t";
}
myfile << "\n";
}
myfile.close();
}
else { cout << "Unable to open file"; }
// now i want to try and edit a specific row (\n) and column (\t)
return 0;
}
Related
2d array comparing with char
I have an array that reads data from a file, the data is binary digits such as 010011001001 and many others so the data are strings which I read in to my 2d array but I am stuck on comparing each value of the array to 0. Any help would be appreciated. #include <iostream> #include <fstream> #include <string> using namespace std; int main() { string myArr[5000][12]; int i = 0, zeroCount = 0, oneCount = 0; ifstream inFile; inFile.open("Day3.txt"); while(!inFile.eof()) { for(int i = 0; i < 5000; i++) { for(int j = 0; j < 12; j++) { inFile >> myArr[i][j]; j++; } i++; } } for(int j = 0; j < 12; j++) { for(int i = 0; i < 5000; i++) { if(myArr[i][j].compare("0") == 0) { zeroCount++; } else { oneCount++; } i++; } if(zeroCount > oneCount) { cout << "Gamma is zero for column " << i << endl; } else { cout << "Gamma is One for column " << i << endl; } j++; } } some input from the text file: 010110011101 101100111000 100100000011 111000010001 001100010011 010000111100
Thank you for editing you question and providing more information. Now, we can help you. You have 2 major misunderstandings. How does a for loop work? What is a std::string in C++ Let us start with the for loop. You find an explanation in the CPP reference here. Or, you could look also at the tutorial shown here. The for loop has basically 3 parts: for (part1; part2; part3). All are optional, you can use them, but no need to use them. part1 is the init-statement. Here you can declare/define/initialize a variable. In your case it is int i = 0. You define a variable of data type int and initialize it with a value of 0 part2 is the condition. The loop will run, until the condition becomes false. The condition will be check at the beginning of the loop. part3 is the so called iteration-expression. The term is a little bit misguiding. It is basically a statement that is executed at the end of the loop, before the next loop run will be executed and before the condition is checked again. In Pseudo code it is something like this: { init-statement while ( condition ) { statement iteration-expression ; } } which means for the part of your code for(int j = 0; j < 12; j++) { int j = 0; // init-statement while ( j < 12 ) { // while ( condition ) { inFile >> myArr[i][j]; // Your loop statements j++; // Your loop statements PROBLEM j++; // iteration-expression from the for loop } } And now you see the problem. You unfortunately increment 'j' twice. You do not need to do that. The last part3 of the for loop does this for you already. So please delete the duplicated increment statements. Next, the std::string A string is, as its names says, a string of characters, or in the context of programming languages, an array of characters. In C we used to write actually char[42] = "abc";. So using really a array of characters. The problem was always the fixed length of such a string. Here for example 42. In such an array you could store only 41 characters. If the string would be longer, then it could not work. The inventors of C++ solved this problem. They created a dynamic character array, an array that can grow, if needed. They called this thing std::string. It does not have a predefined length. It will grow as needed. Therefore, writing string myArr[5000][12]; shows that you did not fully understand this concept. You do not need [12], becuase the string can hold the 12 characters already. So, you can delete it. They characters will implicitely be there. And if you write inFile >> myString then the extractor operator >> will read characters from the stream until the next space and then store it in your myString variable, regardless how long the string is. Please read this tutorial about strings. That is a big advantage over the C-Style strings. Then your code could look like: #include <iostream> #include <fstream> #include <string> using namespace std; int main() { string myArr[5000]; int zeroCount = 0, oneCount = 0; ifstream inFile; inFile.open("Day3.txt"); while (!inFile.eof()) { for (int i = 0; i < 5000; i++) { inFile >> myArr[i]; } } for (int i = 0; i < 5000; i++) { zeroCount = 0; oneCount = 0; for (int j = 0; j < 12; j++) { if (myArr[i][j]== '0') { zeroCount++; } else { oneCount++; } } if (zeroCount > oneCount) { cout << "Gamma is zero for column " << i << endl; } else { cout << "Gamma is One for column " << i << endl; } } } But there is more. You use the magic number 5000 for your array of strings. This you do, because you think that 5000 is always big enough to hold all strings. But what, if not? If you have more than 5000 strings in your source file, then your code will crash. Similar to the string problem for character arrays, we have also a array for any kind of data in C++, that can dynamically grow as needed. It is called std::vector and you can read about it here. A tutorial can be found here. With that you can get rid of any C-Style array at all. But please continue to study the language C++ further and you will understand more and more. Ther are more subtle problems in your code like while(!inFile.eof()), but this should be solved later. I hope I could help
Reading in a CSV file for integers
I have a test file set up here trying to read in a CSV file ifstream file; file.open("New Microsoft Excel Worksheet.csv"); string temp; string arr[15]; int size = 0; int index = 0; while (getline(file, temp, ',')) { if (!temp.empty()) { arr[index] = temp; std::cout << arr[index]; size++; index++; } } Output 34568 29774 18421 it successfully captures each index, and even lines them out in a row (I'm guessing its also capturing a \n?) however I need them to be integers, I would do this in the same loop with a stoi() function, but I need the size of the array to be dynamic (I don't want to use vectors here because this is fitting into another part of code that needs an array) Here is how I turn them into integers and put them in a new array int *intArr = new int[size]; for (index = 0; index < size; index++) { intArr[index] = stoi(arr[index]); std::cout << intArr[index]; } and here is the output for this 3456897748421 It seems to miss each number after it switches to the next row in the csv If I structure it properly, heres whats going on 34568 9774 8421 I'm guessing this has something to do with CSV files giving a \n at the end of a row in an excel file. How do I fix this? I need all the values to be integers, thanks!
I figured it out, you need two while loops like this: while (getline(file, temp)) { istringstream ss(temp); while (getline(ss, data, ',')) { arr[index] = data; std::cout << arr[index]; size++; index++; } } I'm not exactly sure why you need two, because this seems kind of redundant, but getting the line THEN putting it in a string stream seems to get rid of that new line Thanks to #brc-dd for the help!
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
How do I read text into a 2D array of larger parameters than the text (2D array has more rows and columns) using object.get()?
I am attempting to read a text file of characters into a character array (char array[MAX_ROW][MAX_COL]) and the text file has less rows and columns than the character array. This leads to a problem of reading past the substance material that is within the text file. I run into this problem when I read in using the following method: ifstream whiteboard; //ifstream object for reading from a file. whiteboard.open(board_name.c_str()); for(int i = 0; i < MAXROW; i++){ //naive read for canvas, not considering the /n characters or the size of the image.txt for(int j = 0; j < MAXCOL; j++){ //for this to store the print properly it must be the exact size of the image dimensions canvas[i][j] = whiteboard.get(); if(whiteboard.get() == '/n'){ return; } else if(whiteboard.get() != '/n'){ canvas[i][j] = whiteboard.get(); } } } whiteboard.close(); The code above is supposed to run through the 2d array only to the point where the '/n' character is. Thus, allowing me to enter an array of any size. The newline character is at the end of each line of text in a text file (in the form of an enter keystroke). The read to file stops when a newline has been read. However, I am having issues implementing this correctly. Does anyone have any hints that may help me see this more clearly? Thank you very much! EDIT: Input File xxxxxxxxxxxxxx x x x x x x x x x x xxxxxxxxxxxxxx I am hoping to input the box above (along with all of its ' ' characters contained within it) into corresponding values of the character array. I wish to stop the read after reading the rightmost column of x's in and after reading the final x (the bottom right). You can see that my problem comes from having an array that is larger than the size of my text box here. I understand I could fix this by equating the character array to have the same dimensions as the text box, but I wish to keep a large enough constant so that I can read in a file of a relatively large size.
I have one solution, do the following: int n=1025, m=1024, MAX_LINES=1025, i=0, j=0; char character, Matrix[n][m]; fstream file; file.open("file.txt", ios::in); while (file.get(character))// loop executes until the get() function is able to read contents or characters from the file { Matrix[n][m]=character; // copy the content of character to matrix[n][m], here n is used to work as lines and m as normal arrays. m++; // finished copying to matrix[n][m] then m++ else the program will overwrite the contents to the same array. If (m>=1024)// if string[n][m] reached the limit which is 1024. { Matrix[n][m]='\0'; //termimate that line m=0;// start with a new column if (n<MAX_LINES)// if n is less than 1024 then n++;// write to a next line because m can support only 1024 chars. } Matrix[n][m]='\0';// this will terminate the whole string not just one line. file.close(); The Matrix Arrays is filled until the file has contents, but less than 1024x1024 chars, u can increase the chars input from the file but i face problems when taking inn more than 4 kb of data into Matrix... I hope this helps u, if helps even a bit then +1 vote to my answer pls...
You are looking for something like this: ifstream whiteboard; whiteboard.open(board_name); if ( !whiteboard.is_open() ) { // do something here... } char c; int row = 0, col = 0; while ( whiteboard.get( c ) ) { if ( c == '\n' ) { row++; col = 0; continue; } canvas[ row ][ col++ ] = *reinterpret_cast< unsigned char * >( &c ); } whiteboard.close(); With this code you can fill up your matrix with the content of the file... always supposing the "array" in the file fits in the array canvas[][]
If you aren't restricted to using an array, I wanted to add an alternative solution that would allow your canvas to be dynamically sized. using std::vector; std::ifstream whiteboard(board_name); vector<vector<char>> canvas; canvas.emplace_back(); // ^ Replace with push_back(vector<char>()); if not using C++11 char c; while (whiteboard.get(c)) { if (c == '\n') { canvas.emplace_back(); // See above } else { canvas.back().push_back(c); } } You can decide to iterate through your canvas by using either range-based for loops or by using an index (iterators work too but are ugly): // Loop through using range-based for (C++11) for (auto& row : canvas) { for (auto& col : row) { std::cout << col; } std::cout << std::endl; } // Loop through using index for (int i = 0; i < canvas.size(); i++) { for (int j = 0; j < canvas[i].size(); j++) { std::cout << canvas[i][j]; } std::cout << std::endl; }
C++ how make a 2D array using strings and spaces instead of ints
I am making a Sudoku program and my i have a test.txt file that reads 53__7____ 6__195___ _98____6_ 8___6___3 4__8_3__1 7___2___6 _6____28_ ___419__5 ____8__79 where the "_" are actually spaces. The reason i give you _ is so you can see that there are literally only 9 characters on each line. I was thinking that I would have to do something like having GRID[row][column], however I frankly don't know what types I should put my arrays as and I am just lost. I simply want to make it so when i want to output say GRID[0][0] it returns 5, while if i ask for GRID[0][3] it returns a ' '. It is getting it so the array store both the numbers and the spaces is where i am getting completely lost What I currently have tried so far: int main() { ifstream myfile(test.txt); string line; char sudoku_grid[9][9]; if (myfile.is_open()) { while(myfile.good()) { getline(myfile, line); cout << sudoku_grid[line] << endl; } myfile.close(); } else cout << "error"; return 0; } it returns the error line 12: no match for 'operator [ ]' in 'sudoku_grid[line]' Here is my attempt though guidelines through you guys: int main() { ifstream myfile(test.txt); string line; char sudoku_grid[9][9]; if (myfile.good()) { for(int i = 0; i < 9; i++) { getline(myfile, line); for(int j = 0; j < 9; j++) { if (line[j] == ' ') sudoku_grid[j][i] = -1; else sudoku_grid[j][i] = line[i]; } cout << sudoku_grid[i] << endl; } myfile.close(); } else cout << "error"; return 0; } The result is a very awkward answer of strange letters and a new numbers.
I'll just give you the algorithm/logic, not going to write the code for you. Try it and come back when stuck. Initialize output in memory 2D array: numbers[9][9] Open the file Until there is no line left in the file: a. Get the line i b. Until there are no more characters in the line: b1. Get each character of the line c b2. If the character is not space, then numbers[i]=c, else numbers[i]=-1 Your array can be made up of int and in b2 if a whitespace is encountered you can insert -1 to indicate the absence of a number. Of course your code manipulating numbers array needs to take that into account.
Since you need to store both chars and integer type values, use char. each of your integer lies in the range 0-9, so can be stored as a character. char Grid[9][9]; now you can read each character from the string and store it in the array. It will not only keep your spaces intact but also each character. Always remember to use ASCII codes to access the elements of the grid. For 0-9, ASCII codes are 48-57, ASCII code for space is 32. Hope it helps... Edit code: Here is the simplest example... PLace your test file in d:, or edit the path of file in code int main (void) { FILE *fp = fopen("d:\\test.txt","r"); char sudoku_grid[9][9], ch; // I am assuming that file is valid and data in that is also valid if(fp) { for(int i = 0; i < 9; i++) { for(int j = 0; j < 9; j++) { //too read each character ch = fgetc(fp); sudoku_grid[i][j] = ch; } // to read '\n' from the line ch = fgetc(fp); } //for checking if data went correctly for(int i = 0; i< 9;i++) { for(int j= 0; j<9;j++) cout<<sudoku_grid[i][j]; cout<<endl; } } return 0; }
In the first code you get the error message because sudoku_grid can only be indexed by numbers and not by strings. In the second code the line sudoku_grid[j][i] = line[i]; should probably be sudoku_grid[j][i] = line[j]; Does this answer your question?