C++ Reading data by character from txt

250 250
14 190 87 164 180 175 195 185 176 154
14 169 205 252 178 184 169 92 166 180
14 187 175 192 185 178 180 175 176 224


Hello friends, I have a txt file as in the image. The first line 250 250 section shows the size of the array that I will dynamically create, others show their values corresponding to the row and column. As a result, how can I assign this data to this array in integer type. Although I did a lot of research on the file, I could not come to a conclusion. I'm waiting for your help .
Last edited on
Hello faruk61,

It best to start with any code that you do have. This way someone can see if you are on the right path or is something needs changed.

If the first line is the size of the array I would change ti to maybe 5 and 15 until you get the program working.

There are at least 2 way and maybe more that you could do this. First you could read the file into a number then assign it to the array. Second you coulld read directly into the array.

Either way first you deal with the first line to create your array then a nested for loop to deal with the rest of the numbers.

Without seeing what you have done I do not know what needs fixed and I have no idea what you have learned to this point.

Note: When you use "new" there must be a matching "delete" used when you are finished with the array otherwise you create a memory leak that could remain after the program closes.

Andy
Do you have to use a dynamic array or could you use nested vectors ?

In both cases you need to read first the number of rows and columns.
Then you create your array or vectors.
Then you use 2 nested loops to read the data.
Outer loop reads the rows and the inner loops reads the columns.
Hello faruk61,

First off I changed the input to:

5 15
14 190 87 164 180 175 195 185 176 154
14 169 205 252 178 184 169 92 166 180
14 187 175 192 185 178 180 175 176 224


The 5 and 15 is used to get the program working because there is no need for all the wasted space right now.

Learner2 is correct in the 2 nested for loops can be used to read the file, but this did not turn out as easy as I first thought.

The problem is that you do not have 250 rows and 250 columns worth of data to input. So you need to account for how many lines are read and how many columns are read. Should any row very in the number of columns this would create a new problem.

The following code shows what I came up with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <iostream>
#include <iomanip>
#include <limits>
#include <string>

#include <fstream>
#include <sstream>

int main()
{
	int** numArr{ nullptr };
	int maxRows{}, maxCols{}, rowsRead{}, colsRead{};
	std::string line;

	const std::string inFileName{ "Data.txt" };

	std::ifstream inFile(inFileName);

	// <--- Check that the open worked and the stream is usable.
	if (!inFile)
	{
		std::cout << "\n File " << std::quoted(inFileName) << " did not open" << std::endl;
		//std::this_thread::sleep_for(std::chrono::seconds(3));  // <--- Needs header files chrono" and "thread". Optional.

		return 1;
	}

	// <--- Read Row and column for size of array.
	inFile >> maxRows >> maxCols;
	inFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
                                                                           // Clear the "\n" after the last read.

	// <--- Create dynamic array.
	numArr = new int*[maxRows];

	for (int row = 0; row < maxRows; row++)
		numArr[row] = new int[maxCols];

	// <--- Read file into array.
	for (rowsRead = 0; std::getline(inFile, line) && rowsRead < maxRows; rowsRead++)
	{
		std::istringstream iss(line);
		
		colsRead = 0;

		for (int col = 0; iss >> numArr[rowsRead][col]; col++)
			colsRead++;

	}

	// <--- Print array. Mainly used for testing for now.
        // <--- Prints only the part of the array used.
	for (int row = 0; row < rowsRead; row++)
	{
		for (int col = 0; col < colsRead; col++)
		{
			std::cout << std::setw(4) << numArr[row][col] << (col < colsRead - 1 ? ", " : "\n");
		}

		std::cout << '\n';
	}

	// <--- Delete dynamic array.
	for (int i = 0; i < rowsRead; i++)
	{
		delete[] numArr[i];
	};

	delete[] numArr;

	// <--- Keeps console window open when running in debug mode on Visual Studio. Or a good way to pause the program.
	// The next line may not be needed. If you have to press enter to see the prompt it is not needed.
	//std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
	std::cout << "\n\n Press Enter to continue: ";
	std::cin.get();

	return 0;  // <--- Not required, but makes a good break point.
}


Be sure to read the comments in the code.

Andy
Let me tell you this. This is a 250 * 250 two-dimensional matrix. First of all, I will take this from the txt file at runtime. Then I will create a two-dimensional pointer array and drop them in. Then I will make this 2-dimensional pointer array one-dimensional, make changes to the elements in it and make it 2-dimensional again. As a result, I will do Image Processing using MEDIAN FILTER in C ++. I will turn that matrix I created last into an image jpg.
Last edited on
Remember that the best way to allocate a 2D array is to allocate the data segment contiguously instead of row-by-row. It's easy to do. It's faster and takes up less space. It's more compatible with a built-in 2d array.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <iomanip>

template<typename T>
T** array2d(size_t rows, size_t cols)
{
    T** a = new T*[rows];             // row pointer array
    a[0] = new T[rows * cols] {};     // data array
    for (size_t i = 1; i < rows; ++i) // set the rest of the row pointers
        a[i] = a[i - 1] + cols;
    return a;
}

template<typename T>
void array2d_delete(T**& a)
{
    delete[] a[0];   // delete data array
    delete[] a;      // delete row-pointer array
    a = nullptr;
}

int main()
{
    // Allocate the 2D array.
    const size_t Rows = 5, Cols = 7;
    auto a = array2d<int>(Rows, Cols);

    // Fill data part with consecutive numbers.
    auto b = a[0];
    for (size_t i = 0; i < Rows * Cols; ++i)
        *b++ = i;

    // Print it out.
    for (size_t r = 0; r < Rows; ++r)
    {
        for (size_t c = 0; c < Cols; ++c)
            std::cout << std::setw(3) << a[r][c] << ' ';
        std::cout << '\n';
    }

    // Delete the 2D array.
    array2d_delete(a);
}

Output:
  0   1   2   3   4   5   6 
  7   8   9  10  11  12  13 
 14  15  16  17  18  19  20 
 21  22  23  24  25  26  27 
 28  29  30  31  32  33  34 

Note, however, that it's often better to use a 1D array and access it like a 2D array [row * NumCols + col]. This can be hidden behind a class, if desired. Even the above should really be in a class to encapsulate the number of rows and cols, allow automatic destruction, etc.
Last edited on
Topic archived. No new replies allowed.