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 . . .