Question - Spaces in strings

I'm trying to read int and two strings from a .txt file and store them in the members of each structure array. The problem I have is that when reading the two strings, they have spaces behind them from the text file. How do I remove this so the only thing in the string members is just the string I want without the unnecessary spaces?

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
#include <iostream>
#include <cstdlib>
#include <iomanip>
#include <string>
#include <fstream>

using namespace std;

struct Movie
    {
        int year;
        string name;
        string director;
        int timesCalled;
    };

int main()
{
    string file;
    int size = 0;
    ifstream inFile;

    cout << "What is the name of the file you'd like to open? ";
    getline(cin, file);
    file.append(".txt");
    inFile.open(file.c_str());
    if(!inFile)
    {
        cout << "Can't open the input file!" << endl;
        exit(111);
    }

    inFile >> size;
    Movie movieList[size];
    for (int i = 0; i < size; i++)
    {
        inFile.ignore();
        inFile >> movieList[i].year;
        getline(inFile, movieList[i].name);
        getline(inFile, movieList[i].director);
        //inFile >> movieList[i].director;
    }

    for (int i = 0; i < size; i++)
    {
        cout << movieList[i].year << " ";
        cout << movieList[i].name << " ";
        cout << movieList[i].director << endl;
    }

    return 0;
}


The .txt file looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
16
1940    "Rebecca"                               "Alfred Hitchcock"
1945    "The Lost Weekend"                      "Billy Wilder"
1947	"Gentleman's Agreement"			"Elia Kazan"
1934	"It Happened One Night"			"Frank Capra"
1938	"You Can't Take It With You"		"Frank Capra"
1932	"Cavalcade"				"Frank Lloyd"
1953	"From Here To Eternity"			"Fred Zinnemann"
1941	"How Green Was My Valley"		"John Ford"
1950	"All About Eve"				"Joseph L. Mankiewicz"
1944    "Going My Way"                          "Leo McCarey"
1943	"Casablanca"				"Michael Curtiz"
1936    "The Great Ziegfeld"                    "Robert Z. Leonard"
1939	"Gone With the Wind"			"Victor Fleming"
1942	"Mrs. Miniver"				"William Wyler"
1945	"The Lost Weekend"			"William Wyler"
1946	"The Best Years of Our Lives"		"William Wyler"
Last edited on
There's a space at the end of each string that you don't want? My first thought would be to make each one a char array, and then make another char array with the first array's size - 1 and copy all the elements except the... I think it's the second to last element that would have the space since the null terminating character is the last element in a char array if I remember correctly? Then if you want, you could convert the char arrays back to strings

I'm no expert so I don't know if this is a good answer. That's just what I would be trying to do.
I just want to get rid of the spaces in the string variables. When I output the members of the structs, for example when I cout movieList[0].name, which is the name of the first movie, it comes out as " "Rebecca"" not just ""Rebecca"" as I want it without the spaces behind it. The same with the next string. My getline reads the spaces after the year, for example in the second line of the text file, after 1940 it reads the spaces AND the string "Rebecca" And what do you mean by copy all the elements? Copy the chars with the string to a temporary char array?
Yeah... copy the chars that you actually want to be in the string to a temporary char array and then change that one to a string.

But... really it sounds like you're having problems with delimiters so if you fix that you won't have to do all that copying to char array etc. If I was doing this, I'd have everything with only 1 delimiter after it like this


1945#"The Lost Weekend"#"Billy Wilder"#


I'd use the # or some other weird character as a delimiter. I'm assuming you want the quotes to be included in the titles and names. If you don't, then you could do it like this

1945#The Lost Weekend#Billy Wilder#

but maybe this is a homework assignment and you can't change the way the file is structured
Last edited on
Well the thing is the input file has to be in that format, it cannot be changed (this is an assignment) And okay but some of the strings have a space in them as part of the name of the string. how would i get those if i try to disclose all spaces when reading into the char arrays?
Last edited on
I'm not sure... I'm a C++ 2 student myself and I've never had to do something like this, but I think there are lots of ways to solve this. It may be possible to use a regular expression as a delimiter. Or you could use getline() to get each line and then iterate through each line as a char array (and I actually think you may be able to iterate through a string without converting it to a char array) As you iterate through it you can take the characters you want, so to speak, and put them in other char arrays that you'll convert to your variables.

But I think the easiest solution (that I have said so far) is the first one I've mentioned.

EDIT: Actually, I noticed in your file that you have tabs between the stuff you need to read in. So maybe \t could be your delimiter. I think that may solve your problem but eh, I dunno because there are multiple tabs. Basically, you need to research delimiters.
Last edited on
The trick is to use getline twice per input. Like so:

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
#include <iostream>
#include <string>
using namespace std;

struct Movie {
    int year;
    string name, director;
    int timesCalled;
};

int main() {
	
	int N, year;
	string name, director;
	
	cin >> N;
	Movie *movieList = new Movie[N];
	
	while (N--) {
		cin >> year;
		getline(cin, name, '\"');
		getline(cin, name, '\"');
		
		getline(cin, director, '\"');
		getline(cin, director, '\"');
		cout << year << endl <<
			name << endl <<
			director << endl;
	}
	return 0;
}



Input:
1
1947 "Gentleman's Agreement" "Elia Kazan"


Output:
1947
Gentleman's Agreement
Elia Kazan
Last edited on
I would take advantage of the fact that inFile >> whatever; strips out all leading whitespace first before reading into whatever.

If you want to keep the quotes, inFile >> std::ws; can be used for the same purpose, except it only discards the whitespace and doesn't read anything after that.

Once you've gotten past the first quote, you can use std::getline with a delimiter of '\"' (the quote character) to read all the way through to the closing quote (which is read and discarded -- if you wanted to keep it, you can append one manually).

That should be all you need in order to finish this.

Since Smac89 already posted a solution before I finished typing this, this is what I mean:
1
2
3
4
5
6
7
8
9
for (int i = 0; i < size; ++i)
{
    inFile >> movieList[i].year; // Read year
    char tempQuoteChar;
    inFile >> tempQuoteChar; // Discard the whitespace and read the quote
    std::getline(inFile, movieList[i].name, '\"'); // Read until the next quote
    inFile >> tempQuoteChar; // Discard whitespace and read the quote
    std::getline(inFile, movieList[i].director, '\"'); // Read to next quote
}
Last edited on
If you need to include the quotes in your string find might be more appropriate then getline.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <string>

using namespace std;

int main() {
    { int n; cin >> n; }
    int yr = 0;
    string all;
    while ((cin >> yr) && (getline(cin, all)))
    {
        size_t start = all.find('"');
        size_t end = all.find('"', start);
        string mov(all, start, end - start);

        start = all.find('"', end);
        end = all.find('"', start);
        string dir(all, start, end - start);

        cout << yr << mov << dir << endl;
    }
}


I can't tell if the file is tab or space delimited, or a combination of both. If the data is tab delimited maybe something like this will work
1
2
3
4
5
6
7
while ((cin >> yr) && (getline(cin, all)))
    {
        string mov, dir;
        getline(cin >> skipws, mov, '\t');
        getline(cin >> skipws, dir);
        cout << yr << mov << dir << endl;
    }


@Smac89 You could also use cin.ignore instead of calling getline twice, but I suppose it doesn't matter.
Thank you all. And I tried using the ignore func but it didn't work for some reason. the double getlines for each string worked though
And I tried using the ignore func but it didn't work for some reason.

Using Smac89's code so you can see http://ideone.com/YX8h4b but whatever works for you.
Topic archived. No new replies allowed.