1

I am facing a problem with reading and writing a string from and to a file respectively.

Purpose: To enter a string into a text file as a complete sentence, read the string from the text file and separate all words that start from a vowel using a function and display them as a sentence. (The sentence just needs to consist of the words from the string that start with a vowel.)

Problem: The code is working as intended but as i have used the getline() function to obtain the string from the txt file when i withdraw a substring from it, it includes the entire file after the vowel instead of just the word. I cannot understand how to make the substring only include words.

Code:

#include <fstream>
#include <string>
#include <iostream>
#include <cstring>
using namespace std;
string vowels(string a)
{
    int c=sizeof(a);
    string b[c];
    string d;
    static int n;
    for(int i=1;i<=c;i++)
    {
    if (a.find("a")!=-1)
    {
        b[i]=a.substr(a.find("a",n));
        d+=b[i];
        n=a.find("a")+1;
    }
    else if (a.find("e")!=-1)
    {
        b[i]=a.substr(a.find("e",n));
        d+=b[i];
        n=a.find("e")+1;
    }
    else if (a.find("i")!=-1)
    {
        b[i]=a.substr(a.find("i",n));
        d+=b[i];    
        n=a.find("i")+1;
    }
    else if (a.find("o")!=-1)
    {
        b[i]=a.substr(a.find("o",n));
        d+=b[i];
        n=a.find("o")+1;
    }
    else if (a.find("u")!=-1)
    {
        b[i]=a.substr(a.find("u",n));
        d+=b[i];
        n=a.find("u")+1;
    }
    }
    return d;
}
int main()
{
    string input,lne,e; 
    ofstream file("output.txt", ios::app);
    cout<<"Please input text for text file input: ";
    getline(cin,input);
    file << input;
    file.close();
    ifstream myfile("output.txt");
    getline(myfile,lne);
    e=vowels(lne);
    cout<<endl<<"Text inside file reads: ";
    cout<<lne;
    cout<<endl;
    cout<<e<<endl;
    system("pause");
    myfile.close();
    return 0;
}
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321

2 Answers2

0

I haven't read your code VERY carefully, but several things stand out:

  1. Look up find_first_of - it'll simplify your code A LOT.
  2. sizeof(a) certainly doesn't do what you think it does [unless you think it gives you the size of the std::string class type - which makes it rather strange as a use-case, why not use either 12 or 24?]
  3. find (and find_first_of), technically speaking, doesn't return -1 when the function isn't finding what you want. It returns std::string::npos [which may appear to be -1, but a) is not guaranteed to be, and b) is unsingned so can't be negative].
  4. Your program only reads one line.
  5. x.substr(n) will give you the string of x from position n - is that what you want?
  6. Don't repeat find, use p = x.find("X"); and then do x.substr(p) [assuming that is what you want].
Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • Im sorry for the unoptimized code.... im still learning in the ins and outs of C#... 1. i used sizeof() because im using ios:app and the string is increasing, so i was unsure of how many loops to run, sizeof() increases with the string i thought it would be appropriate. 2. i know eof() and a loop can read multiple lines, im just getting the code straight for 1 line. 3. Yes i want it to continue from where it left of, thus the 'n' and 'n+1'. 4. i was x.substr() to begin and end after a word; not include the entire rest of the string. – Mohid Waseem Jun 16 '15 at 07:54
  • But `sizeof` doesn't give you the number of elements in a string, it gives you the number of bytes needed to hold the various bits of data that maintains the string inside `std::string` - in other words, it's a constant, and doesn't even nearly do what you expect it to do. I'm 100% sure that `sizeof` is NOT what you want here. If you want 24, then write 24, not `sizeof(a)` [it could be 12, 16 or 32 too - but on a 64-bit system, it is usually 24]. `std::string::size()` may be what you are looking for. – Mats Petersson Jun 16 '15 at 08:11
0

There are various problems with your code.

int c = sizeof( a );

This is the number of bytes that a string takes up in memory. And you certainly don't want to create an array of this many strings as it makes no sense for what you're trying to achieve. Don't do this to yourself. You're only copying one string inside the loop, all you need is one string and you already have string d.

To get the actual size of a string, you have to call

str.size()

The string.substr(..) has a couple overloads, one of them takes only one argument, an index. This will return sub string starting at that index in the original string. (The string starting at the vowel all the way through to the end of the string) What you are maybe looking for is the overload that takes two arguments, the start index (beginning of the word and the end of the word).

The string input will not take the newline that you enter to flush cin. And then you add it to the file in append mode, so after running the program a few times your file is a huge one-liner. Did you really intend to do this? Maybe you should explicitly add a new line to the file after entering the input. Something like file << std::endl;

Also, the conditions in the ifs

if (a.find("a")!=-1)

Don't match what you do next,

b[i]=a.substr(a.find("a",n));

Then you use a static int,

static int n;

This is bad, because this function will only work once. You're lucky that static initializes its values to zero, but you should always initialize explicitly. In your case, you don't need this to be static.

Finally: "so i was unsure of how many loops to run" When you don't know how many loops you have to run, then a for loop is not adequate. You should use a while loop or a do while.

You shouldn't try to learn C++ by guessing, because that's what it looks like you're doing. You're trying to do more than you know and making some very silly mistakes. Find a good book to learn from, or at the very least google the functions you're using to see what they do and how to use them properly. (ie: http://www.cplusplus.com/reference/string/string/substr/ )

Here's a list of books from stackoverflow's FAQ: The Definitive C++ Book Guide and List

The last thing is about finding vowels. When you find a vowel, you have to make sure it's at the beginning of a word. Then you want to read it until the word ends, that is when you find a character that is not part of a word. (a whitespace, certain punctuation, ... ) This should mark the beginning and end of the word.

Community
  • 1
  • 1
aslg
  • 1,966
  • 2
  • 15
  • 20
  • Thank you ... i now understand my mistakes.... actually this was a task for my last C++ exam.... we weren't taught as well to actually make a program of this level, so none of us were able to do it. You guessed write, im mostly doing this by trial and error, not really solving this logically. Thank you all for the answers; they really did help. Regards. – Mohid Waseem Jun 16 '15 at 08:46