File streams work by using a pointer to keep track of where you are within a file.
File streams have different "states". In order for a filestream to work it has to be in the "good" state. If the file pointer reaches EOF (End Of File) it causes the file stream to go into a failed state until you replace the pointer to point somehere within the file again. You can specify where you want the file pointer to go, or you can close the stream (you may have to "clear" the state before you can close it) and reopen it, in which case the pointer will be repositioned back at the begining of the file again.
You have to pass streams by reference meaning whatever state they end up with in one function will persist in the calling function and will be passed to the next called function.
In your case countChar stops when it attempts to read one more time after finding EOF. But at that point, having found EOF, it is in a failed state when it returns to main() and remains in a failed state when you try to use it in countWords. You have to get it out of the failed state to use it again.
Also, you have to be careful when using the return value of eof() to control a loop in order to avoid a potential bug. In your case your loops are apt to "attempt" to go through the body of the loop one too many times, and may well end up counting one too many char or words. If that happens, then use fin >> c or fin >> s as the loop conditional instead of using fin.gets() within the body loop. If you want to be sure you've read the entire file, then call eof() after completing the loop.