need assistance forcing the user to enter the correct input with a cstring

Im trying to preform a do-while loop that forces the user to enter the correct file name using a c-string. but for some reason it works for those that are wrong but it also fails when i enter in the name of the ,txt file. Here is the code>>>>

#include <iostream>
#include <iomanip>
#include <cctype>
#include <cstdlib>
#include <fstream>
#include <cstring>
using namespace std;



int main() {
ifstream input;
input.open("teams1.txt");
char filename[25];

cout << "Please enter the name of the input file." << endl;
cout << "Filename: ";
cin >> filename;
do {
input.clear();
cout << "That is not a valid file. Try again!" << endl;
cout << "Filename: ";
cin >> filename;
} while (filename != "teams1.txt");





return 0;
}
You need to use strcmp() to compare c-strings.
Return value is 0 when strings are the same.
http://www.cplusplus.com/reference/cstring/strcmp/
Last edited on
also im having a lot of trouble adding the opened file to a dynamic array so i can present the different data. it represents the number of teams(which should vary with different file sizes, the team name, wins losses and weather or not they are in the playoffs. Any suggestions?

6
Team A,3,13,0
Team B,15,1,1
team C,9,7,1
Team D,10,6,1
Team E,7,9,0
Team F,11,5,1

#include <iostream>
#include <iomanip>
#include <cctype>
#include <cstdlib>
#include <fstream>
#include <cstring>
using namespace std;

struct TeamList {
char namerino;
int winerino;
int losserino;
bool thePLAYOFFS;
};

int main() {

ifstream input;
char filename[25];

cout << "Please enter the name of the input file." << endl;
cout << "Filename: ";
cin >> filename;
do {
if (strcmp(filename, "game.txt") == 0)
{
break;
}
else
{
input.clear();
cout << "That is not a valid file. Try again!" << endl;
cout << "Filename: ";
cin >> filename;
}
} while (filename != "game.txt");

input.open("game.txt");




return 0;
}
Use std::getline() with ',' as the delimiter.
http://www.cplusplus.com/reference/string/string/getline/
closed account (48T7M4Gy)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

int main() {
    
    char filename[25];
    
    std::cout << "Please enter the name of the input file." << '\n';
    std::cout << "Filename: ";
   
    while(std::cin >> filename and strcmp(filename, "game.txt") != 0)
    {
        std::cout << "That is not a valid file. Try again!" << '\n';
    }
    
    std::cout << "That is a valid file. No need to try again, in fact you can't!" << '\n';
    
    return 0;
}
Something doesn't make much sense.
I don't think you should be comparing the filename entered by the user with some fixed piece of text.

Instead, your program should attempt to open the file which the user specified, if it succeeds, proceed with the rest of the program. Otherwise output an error message and quit.

1
2
3
4
5
6
7
8
9
10
11
12
    char filename[25];

    cout << "Please enter the name of the input file.\nFilename: ";
    cin >> filename;

    ifstream input(filename);
    
    if (!input)
    {
        cout << "Could not open file: " << filename << endl;
        return 1;
    }


if this is the contents of the input file:
6
Team A,3,13,0
Team B,15,1,1
team C,9,7,1
Team D,10,6,1
Team E,7,9,0
Team F,11,5,1


then this struct won't fit the data:
1
2
3
4
5
6
struct TeamList {
char namerino;
int winerino;
int losserino;
bool thePLAYOFFS;
};


"Team A" is a character string containing spaces.
It won't fit inside a single character
char namerino;

First read the int , read/ ignore the newline character.
allocate a dynamic array of TeamList objects.

Repeat that many times:
Reading each line of data will take multiple steps.
1. read the name (and discard the comma) (use getline).
2. read the integer.
3. read/ignore the comma.
4. read the integer.
5. read/ignore the comma.
6. read the bool.
7. check the file status is still ok
8. read/ignore newline character '\n'.

If the input file looked like this, things would be easier:
6
Team-A 3 13 0
Team-B 15 1 1
team-C 9 7 1
Team-D 10 6 1
Team-E 7 9 0
Team-F 11 5 1

(no commas, no need for getline)
Last edited on
closed account (48T7M4Gy)
Something doesn't make much sense.

My thought exactly when I read it. Why not just hard code the file name but 'the customer is always right' ... maybe.
ok what I need to do is open the input file and read the information into an array of TeamList structures and I need to create this array dynamically, because I won't know how many records of teams there are until I start reading the file. So the data from each record in the file should be stored in one TeamList structure but im just confused.
Last edited on
closed account (48T7M4Gy)
Well, why didn't you say that?

But moving on there are a couple of alternatives that spring to mind:
1. Estimate the size of the array.
or 2. Count the number of records by a first reading of the file and allocate the array size dynamically and accordingly.
or 3. Count the records as they originallly go into the file and record/retrieve that number when it is read.
or 4. Reallocate the size of the array as needed.
or 5. Use STL containers - <vectors> etc

Depending on the size of the list I would go for 2.
so with that said would i just need to read the data with getline in retrospect to the number of lines? because with the size of the file, one record will go in one slot of the array
Last edited on
closed account (48T7M4Gy)
I missed it but as Chervil points out the first line of your data file tells you how many records there are. You need to re-read Chervil's comments and apply them.
ohh okay i see now! but the thing is i have read the first integer of the file as the size of the dynamic array so now i just have to store the 1 of the different teams and their data into a single slot of the array

this is what i did:

input >> x;

TeamList * store = new TeamList[x];

for (int i = 0; i < x; i++)
{
input >> i;
}

input.close();
Last edited on
closed account (48T7M4Gy)
That's sort of right and is best viewed as reasonably good pseudocode.

The problem is your data is not very user friendly and because of the commas particularly you will be faced with complicated data manipulation. The sart to that is using getline(). All of this is covered by Chervil in general terms.

Consider carefully modifying the text file. We don't know obviously whteher that's what your teacher wants and you can't change it.

Also, remember that your array will be an array of Teamlist objects, which is what you want.

This tutorial and the sample programs will be very helpful.
http://www.cplusplus.com/doc/tutorial/files/


6
A 3 13 0
B 15 1 1
etc
... would be ideal.
This part is reasonable.
1
2
3
4
5
6
input >> x;

TeamList * store = new TeamList[x];

for (int i = 0; i < x; i++)
{


if you were using an array of simple objects, such as integers, then the body of the loop might simply be
 
    input >> store[i];

(in fact with C++classes you could define an overloaded version of the >> operator so that would work here - but that's moving a bit too fast).

instead of just
 
    input >> store[i]
you'd need something like
 
    input >> store[i].namerino;
which would work if the name was a single character.

But most likely it will need to be a string. Usually I'd recommend C++ std::string, but since you used character arrays earlier, perhaps that's where you've reached so far.
if you define
 
    char namerino[30];

then the code to read the string could look like this:
 
    input.getline(store[i].namerino, sizeof(TeamList::namerino), ',');


And then you'd have to use input >> to read each of the other member variables, bearing in mind that you also need to read and discard the comma separator after winerino and losserino.

A lot of attention to detail is required, this is quite a fussy file layout to be dealing with.


oh okay i see now, but how come i cant use getline for the rest of the member variables?
Getline is for strings. The other variables are int, int, bool.

http://www.cplusplus.com/reference/istream/istream/getline/
okay this really helped thank you very much!
closed account (48T7M4Gy)
A start FWIW
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
#include <iostream>
#include <fstream>
#include <string>

struct Team
{
    std::string name;
    int winner;
    int loser;
    bool thePlayoffs;
};

int main ()
{
    std::string line;
    std::string name;
    std::string winner;
    int win = 0;
    
    size_t position = 0;
    
    size_t no_teams = 0;
    
    std::ifstream myfile ("game.txt");
    if (myfile.is_open())
    {
        // READ ARRAY SIZE & SETUP ARRAY
        myfile >> no_teams;
        std::cout << "No. of teams: " << no_teams << '\n';
        Team *team_list = new Team[no_teams];
        
        // CLEAR STREAM FOR NEXT LINE
        myfile.ignore(1000, '\n');
        
        // READ IN TEAMS
        while(getline (myfile, line))
        {
            // INTERPRET EACH LINE
            
            // NAME
            position = line.find(',');
            name = line.substr(0, position);
            line.erase(0, position + 1);
            std::cout << "Remainder still to be processed " << line << '\n';
            
            // WINNER
            position = line.find(',');
            winner = line.substr(0, position);
            line.erase(0, position + 1);
            std::cout << "Remainder still to be processed " << line << '\n';
            
            win = std::stoi(winner);
            
            std::cout << name << '*' << win << '*' << "\n\n";
        }
        
        myfile.close();
    }
    
    else
        std::cout << "Unable to open file";
    
    return 0;
}
No. of teams: 6
Remainder still to be processed 3,13,0
Remainder still to be processed 13,0
Team A*3*

Remainder still to be processed 15,1,1
Remainder still to be processed 1,1
Team B*15*

Remainder still to be processed 9,7,1
Remainder still to be processed 7,1
team C*9*

Remainder still to be processed 10,6,1
Remainder still to be processed 6,1
Team D*10*

Remainder still to be processed 7,9,0
Remainder still to be processed 9,0
Team E*7*

Remainder still to be processed 11,5,1
Remainder still to be processed 5,1
Team F*11*

Program ended with exit code: 0
Last edited on
@kemort That's an interesting approach. I do think there's value in looking at these problems from more than one angle.

By the way, there's another thread too:
http://www.cplusplus.com/forum/general/204012/

Anyway, below I changed the commas to tab character and used a stringstream to parse each line:
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 <iostream>
#include <iomanip>
#include <fstream>
#include <algorithm>
#include <string>
#include <sstream>
using namespace std;

struct list{
    char name[40];
    int w;
    int l;
    bool pf;
};

int main() 
{
    ifstream input("data.txt");
    
    int x = 0;
    input >> x;
    input.ignore(10, '\n');
    
    list * mark = new list[x];
    
    string line;
    int count = 0;
    
    while (count < x && getline(input, line))
    {
        replace(line.begin(), line.end(), ',', '\t');
        istringstream ss(line);
        ss.getline(mark[count].name, 40, '\t');
        ss >> mark[count].w;
        ss >> mark[count].l;
        ss >> mark[count].pf;
        if (ss)
            count++;
    }
    
    cout << "count = " << count << '\n';
    if (count != x)
    {
        cout << "error reading expected data from file\n";
    }
    
    for (int i = 0; i < x; i++)
    {
        cout << left << setw(40) << mark[i].name << right;
        cout << setw(5) << mark[i].w;
        cout << setw(5) << mark[i].l;
        cout << setw(5) << mark[i].pf << endl;
    }
}    

closed account (48T7M4Gy)
@Chervil. That's an interesting approach too. It's interesting how ignore() crops up again - makes sense though.

Topic archived. No new replies allowed.