No Matching Function to Call Error

closed account (9hX8C542)
So I have a homework assignment that requires me to read from an input file, store it into arrays, then process that data, and export to an output file using command line.

The problem is that I always get a no matching function to call error. This happens very often for me, especially on recent assignments.

If someone could help me solve this, and tell me why it happened, and the rule behind it, that would help tremendously.

Sorry if my code has more problems, or the answer is really easy. But I appreciate all the help I receive. Thank You for your time.

Error:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
cs135pa08B.cpp:52:5: error: no matching function for call to 'readData'
    readData(fileName, pNames[MAXPLAYERS], batting[MAXPLAYERS],
    ^~~~~~~~
cs135pa08B.cpp:21:6: note: candidate function not viable: no known conversion from
      '__gnu_cxx::__alloc_traits<std::allocator<char> >::value_type' (aka 'char')
      to 'std::__cxx11::string *' (aka 'basic_string<char> *') for 2nd argument
void readData(string x, string[], double[MAXPLAYERS], int a, int[MAXPLAYERS],
     ^
cs135pa08B.cpp:55:5: error: no matching function for call to 'processData'
    processData(batting[MAXPLAYERS], homeRun[MAXPLAYERS],
    ^~~~~~~~~~~
cs135pa08B.cpp:23:6: note: candidate function not viable: no known conversion from
      'double' to 'double *' for 1st argument; take the address of the argument
      with &
void processData(double[MAXPLAYERS], int[MAXPLAYERS], int[MAXPLAYERS],
     ^
cs135pa08B.cpp:58:5: error: no matching function for call to 'writeData'
    writeData(outFile, teamName, year, teamStats[MAXSTATS], numStats);
    ^~~~~~~~~
cs135pa08B.cpp:25:6: note: candidate function not viable: no known conversion from
      'double' to 'double *' for 4th argument; take the address of the argument
      with &
void writeData(string f, string t, int y, double[MAXSTATS], int numStats);


My Code:
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <iostream>
#include <string>
#include <iomanip>
#include <cassert>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <stdlib.h>
#include <stdio.h>
#include <cstring>

using namespace std;

//Constants
const int MAXPLAYERS = 20;
const int MAXSTATS = 4;

//Function Prototypes
void readData(string x, string[], double[MAXPLAYERS], int a, int[MAXPLAYERS],
              int[MAXPLAYERS], int[MAXPLAYERS], int y, string b);
void processData(double[MAXPLAYERS], int[MAXPLAYERS], int[MAXPLAYERS],
                 int[MAXPLAYERS], int z, double[MAXSTATS]);
void writeData(string f, string t, int y, double[MAXSTATS], int numStats);


int main(int argc, char* argv[])
{
    string pNames;
    double batting[MAXPLAYERS];
    int homeRun[MAXPLAYERS];
    int strikeOut[MAXPLAYERS];
    int year;
    int pWalk[MAXPLAYERS];
    int totalPlayers;
    string teamName;
    double teamStats[MAXSTATS];
    int numStats = 4;

    if (argc > 3 || argc < 3)
    {
        cout << "Error: Specify the file name as a command line argument."
             << endl
             << "For example: ./a.out file1.txt file2.txt";
        return 1;
    }//check to see if there is 2 arguments in the command line input

    string fileName = argv[1];
    string outFile = argv[2];

    readData(fileName, pNames[MAXPLAYERS], batting[MAXPLAYERS],
             homeRun[MAXPLAYERS], strikeOut[MAXPLAYERS], year,
             pWalk[MAXPLAYERS], totalPlayers, teamName);
    processData(batting[MAXPLAYERS], homeRun[MAXPLAYERS],
                strikeOut[MAXPLAYERS], pWalk[MAXPLAYERS],
                totalPlayers, teamStats[MAXSTATS]);
    writeData(outFile, teamName, year, teamStats[MAXSTATS], numStats);

}//main

void readData(string fileName, string pNames[MAXPLAYERS],
              double batting[MAXPLAYERS], int year,
              int homeRun[MAXPLAYERS], int strikeOut[MAXPLAYERS],
              int pWalk[MAXPLAYERS], int totalPlayers, string teamName)
{
    ifstream inData;
    inData.open(fileName.c_str());

    while (!inData.eof())
    {
        inData >> teamName;
        inData >> year;
        inData >> totalPlayers;

        for(int i = 0; i < totalPlayers; i++)
        {
            inData >> pNames[i]
                   >> batting[i]
                   >> homeRun[i]
                   >> strikeOut[i]
                   >> pWalk[i];
        }//for loop to store data

    }//while loop for file

    inData.close();
}//function read data


void processData(double batting[MAXPLAYERS], int homeRun[MAXPLAYERS],
                 int strikeOut[MAXPLAYERS], int pWalk[MAXPLAYERS],
                 int totalPlayers, double totalStats[MAXSTATS])
{
    int avgBat = 0;
    int totalHomeRuns = 0;
    int totalStrikeOuts = 0;
    int totalWalks = 0;

    for (int i = 0; i < totalPlayers; i++)
    {
        avgBat += batting[i];
        totalHomeRuns += homeRun[i];
        totalStrikeOuts += strikeOut[i];
        totalWalks += pWalk[i];
    }//for loop for calculating sums

    avgBat = avgBat / totalPlayers;

    totalStats[0] = avgBat;
    totalStats[1] = totalHomeRuns;
    totalStats[2] = totalStrikeOuts;
    totalStats[3] = totalWalks;
}//function process data

void writeData(string fileName, string teamName, int year,
               double totalStats[MAXSTATS], int numStats)
{
    ofstream outData;
    outData.open(fileName.c_str(), ios_base::app);

    outData << teamName << " " << year << " ";

    for (int i = 0; i < numStats; i++)
    {
        outData << totalStats[i] << " ";
    }//for loop to output total stats into file

    outData.close();

}//writeData 
Hello zzknight,

The short answer is that the prototype, function definition and function all must match in the type of variables and the order.

The function is expecting a string 2 arrays then the int year, but the function call is sending a string 4 arrays then the int year. see a problem here?

You could start with coping line 60 and paste it for the prototype. Then adjust the function call to use the same variables in the same order.

That is a good start while I look into the other errors.

Hope that helps,

Andy
Haven’t your teacher told you about struct, yet?
1
2
3
4
5
6
7
    readData(fileName, pNames[MAXPLAYERS], batting[MAXPLAYERS],
             homeRun[MAXPLAYERS], strikeOut[MAXPLAYERS], year,
             pWalk[MAXPLAYERS], totalPlayers, teamName);
    processData(batting[MAXPLAYERS], homeRun[MAXPLAYERS],
                strikeOut[MAXPLAYERS], pWalk[MAXPLAYERS],
                totalPlayers, teamStats[MAXSTATS]);
    writeData(outFile, teamName, year, teamStats[MAXSTATS], numStats);

When you call a function expecting an array parameter, you just pass the array name.
Specifying an index just makes that an element of the array.
Specifying that index as the array size is an out of bounds memory access before you've even begun.

1
2
3
4
5
6
7
    readData(fileName, pNames, batting,
             homeRun, strikeOut, year,
             pWalk, totalPlayers, teamName);
    processData(batting, homeRun,
                strikeOut, pWalk,
                totalPlayers, teamStats);
    writeData(outFile, teamName, year, teamStats, numStats);

Hello zzknight,

First your program uses an input file. Where is it? It helps when everyone uses the same information.

Along with Enoizat's question have you learned about functions?

http://www.cplusplus.com/doc/tutorial/functions/
http://www.cplusplus.com/doc/tutorial/structures/

As I said earlier the prototype, function definition and function call all must math as to the number of parameters and their order. The function call is different only in you just need the variable name.

In "main" if (argc > 3 || argc < 3) could easily be said as if (argc != 3). But your example
"For example: ./a.out file1.txt file2.txt" suggests there are three plus the file name of the program, but are you counting "argv[0]", (the file name of the program), as one? Based on my interpretation of the example "argc" should be four. Or you need to revise the example. It would also help to see what the command line actually looks like.

In the function "readData(...)", what is line 60 in your above code,:

When you open the file stream inData.open(fileName.c_str()); from C++11 on a "std::string" will work. You do not have to convert it to a C string. I do not know what IDE or compiler you are using, but if you have to use ".cstr()" then you should look int updating the IDE/compiler or adjust the IDE to use the C++11 standards. It is a big help.

When you open a file for input it is best to check that the file is open. I tend to use this:
1
2
3
4
5
6
7
8
9
10
//const std::string inFileName{ "" };  // <--- Commented because the first parameter of the function is used. I changed that name to match here.

std::ifstream inFile(inFileName);

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".
	/*return 1;*/  exit(1);  // If not in "main".
}


Next is the while loop. Checking while (!inData.eof()) does not work the way you are thinking. By the time the while condition figures that you have reached end of file you will have processed your last read twice.

The most often way to read a file is: while(inData >> teamName). This way when you try to read past "eof" the stream fails and so does the while loop.

An alternative would be:
1
2
3
4
5
6
7
8
9
10
inData >> teamName;
while (!inData.eof())
{
    inData >> year;
    inData >> totalPlayers;

    // <--- Rest of code.

   inData >> teamName;
}  // End of while loop. 

By reading "teamName" at the end of the while loop if "eof" is set the while condition will work properly. I suggest:
1
2
3
4
5
6
7
while(inData >> teamName)
{
	inData >> year;
	inData >> totalPlayers;

        // <--- Rest of code.
}


The next problem I see deals with "year" and "totalPlayers". These are single variables passed to the function and this creates two problems. First the variables are passed by value, i.e., just a copy, and second when the function ends so do these local variables. So whatever you put in these variables do not make it back to main. Even if it did it would only contain information from the last read.

The variables "year" and "totalPlayers" should be an array or as Enoizat kind of suggests put in a struct.

By using a struct you could have only one array or better a vector of these structs where each element holds complete information of one record.

Right now without knowing what is in the input file I am stuck not able to go much farther without any good information to work with.

Looking back I have the feeling that for(int i = 0; i < totalPlayers; i++) may not work. With i < totalPlayers what happens if you only have say 10 players?

In working with your code I noticed that none of the variables in "main" are initialized. This will be a problem later when you try to use one or more of these uninitialized variables in another function.

From C++11 on it is easy to initialize a variable with an empty set of {}s as:
1
2
int strikeOut[MAXPLAYERS]{};
int year{};

The empty {}s will initialize each element of the arrays to zero and "year" to zero. This will give you the knowledge that the variables contain something other than garbage. And yes you can put a number between the {}s if you need something other than zero.

Also your arrays have a size of "MAXPLAYERS" which is fine, but what happens if you do not use all 20 elements of your array? You need a way to keep track of how much of the array is used. A vector would not have this problem.

Hope that helps,

Andy
Topic archived. No new replies allowed.