How can i transfer a text file(.txt) to array 2D in c++ and this is my source code
fstream fin('textfile.txt', ios::in);
int matrix[n][m]; // n is the number of rows and m is the number of columns
for(int i = 0;i < n; i++){
for(int j = 0; j<m; j++){
fin>>matrix[i][j];
}
}
but how can i detemine n and m for do this,i need your help and your advice, please Join us your perspectives
This solution requires C++11+
If there is no n & m in the file, you must assume that the layout is also in 2D
One Two Three
Four Five Six
Warning:: Untested code.
std::stringstream res;
std::string wordUp;
std::vector<std::string> str;
// the matrix, vector of vector of strings.
std::vector<std::vector<std::string>> matrix;
fstream fin('textfile.txt', ios::in);
int lines = 0;
int words = 0;
// read the file line by line using `getline`
for (std::string line; std::getline(fin, line); ) {
++lines;
// use stringstream to count the number of words (m).
res.str(line); // assign line to res. might also need some reset of good().
while (res.good()) {
res >> wordUp;
str.push_back(wordUp);
++words;
}
matrix.push_back(str);
str.erase(str.begin());
}
So u mean u want to read a file and copy contents to char Matrix[][]??, you can use while loop to read characters, and split every 1024 bytes(1 kb) by lines, i mean do this:
#include <fstream.h>
int main()
{
int n=0, m=0, MAX_LINES=1025, i=0, j=0;
char character, Matrix[1024][1025];
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();
for (i=0; i<1025; i++)
{
for (j=0; j<=1024 || Matrix[i][j]!='\0'; j++)
cout<<Matrix[i][j];
}
return 0;
}
This code will read 1024×1024 chars, but if the txt file is less than 1024(m) characters, the while loop will be exited and Matrix[n][m]='\0'; statement is executed.
EDIT: As asked by David i have written the whole code with main() sorry bro i forget, the bug in the code was the variables n and m were intialised to 1025 and 1024 so the program skips writing to Matrix as the Matrix[1024][1025] cannot store more characters... I think this would help, ok bro...
Related
I am working on a project for a basic programming class and am not entirely familiar with strings and all. The goal of the program is to take one simple text file with a few random, repeated words, and return a file with each separate word and the number of times it appears in the file. The input file looks something like
Class
Text
Class
fall
mark
mark
Text
and the output should read,
Class 2
Text 2
fall 1
mark 2
I am having trouble reading and setting up an array for the input data. Not sure exactly how to set it up. Any suggestions would be great.
int main(void)
{
int k=0, p=0, words=0, match=0, ch=0;
double xx;
char I[WORD][LETTER;
FILE *file;
file = fopen("C:\\Users\\Andrew\\Documents\\te2.txt", "r");
if(file != NULL){
// Count the amount of words in file set up array
int i=0, j=0;
for(i=0; i<WORD; i++){
for(j=0; j<LETTER; j++){
fscanf(file, "%s", &I[i][j]);
ch++;
}}
What you are trying to do is really quite simple. Lets break it down:
Read in each word in a file.
Store it in something that recognises individual words and can increment a number (a std::map).
Print out the result.
Part 1 - Read each word
Lets read in a file word by word. Searching read in a file word by word c++ would have sufficed but here is a short example:
ifstream file; // A in file stream, the c++ way of reading files.
file.open ("example.txt");
string word; // A word to store each word.
// Read each word.
while ( file >> word) {
// Do something with your word. (Part 2)
}
Its as easy as that!
Part 2 - Store them in a map
Now we want to have a map, this is because a map will store only unique words and we can use its value to count the number of each unique word. Read about maps here. We need a string as the key and an int to count the words, so:
std::map<std::string, int> myWords;
To put them in, we need to check if the word already exists, otherwise we set it to one:
// See if the map already contains the word (not only is this easy, it is also very efficient!)
// If we dont contain the word then we get an iterator to past the end of the map.
if (myWords.find(word) == myWords.end()) {
myWords[word] = 1; // If our map doesn't already have this word
// we have encountered our first!
} else {
myWords[word]++; // The map already has the word so just increment it.
}
Part 3 - Print them out
The easy part, simply iterate over the map and print them out:
for (auto wordPair : myWords) {
std::cout << wordPair.first << " " << wordPair.second << std::endl;
}
Put it all together
And you get this:
http://ideone.com/TCMOKh
So I have been working on it and I came up with the idea to have the data come in character by character withfscanf(file, "%c", &array[]);and i have been working on an algorithm to set a certain amount of the characters before a '\n' into a smaller array to use it tom compare to the full string. in the file i have added spaces to any word that was a few characters so that the "word sizes are all the same with the spaces, the arrays are successful just having some issues witht the algorithm itself.
`
#include <stdio.h>
#include <cctype>
#define Words 9
#define Letters 6
#define CHARACT Words*Letters
#define CORRECT 3
int main(void){
double xx;
int match=0, indx=0, i=0, k=0, j=0, b, read=0, r, t, track=0;
char shrt[Letters], Long[CHARACT], c;
FILE *file;
file =fopen("C:\\Users\\Andrew\\Documents\\te2.txt", "r");
if(file != NULL)
{
// initialize long string (full file by characters)
for(k=0; k<CHARACT; k++)
{
fscanf(file, "%c", &Long[k]);
}
// set up shrt[] to compare to rest of array
while(track <= CHARACT)
{
indx+=track;
//STEP 1: take shrt[] out of Long[] for comparisons
for(r=0; r<Letters; r++)
{
shrt[r] = Long[indx];
indx++;
if(shrt[r] == '\n')
break;
}
for(t=0; t<CHARACT; t++)
{
match=0;
int VV = track*Letters;
// STEP 2: keep shrt[] constant, compare to full string one by one
for(int p=0; p<Letters-2; p++)
{
if(shrt[p] == Long[VV])
{
match++;
}
}
if(match >= CORRECT)
{
for(int ee=0; ee<Letters; ee++)
{
printf("%c", shrt[ee]);
}
printf(" %i", match);
}
track+=Letters;
}
}// big for loop
// TESTING TESTING
printf("\n\n\nTEST\n\n");
for(k=0; k<CHARACT; k++)
printf("%c", Long[k]); // delete when ready
printf("%i", read);
}// big if
else{
printf("error");
}
fclose(file);
scanf("%f", &xx);
return 0;
}`
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');
}
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;
}
Okay so the input file looks like this:
00000000100000001010
00000000010000001001
11100000010100000010
10100100101010101010
00101010010010101000
This is an example grid which is 5x20 and the catch is that the rows and cols can be arbitrary. Which means that I need to figure out how many rows and cols the input file has before I can start computing my two dimensional array.
So I am a little confused because right now I am just trying to read in the array then output it to the console without knowing the rows and cols initially. Please help me with this it's annoying and I can't find a way to do it.
P.S. I can not use the string library
The traditional way to do this is to loop through each character in a char array and keeping track of the number of characters until you hit a newline, depending on the format of the data.
#include <iostream>
using namespace std;
int main()
{
char arr[] = "00000000100000001010\n00000000010000001001\n11100000010100000010\n10100100101010101010 \n00101010010010101000";
int cols = 0;
int rows = 0;
for(int i = 0; arr[i] != '\0';i++)
{
if(rows == 0)
cols++;
if(arr[i] == '\n')
rows++;
}
std::cout<<cols<<" Colums"<<std::endl<<rows+1<<" Rows"<<std::endl;
return 0;
}
This is assuming that the columns are uniform and you have your data in an array.
It's much easier/cleaner/better to read in character by character from a stream, but this is the old way.
There are many ways to proceed, depending on what the motivation was behind your teacher's prohibition on using string. One of the two options below will probably be acceptable. Note that I've played a little fast and loose and skipped a fair amount of error checking, but you shouldn't when you flesh it out. In all cases, I'm assuming the file does not end in a line terminator (as you've shown) and is rectangular (same number of characters on every line).
Use an automatically resizing container
You can still get the essential benefit (for this case) of free memory management without using a string. For example, push the characters one-by-one into a vector:
std::ifstream inF("input.txt");
std::vector<char> contents;
char c;
while(inF.get(c).good())
{
contents.push_back(c);
}
int rows = 1 + std::count(contents.begin(), contents.end(), '\n');
int columns = std::find(contents.begin(), contents.end(), '\n') - contents.begin();
Read out the length of the file from the stream
It's a pretty simple matter to figure out how big the file is and pre-allocate a buffer large enough to hold it:
std::ifstream inF("input.txt");
// option 1
inF.seekg(0, std::ios_base::end);
int charCount = inF.tellg();
// option 2
//int charCount = 0;
//while(inF.get() != std::char_traits<char>::eof())
//{
// charCount++;
//}
//inF.clear();
char* contents = new char[charCount + 1];
inF.seekg(0);
inF.read(contents, charCount);
contents[charCount] = '\0';
int rows = 1 + std::count(contents, contents + charCount, '\n');
int columns = std::find(contents, contents + charCount, '\n') - contents;
delete[] contents;
I use Code::Blocks on Windows 7 to make little .exe from .cpp files, and I am a beginner (sorry!)
Here's today's problem:
I have a .csv file containing long integers (from 0 to 2^16) separated by semicolons and listed as a series of horizontal lines.
I will make a simple example here, but in reality the file can be up to 2Go big.
Let's say my file wall.csv appears like this in a text editor such as Notepad++:
350;3240;2292;33364;3206;266;290
362;314;244;2726;24342;2362;310
392;326;248;2546;2438;228;314
378;334;274;2842;308;3232;356
Strangely enough, it appears like this in the windows notepad
350;3240;2292;33364;3206;266;290
362;314;244;2726;24342;2362;310
392;326;248;2546;2438;228;314
378;334;274;2842;308;3232;356
Anyway,
let's say that I will know and will declare in 3 float variables the amount of columns, the amount of lines, and a value from the file.
int col = 7; // amount of columns
int lines = 4; // amount of lines
float x = 0; // a variable that will contain a value from the file
I want:
to create a vector <float> myValues
do myValues.push_back(x) with each value from the 1st line of the csv
do myValues.push_back(x) with each value from the 2nd line of the csv
do myValues.push_back(x) with each value from the 3rd line ...etc.
until the file has been entirely stored in the vector myValues.
My problem:
I don't know how to successively assign to the variable x the values present in the csv file.
How should I do that?
OK this code works (rather slowly but ok!):
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
int col = 1221; // amount of columns
int lines = 914; // amount of lines
int x = 0; // a variable that will contain a value from the file
vector <int> myValues;
int main() {
ifstream ifs ("walls.tif.csv");
char dummy;
for (int i = 0; i < lines; ++i){
for (int i = 0; i < col; ++i){
ifs >> x;
myValues.push_back(x);
// So the dummy won't eat digits
if (i < (col - 1))
ifs >> dummy;
}
}
float A = 0;
float B = col*lines;
for (size_t i = 0; i < myValues.size(); ++i){
float C = 100*(A/B);
A++;
// display progress and successive x values
cout << C << "% accomplished, pix = " << myValues[i] <<endl;
}
}
Put the text data into a stringstream and use std::getline.
It takes an optional third parameter which is the "end-of-line" character, but you can use ; instead of a real end of line.
Call
while (std::getline(ss, str, ';')) {..}
and each loop puts the text in std::string.
Then you will need to convert to a number data type and push into a vector but this will get you started.
Also, why do you use floats for the number of columns and lines?
They are integer values.
Try using the C++ Standard Template Library's input operations.
Make a dummy character variable to eat up semicolons, then cin numbers into your x variable like so:
char dummy;
for (int i = 0; i < lines; ++i){
for (int i = 0; i < col; ++i){
cin >> x;
myValues.push_back(x);
// So the dummy won't eat digits
if (i < (col - 1))
cin >> dummy;
}
}
To do it this way, you can redirect your csv file to be input from the command line like so:
yourExecutable.exe < yourFile.csv
To loop through a vector that is filled with data:
for (size_t i = 0; i < myVector.size(); ++i){
cout << myVector[i];
}
Above, the size_t type is defined by the STL library and is used to suppress an error.
If you want to use the values only once, removing them from the container as they are used, you're better off using the std::queue container. This way, you look at the front element using front() and remove it using pop().