Converting lines

Pages: 12
Can someone further explain how to use sub string and string find ? I am a beginner in an intro C++ class. I am trying to read a text file for a blackjack game and I need to separate each line into 2 cards per player and count the number of wins each player has at the end of the file.
Ex. JH 8D QH AC 8H 9S
I know you would have to convert each line into a string but what happens next ??

By the way, I have read the reference articles for substring & string find so do not link those pages as a response.
Last edited on
If there will always be an even number of cards on each line, you could do something like this, using stringstream.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <string>
#include <sstream>

    using namespace std;

int main()
{
    string line = "JH 8D QH AC 8H 9S";
    istringstream ss(line);
    string word1, word2;

    while (ss >> word1 >> word2)
    {
        cout << word1 << " " << word2 << endl;
    }

    return 0;
}

Output:
JH 8D
QH AC
8H 9S
Last edited on
So there are 100 lines of six cards in the file, so would I increment the lines as so ??

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Before this the file would be read
// string data = text within file

int main ()
{
int i;
   (i, i<0, i++);
  {
    string line = data;
       istringstream ss(line);
       string word1, word2;

      while (ss >> word1 >> word2)
     {
         cout << word1 << " " << word2 << endl;
     }
   }
}


Then for each blackjack I have to record it with a star, so if player one has 6 wins the output should be :

Player 1: ******
The for-loop isn't correct.

At line 6, int i; i is declared but is not given an initial value.
At line 7, (i, i<0, i++); i is not given an initial value, so its value is unknown, it could be anything. Then the test i<0 specifies that the loop will continue so long as i is negative. The line ends with a semicolon making this an empty loop which doesn't control anything.

I suggest you review the for loop here:
http://www.cplusplus.com/doc/tutorial/control/#for
By the way, I have read the reference articles for substring & string find so do not link those pages as a response.


Why not? These are the functions you want (though Chervil does make it simple).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
string line;
string cards[6];

while (getline(file, line)
{
  unsigned int idx = 0; 
  size_t found = line.find(' ', 0);
  while (found != string::npos)
  {
     cards[idx] = line.substr(found - 2, 2);
     ++idx;
     found = line.find( _ , found + 1); 
  }
  if (idx != 6) cout << issues\n;

 }
}


Enhancing Chervil (I think)
1
2
3
string cards[6];
while (file >> cards[0] >> cards[1] >> cards[2] >> cards[3] >> cards[4] >> cards[5]) 
//... 
Last edited on
@ LowestOne Thank you. Your contribution is most welcome.
@LowestOne I understand I have to use sub string and string find but I did not want someone's response to be a link and no explanation, since I have already looked at those pages.
Will your code read every line in the txt file ??
From what I can tell, it cuts out all of the white space and counts the numbers am i correct ??
What would happen with your code if I had this line of code ?
10S KD QD QS 2C 6H
there is a 10 and queens. Would a switch be needed to identify the letters ?

