Array/File Functions

Sep 29, 2019 at 4:09pm
Write a function named arrayToFile . The function should accept three arguments: the name of a file, a pointer to an int array, and the size of the array. The function should open the specified file in binary mode, write the contents of the array to the file, and then close the file.

Write another function named fileToArray . This function should accept three arguments: the name of a file, a pointer to an int array, and the size of the array. The function should open the specified file in binary mode, read its contents into the array, and then close the file.

Need help please..


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
 void arraytofile(string str, int *ptr, int size)
{
	fstream file;
	file.open("str", ios::out | ios::binary);
	if(file.fail())
	{
		cout<<"file opening failed"<<endl;
	}
	
	file.clear();
	file.seekg(0);
	for(int i=0; i<size; i++)
	{
		file.write(reinterpret_cast<char *>(ptr[i]), sizeof(ptr));
	}
	
	file.close();
}

void filetoarray(string str, int *ptr, int size)
{
	fstream file;
	file.open("str", ios::in | ios::binary);
	if(file.fail())
	{
		cout<<"file is not opened"<<endl;
	}
	
	for(int i=0; i<size; i++)
	{
		file.read(reinterpret_cast<char *>(ptr), sizeof(ptr));
	}
	file.close();
}


int main()
{
	int size=5;
	int array[size]= {'1','2','3','4','5'};
	int *intptr=NULL;
	intptr=array;
	string str;
	cout<<"enter the name of the file"<<endl;
	cin>>str;
	
	arraytofile(str, intptr, size);
	
	cout<<"data is written into file"<<endl;
	
	int array2[size];
	int *secptr=NULL;
	secptr=array2;
	
	filetoarray(str, secptr, size);
	cout<<"data is in array"<<endl;
}
Sep 29, 2019 at 4:12pm
file.open(str, ios::out | ios::binary);

No quotes surrounding the file name string, you are trying to open a file named "str"
Sep 29, 2019 at 5:09pm
You didn't say what problems you were having, but after adding the appropriate header files and some whitespace to make reading easier I was able to figure out what was going wrong.

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
#include <fstream>
#include <string>
#include <iostream>

void arraytofile(std::string str, char* ptr, int size)
{
   std::fstream file(str, std::ios::out | std::ios::binary);

   if (!file.is_open())
   {
      std::cout << "file opening failed!!!!\n";

      // if the file failed to open do NOT continue trying to use it!
      return;
   }

   for (int loop { }; loop < size; loop++)
   {
      file.write(reinterpret_cast<char*>(&ptr[loop]), sizeof(char));
   }
}

void filetoarray(std::string str, char* ptr, int size)
{
   std::fstream file(str, std::ios::in | std::ios::binary);

   if (!file.is_open())
   {
      std::cout << "file is not opened!!!!!\n";
      return;
   }

   for (int loop { }; loop < size; loop++)
   {
      file.read(reinterpret_cast<char*>(&ptr[loop]), sizeof(char));
   }
}


int main()
{
   const int size = 5;

   char array[size] = { '1','2','3','4','5' };
   char* intptr = array;

   std::string str;

   std::cout << "enter the name of the file: ";
   std::cin >> str;
   std::cout << '\n';


   std::cout << "data is written to the file\n\n";
   arraytofile(str, intptr, size);

   char array2[size];
   char* secptr = array2;

   filetoarray(str, secptr, size);

   std::cout << "Data in the file:\n";

   for (int loop { }; loop < size; loop++)
   {
      std::cout << secptr[loop] << ' ';
   }
   std::cout << '\n';
}

enter the name of the file: test.txt

data is written to the file

Data in the file:
1 2 3 4 5

You mixed up using your arrays as if it an array of ints and an array of chars. Since you initialized the first array with char values every usage of it became a char array or char* pointer.

Using binary format for simple data types is a bit of overkill. It works best with complex data types, for example a class:
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
#include <fstream>
#include <iomanip>
#include <string>
#include <iostream>

class Human
{
public:
   Human() : Name(""), DOB(""), Age(0) { }
   Human(std::string inName, std::string inDOB, unsigned short inAge)
      : Name(inName), DOB(inDOB), Age(inAge) { }

public:
   std::string    Name;
   std::string    DOB;
   unsigned short Age;
};


int main()
{
   Human Input("Joe Schmuckatelli", "May 1956", 61);

   std::ofstream fsOut("MyBinary.txt", std::ios_base::out | std::ios_base::binary);

   if (!fsOut.is_open())
   {
      std::cout << "Unable to open file for writing!!!!!\n";
   }
   else
   {
      std::cout << "Writing one object of Human to a binary file\n\n";
      fsOut.write(reinterpret_cast<const char*> (&Input), sizeof(Input));
      fsOut.close();

      std::ifstream fsIn("MyBinary.txt", std::ios_base::in | std::ios_base::binary);

      if (!fsIn.is_open())
      {
         std::cout << "Unable to open file for reading!!!!!\n";
      }
      else
      {
         Human somePerson;
         fsIn.read(reinterpret_cast<char*> (&somePerson), sizeof(somePerson));
         fsIn.close();

         std::cout << "Reading information from binary file:\n";
         std::cout << "Name = " << somePerson.Name << '\n';
         std::cout << "Age  = " << somePerson.Age << '\n';
         std::cout << "DOB  = " << somePerson.DOB << '\n';
      }
   }
}

Writing one object of Human to a binary file

Reading information from binary file:
Name = Joe Schmuckatelli
Age  = 61
DOB  = May 1956
Sep 29, 2019 at 7:54pm
Thank you so much Furry,
You are really master of C++.
it is working well.


