Evolution.
Implementation of your homework with pointer to first character of 2d array
#include <iostream>
#include <fstream>
#define MAX_NUMBER_FRIENDS 30
#define MAX_NAME_LENGTH 50
int readFromFile(char *dataPointer)
{
int count = 0;
std::ifstream infile;
infile.open("r:\\friends.txt");
if (infile.fail())
{
std::cout << "\nError opening file!\n";
}
else
{
std::cout << "Reading from the file.";
do
{
infile.getline(dataPointer, MAX_NAME_LENGTH);
if (not infile.fail()) {
count++;
dataPointer += MAX_NAME_LENGTH;
}
} while ((not infile.fail()) and (count < MAX_NUMBER_FRIENDS));
infile.close();
std::cout << "\nDone!\n";
}
return count;
}
void displayData(char* dataPointer, int count) {
std::cout << "\nContent of the array\n";
for (int i = 0; i < count; ++i) {
std::cout << dataPointer << '\n';
dataPointer += MAX_NAME_LENGTH;
}
std::cout << '\n';
}
int main() {
char arrFriends[MAX_NUMBER_FRIENDS][MAX_NAME_LENGTH];
char* arrFriendsPointer = &arrFriends[0][0];
int numberOfNames = readFromFile(arrFriendsPointer);
displayData(arrFriendsPointer, numberOfNames);
}
Next, with comments. Looks immediately better:
#include <iostream>
#include <fstream>
// Compile Time Specification: Numbers are not magic, but given by requirement
// This will define the number of the elements in the friends array
#define MAX_NUMBER_FRIENDS 30
// This is the maximum length of the name
#define MAX_NAME_LENGTH 50
// Read a a list of names from a file and store it in a given array
int readFromFile(char* dataPointer) {
// We will count the number of names in the file and return this info to the caller of this function
int nameCount = 0;
// Open the input text file with names
std::ifstream nameFileStream;
nameFileStream.open("r:\\friends.txt");
// Check, if the file could be opened and that there is no failure
if (nameFileStream.fail()) {
// Error. There was a failure. File could not be opened
std::cout << "\nError opening file!\n";
}
else
{
// File could be opened. Give status message
std::cout << "Reading from the file.";
do
{
// Read one name from the file. Protect from out of bound error
nameFileStream.getline(dataPointer, MAX_NAME_LENGTH);
// Check, if the name could be read, or, if there was a failure
if (not nameFileStream.fail()) {
// Name could be successfully read. Increase name counter
nameCount++;
// And point to the next row in the 2d array
dataPointer += MAX_NAME_LENGTH;
}
// Loop end condition will check for stream failure or too many names
} while ((not nameFileStream.fail()) and (nameCount < MAX_NUMBER_FRIENDS));
// Close the file at the end
nameFileStream.close();
// Final status message
std::cout << "\nDone!\n";
}
return nameCount;
}
// Display the data
void displayData(char* dataPointer, int count) {
// Give user information
std::cout << "\nContent of the array\n";
// In a loop, show all names
for (int i = 0; i < count; ++i) {
// Output name
std::cout << dataPointer << '\n';
// Set pointer to next row in 2d array
dataPointer += MAX_NAME_LENGTH;
}
std::cout << '\n';
}
int main() {
// Define a 2 dimensional array to hold a number of name strings
char arrFriends[MAX_NUMBER_FRIENDS][MAX_NAME_LENGTH];
// This is a pointer to the first character in the 2d array
char* arrFriendsPointer = &arrFriends[0][0];
// Read and show data
int numberOfNames = readFromFile(arrFriendsPointer);
displayData(arrFriendsPointer, numberOfNames);
}
Now, with a pointer to the first row of the 2d array. And some further improvements
#include <iostream>
#include <fstream>
// Compile Time Specification: Numbers are not magic, but given by requirement
// This will define the number of the elements in the friends array
constexpr unsigned int MaxNumberFriends = 30;
// This is the maximum length of the name
constexpr unsigned int MaxNameLength = 50;
// Read a a list of names from a file and store it in a given array
unsigned int readFromFile(char (*dataPointer)[MaxNameLength]) {
// We will count the number of names in the file and return this info to the caller of this function
unsigned int nameCount{};
// Open the input text file with names
std::ifstream nameFileStream{ "r:\\friends.txt"};
// Check, if the file could be opened and that there is no failure
if (nameFileStream.fail()) {
// Error. There was a failure. File could not be opened
std::cout << "\nError opening file!\n";
}
else {
// File could be opened. Give status message
std::cout << "Reading from the file.";
do {
// Read one name from the file. Protect from out of bound error
nameFileStream.getline(dataPointer[nameCount], MaxNameLength);
// Check, if the name could be read, or, if there was a failure
if (not nameFileStream.fail()) {
// Name could be successfully read. Increase name counter
nameCount++;
}
// Loop end condition will check for stream failure or too many names
} while ((not nameFileStream.fail()) and (nameCount < MaxNumberFriends));
// Final status message
std::cout << "\nDone!\n";
}
return nameCount;
}
// Display the data
void displayData(char(*dataPointer)[MaxNameLength], int count) {
// Give user information
std::cout << "\nContent of the array\n";
// In a loop, show all names
for (int i = 0; i < count; ++i) {
// Output name
std::cout << dataPointer[i] << '\n';
}
std::cout << '\n';
}
int main() {
// Define a 2 dimensional array to hold a number of name strings
char arrFriends[MaxNumberFriends][MaxNameLength]{};
// This is a pointer to the first row in the 2d array
char(*arrFriendsPointer)[MaxNameLength] {&arrFriends[0]};
// Read and show data
unsigned int numberOfNames = readFromFile(arrFriendsPointer);
displayData(arrFriendsPointer, numberOfNames);
}
And now with a pointer to the complete 2d array. And some further improvements . . .
#include <iostream>
#include <fstream>
// Compile Time Specification: Numbers are not magic, but given by requirement
// This will define the number of the elements in the friends array
constexpr unsigned int MaxNumberFriends = 30;
// This is the maximum length of the name
constexpr unsigned int MaxNameLength = 50;
// Read a a list of names from a file and store it in a given array
unsigned int readFromFile(char (*dataPointer)[MaxNumberFriends][MaxNameLength]) {
// We will count the number of names in the file and return this info to the caller of this function
unsigned int nameCount{};
// Open the input text file with names
std::ifstream nameFileStream{ "r:\\friends.txt" };
// Check, if the file could be opened and that there is no failure
if (nameFileStream.fail()) {
// Error. There was a failure. File could not be opened
std::cout << "\nError opening file!\n";
}
else {
// File could be opened. Give status message
std::cout << "Reading from the file.";
do {
// Read one name from the file. Protect from out of bound error
nameFileStream.getline((*dataPointer)[nameCount], MaxNameLength);
// Check, if the name could be read, or, if there was a failure
if (not nameFileStream.fail()) {
// Name could be successfully read. Increase name counter
nameCount++;
}
// Loop end condition will check for stream failure or too many names
} while ((not nameFileStream.fail()) and (nameCount < MaxNumberFriends));
// Final status message
std::cout << "\nDone!\n";
}
return nameCount;
}
// Display the data
void displayData(char(*dataPointer)[MaxNumberFriends][MaxNameLength], int count) {
// Give user information
std::cout << "\nContent of the array\n";
// In a loop, show all names
for (int i = 0; i < count; ++i) {
// Output name
std::cout << (*dataPointer)[i] << '\n';
}
std::cout << '\n';
}
int main() {
// Define a 2 dimensional array to hold a number of name strings
char arrFriends[MaxNumberFriends][MaxNameLength]{};
// This is a pointer to the 2d array
char (* arrFriendsPointer)[MaxNumberFriends][MaxNameLength] = &arrFriends;
//Read and show data
unsigned int numberOfNames = readFromFile(arrFriendsPointer);
displayData(arrFriendsPointer, numberOfNames);
}
A little bit more C++
#include <iostream>
#include <fstream>
// Compile Time Specification: Numbers are not magic, but given by requirement
// This will define the number of the elements in the friends array
constexpr unsigned int MaxNumberFriends{ 30u };
// This is the maximum length of the name
constexpr unsigned int MaxNameLength{ 50u };
// Defining types
using Array2d = char[MaxNumberFriends][MaxNameLength];
using Array2dPtr = Array2d*;
// Read a a list of names from a file and store it in a given array
size_t readFromFile(Array2dPtr dataPointer) {
// We will count the number of names in the file and return this info to the caller of this function
size_t nameCount{};
// Open the input text file with names and check, if it could be opened
if (std::ifstream nameFileStream{ "r:\\friends.txt" }; nameFileStream) {
// File could be opened. Give status message
std::cout << "Reading from the file.";
do {
// Read one name from the file. Protect from out of bound error
nameFileStream.getline((*dataPointer)[nameCount], MaxNameLength);
// Check, if the name could be read, or, if there was a failure
if (not nameFileStream.fail()) ++nameCount;
// Loop end condition will check for stream failure or too many names
} while ((not nameFileStream.fail()) and (nameCount < MaxNumberFriends));
// Final status message
std::cout << "\nDone!\n";
}
else std::cerr << "\n*** Error: File could not be opened.\n";
return nameCount;
}
// Display the data
void displayData(Array2dPtr dataPointer, size_t count) {
// Give user information
std::cout << "\nContent of the array\n";
// In a loop, show all names
for (size_t i{}; i < count; ++i)
std::cout << (*dataPointer)[i] << '\n';
std::cout << '\n';
}
int main() {
// Define a 2 dimensional array to hold a number of name strings
Array2d arrFriends{};
// This is a pointer to the 2d array
Array2dPtr arrFriendsPointer{ &arrFriends};
//Read and show data
size_t numberOfNames = readFromFile(arrFriendsPointer);
displayData(arrFriendsPointer, numberOfNames);
}
And, at the end, one of many full blown C++ solutions:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <iterator>
struct Names {
std::vector<std::string> names{};
size_t count() const { return names.size(); }
// Define simple extractor
friend std::istream& operator >> (std::istream& is, Names& n) {
n.names.clear();
for (std::string line{}; std::getline(is, line); n.names.push_back(line));
return is;
}
// Define simple inserter
friend std::ostream& operator << (std::ostream& os, const Names& n) {
std::copy(n.names.begin(), n.names.end(), std::ostream_iterator< std::string>(os, "\n"));
return os;
}
};
size_t readFromFile(Names& names) {
// Open the input text file with names and check, if it could be opened
if (std::ifstream nameFileStream{ "r:\\friends.txt" }; nameFileStream)
// Rad everything with one simple statement
nameFileStream >> names;
else std::cerr << "\n*** Error: File could not be opened.\n";
// Return number of elements
return names.count();
}
int main() {
Names names{};
size_t numberOfNames = readFromFile(names);
std::cout << "\nNumber of names read: " << numberOfNames << "\n\n" << names << '\n';
}
Or, using a line proxy . . .
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
class CompleteLine { // Proxy for the input Iterator
public:
// Overload extractor. Read a complete line
friend std::istream& operator>>(std::istream& is, CompleteLine& cl) { std::getline(is, cl.completeLine); return is; }
// Cast the type 'CompleteLine' to std::string
operator std::string() const { return completeLine; }
protected:
// Temporary to hold the read string
std::string completeLine{};
};
// Solution
int main() {
// Open the input text file with names and check, if it could be opened
if (std::ifstream nameFileStream{ "r:\\friends.txt" }; nameFileStream) {
// Read the complete file
std::vector names{ std::istream_iterator<CompleteLine>(nameFileStream),{} };
// Show user output and list up the names
if (not names.empty()) std::cout << "\nReading Data from file\nDone\n\n";
std::copy(names.begin(), names.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
}
else std::cerr << "\n*** Error: File could not be opened.\n";
}
Have fun . . .
std::getlineandstd::vector<std::string>to read all lines? Secondly always consider a loop likewhile (!infile.eof())as wrong.while (!eof)problem, when reading you need 1) read the data, 2) test that you read the data, and 3) use the data or handle the error depending on the results of 2). If you use any other order, you have a bug. In thewhile (!eof), the test for a successful data read is performed BEFORE the read where it is almost completely worthless.