@Chervil
Thank you for the corrections. I made a couple mistakes, I just wanted to make sure the concept was there.
Your output makes sense, but I do not know how to make sure the program knows every third line would be the first player and so on.
Last edited on
I have gotten this far in 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
while (data[c] != '\0' /* or '\n' */) 
{

	// One Line
	card = 0;
	person = 0;
	first_card = 1;
	value = 0;

	while (data[c] != ' ' && first_card) 
    {

		switch(data[c]) 
        {
			case 'K': 
			case 'Q':
			case 'J': 
			case '1': value += 10; first_card--; break;
			case 'A': value += 11; first_card--; break;
			default: first_card--; break;
		}
		c++;
	}


So far this will read in lines from the file and check for special cases in the first card. How do I continue this program with arrays?? My teacher told us to use them but never explained how to use them for this particular game.
It's kind of hard to give guidance on what to do next, as it depends on the exact requirements. For example I assumed each card was represented by two letters, such as TS for ten of spades. I see from an earlier post that you will have three characters, 10S in this case. Either way is ok, but it needs to be clearly specified.

To be frank, I'm not really a card player so some of the rules of the game are not familiar to me. What you need to do is to describe in words what it is you need to do, and then set about translating that into code. My sticking point here is not having a clear description of the exact requirements.
We have to get the lines from a txt file, seperate the cards (two per each player) and give the total number of blackjacks represented by stars at the end of the program for each player. The teacher strongly suggest using arrays, but says there are other ways to complete the program.

For example:
If player1 has 6 blackjacks throughout the whole game, then the table will show:

Player 1: 6 wins *****

As for the rules of the game:
A blackjack is defined as an Ace of any suit and a 10 valued card (Jack, Queen ,King or 10) of any suit
Ok, but how many players will there be? Is it a fixed number or can it vary?
When allocating cards to each player, initially I was thinking of reading two cards, giving them to the first player, and so on. But maybe it is supposed to happen like this, give each player one card, then give each player another card, and so on.

I had also initially assumed that there were a fixed number of cards on each line of the file, but maybe there is just one card per line. And maybe it doesn't even matter, we should just read one card at a time?

As you can see, I have plenty of questions. For me, the most difficult part of any programming task, and this is no exception, it to get the exact requirements.
^^ For example, do you have to use substring? You could simply iterate through the string:
1
2
3
4
int spaceCount = 0;
for (unsigned int i = 0; i < str.length(); i++)
  if (str.at(i) == ' ') spaceCount++;
if (spaceCount != 5) std::cout << "Hey, I was excepting six cards!\n";


To get substrings for various lengths is a little tricky. You need to keep track of where you were before you looked for the next space:
1
2
3
4
5
6
7
8
9
10
// #include <iomanip>
size_t start = 0;
size_t end = str.find(' ', start);
while (end != std::string::npos)
{
    std::cout << "Line from:" << setw(3) << start << " to" << setw(3) << end
              << " is: " << str.substr(start, end - start) << '\n';
    start = end + 1;  // you may have to play around with ones to get rid of empty spaces
    end = str.find(' ', start);
}
Last edited on
The teacher said substring and find can be used to get rid of white space and to find Aces within the code. There are three players throughout the whole game.
@RadCod3Win

I'm not really sure what you're trying to do with the code in your 4th post. You're not saving value between iterations, changing player, or actually reading the second card.

Also, have to repeat Chervil's question. How is the line supposed to be read? Your example:

JH 8D QH AC 8H 9S

Does that mean this?

Player1: JH 8D
Player2: QH AC
Player3: 8H 9S

Or this?

Player1: JH AC
Player2: 8D 8H
Player3: QH 9S

I know you said earlier that there are 100 lines of 6 cards each, so I'm assuming there are 3 players through 100 rounds, and none of them ever hits for another card.
Ok I shall further explain. I will use find to search for an 'A' within the line, if an 'A' is found, then the card before it also must be accounted for. In the example above: JH 8D QH AC 8H 9S
An 'A' is found, then you must find a K,Q,J or 10 as the second card, if one of the three options is there, then the player gets a blackjack and a point is given to the player. After going through many lines of code, the output should read the number of wins each player received throughout the txt file.
:Player 1: 6 wins ******

Theoretically the code will be read as such:

Player1: JH 8D
Player2: QH AC
Player3: 8H 9S
So only a blackjack (Ace + 10pt card) counts as a win?
As for the rules of the game:
A blackjack is defined as an Ace of any suit and a 10 valued card (Jack, Queen ,King or 10) of any suit.
Well, I came up with this loop for finding blackjacks:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    while (getline(fin, line))
    {
        if (line.find('A') != std::string::npos)
        {
            const std::string tens = "1JQK";
            std::istringstream sin(line);

            for (int player = 0; player < 3; player++)
            {
                std::string first, second;
                sin >> first >> second;
                if ((first[0] == 'A' && tens.find(second[0]) != std::string::npos) ||
                   (second[0] == 'A' && tens.find(first[0]) != std::string::npos))
                   playerwins[player]++;
            }
        }
    }
I have this so far :
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
inputFile.open (filename.c_str());
    if (inputFile.is_open())
    {
       for(int p = 0; p < 1000; p++)                    
       //while(!inputFile.eof())                   // while loop for when the program gets to the eof
        {                                    
          getline(inputFile, data);
          lines++;
          //characters += data.length ();
          int test = data.find('A');
          if(test >= 0)
          {
              //cout << "Line: "<< lines << " ---> " <<data<<endl;  
               int endcard1 = data.find_first_of(" ",0);
                string card1 = data.substr(0,endcard1);
                
              //  cout << "End position:"<< endcard1<<" substr "<< card1<<endl;
                endcard1++;
                
                int endcard2 = data.find_first_of(" ",endcard1);
                string card2 = data.substr(endcard1,endcard2);
                endcard2++;
                           if (card1 == "A" && card2 == "J" || card2 == "K" || card2 == "Q" || card2 == "10")
                              {
                                     player1++;
                              }
              int endcard3 = data.find_first_of(" ",endcard2);
              card3 = data.substr(endcard2, endcard3);
              endcard3++;
              
              int endcard4 = data.find_first_of(" ", endcard3);
              card4 = data.substr(endcard3, endcard4);
              endcard4++;
                         if (card3 == "A" && card4 == "J" || card4 == "K" || card4 == "Q" || card4 == "10") 
                            {
                                   player2++;
                            }
              int endcard5 = data.find_first_of(" ",endcard4);
              card5 = data.substr(endcard4, endcard5);
              endcard5++;
              
              int endcard6 = data.find_first_of(" ",endcard5);
              card6 = data.substr(endcard5, endcard6);
              endcard6++;
                         if (card5 == "A" && card6 == "J" || card6 == "K" || card6 == "Q" || card6 == "10")
                            {
                                   player3++;
                            }
              cout << "Player 1 has" << " " << player1 << "blackjacks";
              cout << "Player 2 has" << " " << player2 << "blackjacks";
              cout << "Player 3 has" << " " << player3 << "blackjacks";
              


But the code will not output the right things. Please help !!
You are creating strings by using the substring function, but not doing it correctly.

The first parameter is the position you want the substring to start from. The second parameter is how long you want the substring to be (ie how many characters to copy). What you did was fine for the first card, but not for the others. (EG if endcard3 was the 3rd space, it would be in position 9 or more, so your card3 string would be 9 or more characters long.)

You're also not really using the find_first_of function correctly...

The first parameter is the string or character to search for. The second parameter is the position to start searching from. If you start searching for spaces from where you found your last space, it will return the position of the same space.

Taken together this is the result:

Example: JH 8D QH AC 8H 9S

card1 = "JH"
card2 = " 8"
card3 = " 8"
card4 = " 8"
card5 = " 8"
card6 = " 8"

Assuming you fixed both the problems above, you still have your conditions wrong.

"JH" != "J"
"AC" != "A"
etc.
Pages: 12