Hi

I am making a program that reads a string, when it finds a '.' character it changes the next character after the '.' to uppercase.

My problem is, I am trying to take a string with 5 arrays (string line[5]), & extract the 1st character of line[0], then the 1st character of line[1] and so on. But I dont know the correct way to do it?

input file (info.txt) contents:

i went to the zoo. i love cheese. how are you. what is your name. nice to meet you.

Here is my code, as you can see I dont know the correct syntax to do what I want in function capitalise.

#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>

using namespace std;

void capitalise(string line_array[]);

int main()
{
	ifstream infile;

	string line_array[5];

	infile.open("info.txt");

	if (!infile)
	{
		cout << "Failed to open file";
		return 0;
	}

	for (int i = 0; i < 5; i++)
	{
		getline(infile, line_array[i], '.');
	}

	infile.close();
	
	capitalise(line_array);


	return 0;
}

void capitalise(string line_array[])
{
	char first_letter[5];
		
	for (int i = 0; i < 5; i++)
	{
		line_array >> cin.ignore(100, ' ');
		first_letter[i] = line_array[i];
	}

	for (int j = 0; j < 5; j++)
	{
		if ( first_letter[j] != toupper(first_letter[j]) )
			first_letter[j] = toupper(first_letter[j]);
	}
	

}

Recommended Answers

All 9 Replies

Ok I think I'm misunderstanding something here.

When you mean a string of 5 arrays you really mean an array of depth 5 that can store strings?

Also, are we at all backtracking? And what is really the first character?

If we try using an implementation that parses your line of text (one big string) into 5 smaller strings, each one a sentence, Which character do you want to be the first?

Let's assume that the first character is a letter and that you break up the big string into 5 smaller ones. If that's true, and you're only analyzing the first letter, then none of your letters will be capitalized. Now let's assume that the first letter is a '.'. If that's true then you have to modify your file to have a . in the first sentence and split your big string into smaller ones with a space-char delimiter.

Now let's assume that you don't split your string and keep it as one big string, which is fine too. You then need to consider which character is really the next. Since you are keeping the space chars, without using them as delimiters and skipping them they will persist, but you don't want to capitalize the space character instead of the actual next alphabet-based character... so as you are finding your '.' characters, you need to skip other character until you find one that can be capitalized.

If that's at all confusing please re-read again, or consider these following, more visual cases--

information inside these [] brackets denote 1 string entity

// case 1 use periods to promote the absolute next char after
[.i went to the zoo.i love cheese.how are you.what is your name.nice to meet you.]

// case 2.1 use periods to promote the absolute next char for the
// next sentence, given the very first sentence's char is always
// promoted
[i went to the zoo.][i love cheese.][how are you.][what is your name.][nice to meet you.]

// case 2.2 you decide to traverse the entire string to find the 
// period
// and if you do, promote the first character to uppercase. Repeat
// for each string
[i went to the zoo.][i love cheese.][how are you.][what is your name.][nice to meet you.]

// case 3.1 promote the first alphabet character you find in this big
// string, then scan the string and if you encounter a period you 
// promote the next alphabet character to uppercase
[i went to the zoo. i love cheese. how are you. what is your name. nice to meet you.]

// case 3.2 like case 2.2, except you promote only the next
// alphabet character as opposed to the first
[i went to the zoo.] [  i love cheese.] [ how are you.] [   what is your name.] [       nice to meet you.]

// case n...

You should have to take care of code.

Improper use of cin

line_array >> cin.ignore(100, ' ');

Cannot convert from string to char.

first_letter[i] = line_array[i];

A code I am pasting here will help you to understand where you are wrong?

void capitalise(string line_array[])
{
   for (int i = 0; i < 5; i++)
    {  
 	if(line_array[i][0]==' ')
	     line_array[i].erase(0,1); // Remove leading blank.
	line_array[i][0]=line_array[i][0]-32;
	}
}

Modify your program and show us your progress.

Wow, thank you, does exactly what I want. thanks for your help

Example of new output with the new function: (I just need to not delete the blank spaces but works great)

I went to the zooI love cheeseHow are youWhat is your nameNice to meet you

#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>

using namespace std;

void capitalise(string line_array[]);

int main()
{
	ifstream infile;

	string line_array[5];

	infile.open("info.txt");

	if (!infile)
	{
		cout << "Failed to open file";
		return 0;
	}

	for (int i = 0; i < 5; i++)
	{
		getline(infile, line_array[i], '.');
	}

	infile.close();

	capitalise(line_array);


	return 0;
}

