This looks like homework stuff but please be assured that it isn't homework. Just an exercise in the book we use in our c++ course, I'm trying to read ahead on pointers..
The exercise in the book tells me to split a sentence into tokens and then convert each of them into pig latin then display them..
pig latin here is basically like this: ball becomes allboy in piglatin.. boy becomes oybay.. take the first letter out, put it at the end then add "ay"..
so far this is what i have:
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#include <cstring>
using std::strtok;
using std::strcat;
using std::strcpy;
void printPigLatin( char * );
int main()
{
char sentence[500];
char *token;
cout << "Enter string to tokenize and convert: ";
cin.getline( sentence, 500 );
token = strtok( sentence, " " );
cout << "\nPig latin for each token will be: " << endl;
while( token != NULL )
{
printPigLatin( token );
token = strtok( NULL, " " );
}
return 0;
}
void printPigLatin( char *word )
{
char temp[50];
for( int i = 0; *word != '\0'; i++ )
{
temp[i] = word[i + 1];
}
strcat( temp, "ay" );
cout << temp << endl;
}
I understand the tokenizing part quite clearly but I'm not sure how to do the pig latin.. i tried to start by simply adding "ay" to the token and see what the results will be .. not sure why the program goes into an infinite loop and keeps on displaying "ayay" .. any tips?
EDIT: this one works fine now but im not sure how to add the first letter of the token before adding the "ay"
EDIT: this is how i "see" it done but not sure how to correctly implement it ..
You're running over your input string with strcat. You need to either create a new string for each token, copying the token and "ay", or simply print the token and then "ay". However, if you're using C++ why not use istream iterators and STL algorithms?
To be honest, I severly doubt the quality of the C++ book, judging from your example. The “basic stuff” in C++ isn't the C pointer style programming. Rather, it's applying high-level library functionality. As “On Freund” pointed out, the C++ standard library provides excellent features to tackle your task. You might want to search for recommendations of better C++ books.
Concerning the problem: your printPigLatin could use the existing function strcpy (or better: strncpy which is safer in regards to buffer overflows). Your manual copy omits the first character from the input because you're using the i + 1st position. You also have a broken loop condition which always tests the same (first) character. Additionally, this should result in an overflow anyway.
As the people before me pointed out, there are several other methods of achieving what you want to do.
However, the actual problem with your code seems to be the use of strcat, I see that you changed it a bit in the edit. Here is an explanation of why the initial one did not work char* and size issues
Basically, the pointer does not allocate enough memory to add the "ay" to the string provided. If you create a pointer using the technique shown in the link, it should work fine.
I got your program to work, taking the strcat out and using
cout << word << "ay" << endl
Your loop is infinite because of *word != '\0'.
The word pointer is not changed at any time in the loop.
This seemed to have worked:
void printPigLatin( char *word )
{
cout << word + 1 << word[0] << "ay" << endl;
}
Just not sure if it's a good idea to do that.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Splitting a string in C++
I need a function of split.
has to work like this:
buffer = split(str, ' ');
I searchead a split functions, tryed boost libs, and all works bad :/
strtok() from standard c library is pretty good and does what you are looking for. Unless you are keen on using it from multiple threads and worried about function not being re entrant which i don't suspect is the case here.
P.S. Above assumes you have a character array as input. If it was a c++ string, still you can use string.c_str to get the c string before using strtok
The boost lib is supposed to work as well.
Use it like so:
vector <string> buffer;
boost::split(buffer, str_to_split, boost::is_any_of(" "));
Added:
Make sure to include the algorithm:
#include <boost/algorithm/string.hpp>
Print it to the std::cout like so:
vector<string>::size_type sz = buffer.size();
cout << "buffer contains:";
for (unsigned i=0; i<sz; i++)
cout << ' ' << buffer[i];
cout << '\n';
I guess strtok() is what you're looking for.
It allows you to always return the first sub string delimited by given character(s):
char *string = "Hello World!";
char *part = strtok(string, " "); // passing a string starts a new iteration
while (part) {
// do something with part
part = strtok(NULL, " "); // passing NULL continues with the last string
}
Note that this version must not be used in several threads at once (there's also a version (strtok_s(), more details here) which has an additional parameter to make it work in a parallelized environment). This is also true for cases where you'd like to split a substring within a loop.
TL;DR I need to know which characters are deleted with Win32.
Basically, I need to know what characters are deleted, each time they are. Considering that there are three methods to delete, (Backspace, delete, and Right click>Delete) I'm not sure if I'll just be re-using the same code or what. There's also the option of multiple characters being selected, as well as the option for undo/redo. There's probably something else I'm missing.
As I said above, I need to know which characters are deleted, and how to use undo/redo and how to tell if when using those if characters were added or deleted. (If that's something easily Google, tell me, I just thought of them as I've been writting this post)
What exactly are you talking about? The win32 default control windows? You can subclass them to do that...
http://msdn.microsoft.com/en-us/library/bb773183%28v=vs.85%29.aspx
Well, if you come up with something specific code-wise and don't quite know what to do, just ask here and see if someone can't help you.
With regard to undo/redo, I believe it all depends on the size of the focus area, and I'm not sure how MS does it for, say, Word, or Excel, etc.
But for short stuff, what I posted above should work in a universal sense, but apparently not in your case.
Nevertheless, if anyone wanted to shorten the iteration in the above, they could replace the loop above by starting right at the end of shorter string, like this --
for(int i = iLen2, x=0; i < iLen1; i++, x++)
szAnswer[x]=str1[i];
This simply confines the interation to the missing characters.
Here is a small Win32 Console application that will demonstrate a very simple way to determine which characters have been deleted. You can easily adapt this to a Win32 App, add iterations to it, and so on
#include <iostream>
#include <string>
using namespace std;
#ifndef MAX_PATH
#define MAX_PATH 256
#endif
int main()
{
int iLen1, iLen2, iResult;
char str1[]="The old red box.";
char str2[]="The old red";
char szAnswer[MAX_PATH]="";
// strcmp() will be greather than 0
// if str1 is longer than str2
if(strcmp(str1, str2) > 0)
{
iLen1=strlen(str1);
iLen2=strlen(str2);
iResult=iLen1-iLen2;
cout << "The number of missing characters is " << iResult << endl << endl;
// now lets see which characters are missing
// we iterate through the entire length
// of str1, which is the full text, but
// we only start puting characters into our
// result when we get to the end of str2
for(int i=0, x=0; i < iLen1; i++)
{
if(i >= iLen2)
{
szAnswer[x++]=str1[i];
}
}
cout << endl << "The missing characters are --" << endl << endl << szAnswer << endl << endl;
}
return 0;
}
I am having a really hard time with this problem...
Write a program that reads two strings (that do not contain blanks)
called searchPattern and longSequence.
The program will display in the screen the positions where
searchPattern appears in longSequence.
For example, when
seachPattern is asd
and longSewuence is asdfasdfasdfasdf
(the positions are 0123456789012345)
the program will display 0, 4, 8, 12.
Another example, when
seachPattern is jj
and longSewuence is kjlkjjlkjjjlkjjjkl
(the positions are 012345678901234567)
the program will display 4, 8, 9, 13, 14.
can anyone help?
Some hints:
Read in the two strings. Look up "std::cin" for how to read and "std::string" for how to store the strings.
Look at the std::string class's find() method to search for the substring in the long string.
Have a go and then post what you have done on here. You will find plenty of people happy to help you, but you have to make some effort yourself. :-)
As a starting point, maybe just write the part that reads in the strings. When that is working well, you can add features.
Good luck.
To start thinking about the solution of problems like this, the best way is to think how you would solve it using a pen and paper in as much detail as possible and then try to translate that to code.
I would use Test Driven Development and start out small and build up.
For example, forget about user I/O, and stick with hard-coded data:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
int main(void) // For now, can be modified later.
{
const char pattern[] = "asd";
const char sequence[] = "asdfasdfasdfasdf";
std::string::size_type position = 0;
const std::string longSequence(sequence);
position = longSequence.find(pattern, position);
while (position != std::string::npos)
{
cout << "pattern found at position: " << position << endl;
position = longSequence.find(pattern, position);
}
cout << "Paused. Press ENTER to continue." << endl;
cin.ignore(100000, '\n');
return 0;
}
You may want to convert the above into using a state machine rather than using std::string::find(). Again, this is just a foundation to build upon.
It's a recursive backtracking problem. Just like getting the mouse out of the maze. Define your base cases and your paths through the data. In the end all you need is a single function of maybe 15 - 20 lines.
ifstream toOpen;
openFile.open("sample.html", ios::in);
if(toOpen.is_open()){
while(!toOpen.eof()){
getline(toOpen,line);
if(line.find("href=") && !line.find(".pdf")){
start_pos = line.find("href");
tempString = line.substr(start_pos+1); // i dont want the quote
stop_pos = tempString .find("\"");
string testResult = tempString .substr(start_pos, stop_pos);
cout << testResult << endl;
}
}
toOpen.close();
}
What I am trying to do, is to extrat the "href" value. But I cant get it works.
EDIT:
Thanks to Tony hint, I use this:
if(line.find("href=") != std::string::npos ){
// Process
}
it works!!
I'd advise against trying to parse HTML like this. Unless you know a lot about the source and are quite certain about how it'll be formatted, chances are that anything you do will have problems. HTML is an ugly language with an (almost) self-contradictory specification that (for example) says particular things are not allowed -- but then goes on to tell you how you're required to interpret them anyway.
Worse, almost any character can (at least potentially) be encoded in any of at least three or four different ways, so unless you scan for (and carry out) the right conversions (in the right order) first, you can end up missing legitimate links and/or including "phantom" links.
You might want to look at the answers to this previous question for suggestions about an HTML parser to use.
As a start, you might want to take some shortcuts in the way you write the loop over lines in order to make it clearer. Here is the conventional "read line at a time" loop using C++ iostreams:
#include <fstream>
#include <iostream>
#include <string>
int main ( int, char ** )
{
std::ifstream file("sample.html");
if ( !file.is_open() ) {
std::cerr << "Failed to open file." << std::endl;
return (EXIT_FAILURE);
}
for ( std::string line; (std::getline(file,line)); )
{
// process line.
}
}
As for the inner part the processes the line, there are several problems.
It doesn't compile. I suppose this is what you meant with "I cant get it works". When asking a question, this is the kind of information you might want to provide in order to get good help.
There is confusion between variable names temp and tempString etc.
string::find() returns a large positive integer to indicate invalid positions (the size_type is unsigned), so you will always enter the loop unless a match is found starting at character position 0, in which case you probably do want to enter the loop.
Here is a simple test content for sample.html.
<html>
<a href="foo.pdf"/>
</html>
Sticking the following inside the loop:
if ((line.find("href=") != std::string::npos) &&
(line.find(".pdf" ) != std::string::npos))
{
const std::size_t start_pos = line.find("href");
std::string temp = line.substr(start_pos+6);
const std::size_t stop_pos = temp.find("\"");
std::string result = temp.substr(0, stop_pos);
std::cout << "'" << result << "'" << std::endl;
}
I actually get the output
'foo.pdf'
However, as Jerry pointed out, you might not want to use this in a production environment. If this is a simple homework or exercise on how to use the <string>, <iostream> and <fstream> libraries, then go ahead with such a procedure.
Well!
I feel really stupid for this question, and I wholly don't mind if I get downvoted for this, but I guess I wouldn't be posting this if I had not at least made an earnest attempt at looking for the solution.
I'm currently working on Euler Problem 4, finding the largest palindromic number of two three-digit numbers [100..999].
As you might guess, I'm at the part where I have to work with the integer I made. I looked up a few sites and saw a few standards for converting an Int to a String, one of which included stringstream.
So my code looked like this:
// tempTotal is my int value I want converted.
void toString( int tempTotal, string &str )
{
ostringstream ss; // C++ Standard compliant method.
ss << tempTotal;
str = ss.str(); // Overwrite referenced value of given string.
}
and the function calling it was:
else
{
toString( tempTotal, store );
cout << loop1 << " x " << loop2 << "= " << store << endl;
}
So far, so good. I can't really see an error in what I've written, but the output gives me the address to something. It stays constant, so I don't really know what the program is doing there.
Secondly, I tried .ToString(), string.valueOf( tempTotal ), (string)tempTotal, or simply store = temptotal.
All refused to work. When I simply tried doing an implicit cast with store = tempTotal, it didn't give me a value at all. When I tried checking output it literally printed nothing. I don't know if anything was copied into my string that simply isn't a printable character, or if the compiler just ignored it. I really don't know.
So even though I feel this is a really, really lame question, I just have to ask:
How do I convert that stupid integer to a string with the stringstream? The other tries are more or less irrelevant for me, I just really want to know why my stringstream solution isn't working.
EDIT:
Wow. Seriously. This is kind of embarrassing. I forgot to set my tempTotal variable to something. It was uninitialized, so therefore I couldn't copy anything and the reason the program gave me either a 0 or nothing at all.
Hope people can have a laugh though, so I think this question would now be better suited for deletion since it doesn't really serve a purpose unless xD But thanks to everybody who tried to help me!
Have you tried just outputting the integer as is? If you're only converting it to a string to output it, then don't bother since cout will do that for you.
else
{
// toString( tempTotal, store ); // Skip this step.
cout << loop1 << " x " << loop2 << "= " << tempTotal << endl;
}
I have a feeling that it's likely that tempTotal doesn't have the value you think it has.
I know this doesn't directly answer your question but you don't need to write your own conversion function, you can use boost
#include <boost/lexical_cast.hpp>
using boost::lexical_cast;
//usage example
std::string s = lexical_cast<std::string>(tempTotal);
Try the following:
string toString(int tempTotal)
{
ostringstream ss;
ss << tempTotal;
return ss.str();
}
string store = toString(tempTotal);
If you want to output the integer, you don't even need to convert it; just insert it into the standard output:
int i = 100;
cout << i;
If you want the string representation, you're doing good. Insert it into a stringstream as you did, and ask for it's str().
If that doesn't work, I suggest you minimize the amount of code, and try to pinpoint the actual problem using a debugger :)
Short answer: your method to convert an int to a string works. Got any other questions?