I didn't get one thing, why you used char *ptr ... in both functions instead of using int * ptr.
Sep 29, 2019 at 9:42pm
why you used char *ptr ... in both functions instead of using int * ptr.
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>

int main()
{
   // not what you think it is.  '1' = 49!
   int myInt = '1';

   char myChar = '1';

   std::cout << myInt << '\t' << myChar << '\n';
}
49      1


You are really master of C++.

HA-HA-HA-HA-HA-HA! Great joke, there.

Oh, you were serious?

Not even close, really. There are others here who are much better at making C++ dance. I can barely make it shuffle around like a zombie.
Sep 30, 2019 at 2:49pm
HA-HA-HA-HA-HA-HA! Great joke, there.

Oh, you were serious?



Yes, you quite expert. Thank you so much.
Sep 30, 2019 at 3:13pm
If you absolutely must pass your array(s) as int*:

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
#include <fstream>
#include <string>
#include <iostream>

void arraytofile(std::string str, int* ptr, int size)
{
   std::fstream file(str, std::ios::out | std::ios::binary);

   if (!file.is_open())
   {
      std::cout << "file opening failed!!!!\n";

      // if the file failed to open do NOT continue trying to use it!
      return;
   }

   for (int loop { }; loop < size; loop++)
   {
      // notice you are taking the size of the actual data type being written
      // otherwise the alignment is all FUBARed
      file.write(reinterpret_cast<char*>(&ptr[loop]), sizeof(int));  
   }
}

void filetoarray(std::string str, int* ptr, int size)
{
   std::fstream file(str, std::ios::in | std::ios::binary);

   if (!file.is_open())
   {
      std::cout << "file is not opened!!!!!\n";
      return;
   }

   for (int loop { }; loop < size; loop++)
   {
      file.read(reinterpret_cast<char*>(&ptr[loop]), sizeof(int));
   }
}


int main()
{
   const int size = 5;

   int array[size] = { 1, 2, 3, 4, 5 };  // initialize with ints, not chars.
   int* intptr = array;

   std::string str;

   std::cout << "enter the name of the file: ";
   std::cin >> str;
   std::cout << '\n';


   std::cout << "data is written to the file\n\n";
   arraytofile(str, intptr, size);

   int array2[size];
   int* secptr = array2;

   filetoarray(str, secptr, size);

   std::cout << "Data in the file:\n";

   for (int loop { }; loop < size; loop++)
   {
      std::cout << secptr[loop] << ' ';
   }
   std::cout << '\n';
}
Sep 30, 2019 at 3:36pm
Furry Guy wrote:
It works best with complex data types, for example a class:

That actually crashed.

Are you sure that sizeof(somePerson) is legitimate when it contains strings that may be of arbitrary length?
Sep 30, 2019 at 4:10pm
Alright, I got i.

Are you sure that sizeof(somePerson) is legitimate when it contains strings that may be of arbitrary length?


Actually you are right.
sizeof gives actual size of any type of data in bytes whereas get the length of an array of chars/string. It doesn't care about the value of the variable.
Sep 30, 2019 at 4:49pm
Are you sure that sizeof(somePerson) is legitimate when it contains strings that may be of arbitrary length?


VS 2017/2019 and LLVM/GCC (Code::Blocks) don't have problems, exit code 0.

What compiler did you use that has problems?
Sep 30, 2019 at 5:26pm
I used g++.

However, I can't see how it would know how many bytes to read without knowing the length of the strings.
Sep 30, 2019 at 6:00pm
The example code I posted seems to be a "one-off" weird bit of code, that "just worked."

It was a pre-C++11 bit of code.

I was wondering how it was able to process the length of strings back when I first saw the code.

But it worked across multiple compilers, even changing what the strings held so dealt with difference sizes and padding alignments.

It never had problems when I did limited testing, so figured there was some C+++ FM going on I didn't understand.

Other binary file examples I saw use char arrays with fixed sizes, easy to understand why that works.

It has been a while since I looked at that code sample and when I resurrected it the fact it worked fooled me into being complacent. And stupid.

@shoaib yehya,

Still think I'm a master of C++? I told you I wasn't.
Sep 30, 2019 at 6:07pm
It may be that strings start with a minimum capacity (probably different on different systems) and as long as you don't exceed that then things would be "fine".
Sep 30, 2019 at 6:20pm
I did some further testing, and even without changing any of the string data in the class, a recompile with VS and C:B can crash.

Change any of the string data and it is a hit and miss "fall down and go boom" situation.

Most of the times crash, but sometimes it doesn't.

I made a simple, easily preventable, noob mistake; assumed a few test cases that worked meant it was code without problems.

Mea Culpa. And all that jazz.

Learned a couple of lessons today.

I know they won't be the last.
Last edited on Sep 30, 2019 at 6:21pm
Oct 1, 2019 at 2:21pm
Still think I'm a master of C++? I told you I wasn't.


Atleast you are doing better than me.

secondly, what if we use strlen/strin.lenght() function for that ??
It will include NUllpointer as well.
Oct 1, 2019 at 2:21pm
What compiler did you use that has problems?


using old version,
Dev c++.
Oct 1, 2019 at 2:39pm
strlen() does not include the null-terminator, but requires a null-terminator to know when to stop looping.
e.g. { 'h', 'e', 'l', 'l', 'o', '\0' } --> will return 5.

string.length() is not null-terminated (e.g. you can push_back a null character and the length will be incremented).
Oct 1, 2019 at 2:43pm
strlen() does not include the null-terminator, but requires a null-terminator to know when to stop looping.
e.g. { 'h', 'e', 'l', 'l', 'o', '\0' } --> will return 5.



Alright thanks Ganado
Topic archived. No new replies allowed.