I keep seeing similar questions to mine, however, I can't seem to find one that helps my situation. Honestly, it seems like such a mundane question, I shouldn't be asking it, but here I am 2 weeks latter, still with no answer.
{
string word;
ArrayWithWords[d] = word;
d++;
}
Every time this loop runs, I want to put word in position d of the array. Other examples I've found only turn the string into char*.
The array will be used more than once and having a solid value, if that's what it's called, is far more preferred. I'd like to avoid using a pointer.
Just use a vector of strings.
#include <string>
#include <vector>
int main()
{
std::vector<std::string> ArrayWithWords(10);
size_t d = 5; // something between 0 and 9
std::string word;
ArrayWithWords[d] = word;
d++;
}
Pretty much the same thing that was just posted but a little bit more old school.
#include <string>
using namespace std;
int main()
{
string stringArray[10];
string word;
word = "hello";
for (int i = 0; i < 10; i++)
{
stringArray[i] = string(word);
}
}
Related
For example: I have a string:
abcdef aaaaaaa bbbbbb
and program should output
abcdef
because it's the word with the greatest number of different letters.
How can I do this?
This is the attempt I made
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
void main()
{
string a;
int count = 0;
getline(cin, a);
for (int i = 0; i < a.length(); i++) {
if (a[i] == ' ') {
count++;
}
}
cout << count+1;
}
I think the easiest way to do it is to use std::stringstream to split your string into words.
After that, as already suggested in comments, you could use std::set to count the letters numbers since each element in std::set is unique.
A possible solution would be:
std::pair<std::string, unsigned int> max_letters_word(const std::string & s)
{
std::pair<std::string, unsigned int> result {"", 0};
std::stringstream ss(s);
std::string word;
std::set<char> set;
while(ss >> word)
{
for(char c : word)
set.insert(c);
if(set.size() > result.second)
{
result.first = word;
result.second = set.size();
}
set.clear();
}
return result;
}
And you could use this function as follows:
int main()
{
// Considering this string
std::string s = "abcdef aaaaaaaaa bbbuubbb";
// Call max_letters_word()
std::pair<std::string, unsigned int> result = max_letters_word(s);
// Display the result
std::cout << result.first << ": " << result.second << '\n';
return 0;
}
Live example
With any programming language, "How can I do x?" can have a lot of different answers. Some languages, like python try to lull into the idea that there is one correct (or pythonic as they say) way of doing things, but it's still not true. To python's credit, they usually have a lot less variation than C++ can have.
That is to say, it's a bad question. You need to let us know what your requirements and restrictions are. That allows people to provide solutions that can actually work for you.
Break down the task into sub-tasks. Break the sub-tasks down. Figure out what your algorithm is before writing any code. At a high level, it looks like you need to:
Split the line into individual words
Count the unique characters in each word
Keep track while counting to know which word has the most unique characters
Print the word with the most unique characters
You need to break those tasks down further until you arrive at something you can do. Then do it, and move on. Eventually you'll have a complete program.
If I were to guess, this solution is probably not what you're looking for:
#include <algorithm>
#include <cctype>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
std::size_t count_unique_chars(std::string word) {
for (auto& i : word) {
i = std::toupper(i);
}
std::sort(word.begin(), word.end());
word.erase(std::unique(word.begin(), word.end()), word.end());
return word.length();
}
int main(int argc, char* argv[]) {
if (argc != 2) return 1;
std::string stringLine = argv[1];
std::stringstream stream(stringLine);
std::vector<std::string> words;
std::copy(std::istream_iterator<std::string>(stream),
std::istream_iterator<std::string>(), std::back_inserter(words));
int maxUniqueChars = 0;
std::string wordWithMostUniqueChars;
for (auto i : words) {
int charCount = count_unique_chars(i);
if (charCount > maxUniqueChars) {
maxUniqueChars = charCount;
wordWithMostUniqueChars = i;
}
}
std::cout << wordWithMostUniqueChars << '\n';
}
Outputs:
❯ ./a.out "abcdef aaaaaaa bbbbbb"
abcdef
❯ ./a.out "cat cattttttt cats"
cats
It works, but this looks like a homework problem and most of that code probably flies right over your head. So it doesn't really help you.
I can make some assumptions, but even they might be off. I'm just trying to highlight how much work goes into asking the right questions. It may sound super-annoying, but there are nothing but benefits. Formulating a "good" question requires you to put in effort. That effort comes across in the asking, and when people get a well-formulated question, they will recognize your effort and be more willing to help. It's also easier to answer a well formulated question.
Here's another program that uses a different tactic.
#include <cctype>
#include <iostream>
#include <string>
#include <vector>
std::size_t count_unique_chars(std::string word) {
std::vector<char> letters(26, 0);
for (auto i : word) {
char c = std::toupper(i);
++letters[c - 'A'];
}
int count = 0;
for (auto i : letters) {
if (i > 0) ++count;
}
return count;
}
int main(int argc, char* argv[]) {
if (argc != 2) return 1;
std::string stringLine = argv[1];
std::vector<std::string> words;
while (stringLine.size() > 0) {
std::size_t idx = stringLine.find_last_of(" ");
std::string word = stringLine.substr(idx + 1);
words.push_back(word);
if (idx == std::string::npos) idx = 0;
stringLine.erase(idx);
}
std::size_t maxUniqueChars = 0;
std::string wordWithMostUniqueChars;
for (auto i : words) {
std::size_t count = count_unique_chars(i);
if (count > maxUniqueChars) {
maxUniqueChars = count;
wordWithMostUniqueChars = i;
}
}
std::cout << wordWithMostUniqueChars << '\n';
}
It still relies on taking advantage of std::string and what it offers, which might not fit with your restrictions.
Both programs follow the high-level steps outlined above. Both programs work, but go about executing the algorithm in different ways. Having clear requirements, and knowing what restrictions are in place will also steer you toward a solution.
Yeah we can do this.. Following is the code which can help you out.
#include<bits/stdc++.h>
using namespace std;
int main(){
string s;
getline(cin,s);
s=s+' ';
string word="";
int ans=0;
map<int,string> mp;
for(int i=0;i<s.length();i++){
char ch=s[i];
if(s[i]!=' ')
word=word+ch;
else{
int c=0;
for(int j=0;j<word.length()-1;j++){
if(word[j]!=word[j+1])
c++;
}
ans=max(ans,c);
mp[c]=word;
word="";
}
}
cout<<mp[ans];
}
I have had a similar problem while coding in Java, and in that instance, I used str1.split(",") to change the string of integers into an array of them.
Is there a method in C++ that has a similar function to Java's split method, or is the best way using a for loop to achieve the same goals?
Using std::istringstream to parse this out would certainly be more convenient.
But the question being asked is what's going to be most "efficient". And, for better or for worse, #include <iostream> is not known for its efficiency.
A simple for loop will be hard to beat, for efficiency's sake.
Assuming that the input doesn't contain any whitespace, only commas and digits:
std::vector<int> split(const std::string &s)
{
std::vector<int> r;
if (!s.empty())
{
int n=0;
for (char c:s)
{
if (c == ',')
{
r.push_back(n);
n=0;
}
else
n=n*10 + (c-'0');
}
r.push_back(n);
}
return r;
}
Feel free to benchmark this again any istream or istream_iterator-based approach.
If ou already know the number of elements in your string, the fastest method is to use the c function sscanf which is a lot faster that istringstream (http://lewismanor.blogspot.fr/2013/07/stdstringstream-vs-scanf.html):
#include <cstdio>
#include <iostream>
using namespace std;
int main() {
const char * the_string= "1,2,3,45";
int numbers[4];
sscanf(the_string, "%d,%d,%d,%d", numbers+0, numbers+1, numbers+2, numbers+3);
// verification
for(int i=0; i<4; i++)
cout<<numbers[i]<<endl;
}
I am having trouble getting started with a program. I need to read in each word from a file, then convert it to lower case. I would like to std::cout each word after I find it. I assume I need to use Cstr() some how. I am guessing I should use something like
ofs.open(infile.c_str());
but how to lower case?
string[i] = tolower(string[i]);
then,
std::cout << string[i];
Thanks for the help.
Here is a complete solution:
#include <ctype.h>
#include <iterator>
#include <algorithm>
#include <fstream>
#include <iostream>
char my_tolower(unsigned char c)
{
return tolower(c);
}
int main(int ac, char* av[]) {
std::transform(std::istreambuf_iterator<char>(
ac == 1? std::cin.rdbuf(): std::ifstream(av[1]).rdbuf()),
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(std::cout), &my_tolower);
}
I found the answer to my own question. I really didn't want to use transform, but that does work as well. If anyone else stumbles across this here is how I figured it out...
#include <iostream>
#include <string>
#include <fstream>
int main()
{
std::ifstream theFile;
theFile.open("test.txt");
std::string theLine;
while (!theFile.eof())
{
theFile >> theLine;
for (size_t j=0; j< theLine.length(); ++j)
{
theLine[j] = tolower(theLine[j]);
}
std::cout<<theLine<<std::endl;
}
return 0;
}
int main()
{
ofstream of("xyz.txt");
clrscr();
ifstream inf;
char line;
inf.open("abc.txt");
int count=0;
while(!inf.eof())
{
inf.get(line);
if(line>=65 && line<=123)
{
cout<<line;
line=line-32;
of<<line;
count++;
cout<<line;
}
}
cout<<count;
getch();
return 0;
}
First of all, unless this is something like a homework assignment, it's probably easier to process one character at a time rather than one word at a time.
Yes, you have pretty much the right idea for converting to lower case, with the minor detail that you normally want to cast the input to unsigned char before passing it to tolower.
Personally, I'd avoid doing explicit input and output, and instead do a std::transform with a pair of istream_iterators and an ostream_iterator for the result.
This question already has answers here:
How do I iterate over the words of a string?
(84 answers)
Closed 3 years ago.
I have the following code that is suppose to split a string and inserting it into an array :
char *t;
char *tmpLine = (char *)line.c_str();
t = strtok(tmpLine, "\t");
int counter = 0;
while(t != NULL) {
tempGrade[counter] = atoi(t);
counter++;
t = strtok(NULL, "\t");
}
but for some reason the last entry of line is ignored and not inserted. also line is :
string line = "1 90 74 84 48 76 76 80 85";
NOTE : the spaces are tabspaces (\t) in the original file.
Your code is so wrong it burns my eyes.
What is so wrong?
char *tmpLine = (char *)line.c_str();
First, you are (unless I'm wrong) casting away the constness of a std::string, which is a very bad idea. Anyway, casting away the constness smells of modification attempt...
t = strtok(tmpLine, "\t");
And here we are...
You are modifying the buffer provided by the std::string, as strtok destroys the string given to it.
Bad idea: You are not the owner of the std::string's internal buffer, so you should not modify it (you don't want to break your string, and provoke a bug, want you?),
Back to the code:
t = strtok(tmpLine, "\t");
Ok, so, you're using strtok, which is not a reentrant function.
I don't know what compiler you're using, but I guess most would have a more safe (i.e. less stupid) alternative. For example, Visual C++ provides strtok_s. If you don't have one provided, then the best solution is to write your own strtok, or use another tokenization API.
In fact, strtok is one of the few counter-examples of "don't reinvent the wheel": In that case, rewriting your own will always be better than the original standard C function, if you have some experience in C or C++.
Ok, but, about the original problem?
Others have provided insight about alternatives, or even the fact the incomplete sample of code you provided seemed complete, so I'll stop here my analysis, and let you consider their answers.
I don't know what your code is for, but it is plain wrong, and would be even if the bug you reported (the missing token) didn't exist. Don't use that on production code.
but can you give me a quick hack around this? because this is not an important project and I would have to change alot to do it like in that question
No, you don't. This does the same thing assuming tempGrade is an int array:
istringstream iss(line);
int counter = copy(istream_iterator<int>(iss),
istream_iterator<int>(),
tempGrade) - tempGrade;
But it would be better to change tempGrade to vector and use the code from the answer Moo-Juice linked to.
As other people mention, I suggest you take the recommended C++ approach to this problem.
But I tried out your code, and I can't tell what is wrong with it. I don't repro your issue on my end:
1
90
74
84
48
76
76
80
85
Perhaps your iteration to print out the loop is too short, or your tempGrade array is too small? Or perhaps your final "tab" isn't really a tab character?
Here's the code I compiled to check this code.
#include<iostream>
int main(int argc, char* argv[])
{
std::string line = "1\t90\t74\t84\t48\t76\t76\t80\t85";
char *t;
char *tmpLine = (char *)line.c_str();
t = strtok(tmpLine, "\t");
int counter = 0;
int tempGrade[9];
while(t != NULL) {
tempGrade[counter] = atoi(t);
counter++;
t = strtok(NULL, "\t");
}
for(int i = 0; i < 9; ++i) {
std::cout << tempGrade[i] << "\n";
}
}
Here is a very simple example showing how to make use of stream extraction operators and vector to do this in a more idiomatic C++ manner:
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
void parse(string line)
{
stringstream stream(line);
int score;
vector<int> scores;
while (stream >> score)
scores.push_back(score);
for (vector<int>::iterator itr = scores.begin(); itr != scores.end(); ++itr)
cout << *itr << endl;
}
int main(int argc, char* argv[])
{
parse("1\t90\t74\t84\t48\t76\t76\t80\t85");
return 0;
}
I have comma delimited strings I need to pull values from. The problem is these strings will never be a fixed size. So I decided to iterate through the groups of commas and read what is in between. In order to do that I made a function that returns every occurrence's position in a sample string.
Is this a smart way to do it? Is this considered bad code?
#include <string>
#include <iostream>
#include <vector>
#include <Windows.h>
using namespace std;
vector<int> findLocation(string sample, char findIt);
int main()
{
string test = "19,,112456.0,a,34656";
char findIt = ',';
vector<int> results = findLocation(test,findIt);
return 0;
}
vector<int> findLocation(string sample, char findIt)
{
vector<int> characterLocations;
for(int i =0; i < sample.size(); i++)
if(sample[i] == findIt)
characterLocations.push_back(sample[i]);
return characterLocations;
}
vector<int> findLocation(string sample, char findIt)
{
vector<int> characterLocations;
for(int i =0; i < sample.size(); i++)
if(sample[i] == findIt)
characterLocations.push_back(sample[i]);
return characterLocations;
}
As currently written, this will simply return a vector containing the int representations of the characters themselves, not their positions, which is what you really want, if I read your question correctly.
Replace this line:
characterLocations.push_back(sample[i]);
with this line:
characterLocations.push_back(i);
And that should give you the vector you want.
If I were reviewing this, I would see this and assume that what you're really trying to do is tokenize a string, and there's already good ways to do that.
Best way I've seen to do this is with boost::tokenizer. It lets you specify how the string is delimited and then gives you a nice iterator interface to iterate through each value.
using namespace boost;
string sample = "Hello,My,Name,Is,Doug";
escaped_list_seperator<char> sep("" /*escape char*/, ","/*seperator*/, "" /*quotes*/)
tokenizer<escaped_list_seperator<char> > myTokens(sample, sep)
//iterate through the contents
for (tokenizer<escaped_list_seperator<char>>::iterator iter = myTokens.begin();
iter != myTokens.end();
++iter)
{
std::cout << *iter << std::endl;
}
Output:
Hello
My
Name
Is
Doug
Edit If you don't want a dependency on boost, you can also use getline with an istringstream as in this answer. To copy somewhat from that answer:
std::string str = "Hello,My,Name,Is,Doug";
std::istringstream stream(str);
std::string tok1;
while (stream)
{
std::getline(stream, tok1, ',');
std::cout << tok1 << std::endl;
}
Output:
Hello
My
Name
Is
Doug
This may not be directly what you're asking but I think it gets at your overall problem you're trying to solve.
Looks good to me too, one comment is with the naming of your variables and types. You call the vector you are going to return characterLocations which is of type int when really you are pushing back the character itself (which is type char) not its location. I am not sure what the greater application is for, but I think it would make more sense to pass back the locations. Or do a more cookie cutter string tokenize.
Well if your purpose is to find the indices of occurrences the following code will be more efficient as in c++ giving objects as parameters causes the objects to be copied which is insecure and also less efficient. Especially returning a vector is the worst possible practice in this case that's why giving it as a argument reference will be much better.
#include <string>
#include <iostream>
#include <vector>
#include <Windows.h>
using namespace std;
vector<int> findLocation(string sample, char findIt);
int main()
{
string test = "19,,112456.0,a,34656";
char findIt = ',';
vector<int> results;
findLocation(test,findIt, results);
return 0;
}
void findLocation(const string& sample, const char findIt, vector<int>& resultList)
{
const int sz = sample.size();
for(int i =0; i < sz; i++)
{
if(sample[i] == findIt)
{
resultList.push_back(i);
}
}
}
How smart it is also depends on what you do with those subtstrings delimited with commas. In some cases it may be better (e.g. faster, with smaller memory requirements) to avoid searching and splitting and just parse and process the string at the same time, possibly using a state machine.