void capitalise(string line_array[])
{
	for (int i = 0; i < 5; i++)
	{
		if(line_array[i][0]==' ')
			line_array[i].erase(0,1); // Remove leading blank.
		line_array[i][0]=line_array[i][0]-32;
	}

	for (int i = 0; i < 5; i++)
	{
		cout << line_array[i];
	}
}
Member Avatar for iamthwee
void capitalise(string line_array[])
{
	for (int i = 0; i < 5; i++)
	{
		if(line_array[i][0]==' ')
			line_array[i].erase(0,1); // Remove leading blank.
			
			
		int j=	line_array[i].length();
			line_array[i].insert(j,". ");
		line_array[i][0]=line_array[i][0]-32;
	}

	for (int i = 0; i < 5; i++)
	{
		cout << line_array[i];
	}
}

maybe?

>>But I dont know the correct way to do it?
What you are doing is ``just" acceptable. It is no where near to what one would called a good code.
I suggest you to use the infamous Unix philosophy KISS( Keep it Simple and Stupid).
Although I am not a big fan of recursion, these problems are best nail for the recursion-hammer.

Consider this:
Write a Small function say, sentence_case(string s) whose job is strictly to do this:
* Take a string.
* Capitalize the First alpha-character after the encounter of the first period(lets say the first encounter of the first alpha-character preceded by a period was at k-th subscript.)
* Return s.substr(0,k)+sentence_case(substr(k, s.size-k) ) That is the corrected_part+ the sentence_case(uncorrected_part)
* This will again call sentence_case on the rest of the string.
* If there is no occurrence of a period, Return the String s, as-is.

I don't know how much you appreciate good programming technique but the one you are applying will lead into what is called the 'adhocity trap'. It won't be months, when you will again look up your code and won't be able to recognize what you did.

The member function you would require are : string::find, string::substr and sting::size You can find reference about these on http://www.cplusplus.com/reference/string/string/
Good Luck

may be it helps to improve your code:

#include <string>
#include <fstream>
#include <cctype>
#include <vector>

std::string& capZ(std::string& s)
{
    int c;
    std::string::size_type pos = 0;
    do {
        while (pos < s.size() && (c = s[pos]&0xFF, isspace(c)))
            pos++;
        if (pos == s.size())
            break;
        if (s[pos] == '.')
            pos++;
        else {
            if (isalpha(c))
                s[pos] = toupper(c);
            pos = s.find('.',pos);
        }
    } while (pos != std::string::npos);
    return s;
}

int main()
{
    std::vector<std::string> done;
    std::ifstream file("info.txt");
    if (file) {
        std::string line;
        while (std::getline(file,line))
            done.push_back(capZ(line));
        file.close();
        for (size_t i = 0; i < done.size(); i++)
            cout << done[i] << '\n';
    }
    return 0;
}

Try this, it works ;)

>Try this, it works
Why do you think I didn't gave him the code?
Anyways, here is my version.

#include <iostream>
#include <string>
#include <cctype>

std::string sentn_case(std::string s)
{
    size_t pos=0;
    //Capatalize the beigning of the string
    while (!isalpha(s[pos])) pos++;
    s[pos]=toupper(s[pos]);

    //Now find the period and split the string for next recursion
    pos=s.find(".");
    if (pos==std::string::npos)return s;

    while (!isalpha(s[pos])) pos++;
    return s.substr(0,pos)+sentn_case(s.substr(pos));
}
int main()
{
    std::string s=\
" and then a voice came over.\" hello. how are you. mister\"";
    std::cout<<sentn_case(s)<<std::endl;
}

The actual function is just 7 lines!
My solution may be less efficient (considering it uses recursion) but quite elegant.

@ArkM code: The output from your function was: And then a voice came over."hello. How are you. Mister"

commented: And what are you doing here. Stop the spoon feeding! -4

>Why do you think I didn't gave him the code?
I don't think that both codes are suitable for his homework solution ;)
I have never said that your solution is bad or less effective than mine,
I'm not interesting for shortes/fastest/best/what else code competitions.
>...but quite elegant.
Congratulations! I'm very glad of the opportunity to read this extremely elegant code.
>."hello
. 1st = > . 1St? ;)

By the way, isalpha(s[i]) is a dangerous construct if s contains non-ascii characters...

>Congratulations! I'm very glad of the opportunity to read this extremely elegant
>code.
LoL. You're sounding funny.:)

>>. 1st = > . 1St?
fine fine. I didn't write that code for 'utmost' perfection. (same way as you did not)
Anyways, that catch can be solved by using isalnum instead.

>By the way, isalpha(s) is a dangerous construct if s contains non-ascii
>characters...
Surprisingly, my implementation handles it. (GNU g++ on Linux)

You looks like a implementor to me, are you?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.