I have a homework assignment in which I have to return the number of words in a string based on the number of blank spaces. Here is my code, I am not sure what is wrong with it but I keep getting error messages when I try to compile it.
string getWordCount(string sentence){
int count = 1;
for(int i = 1; i < sentence.length(); i++){
if (s[i]==' '){
count++;
}
}
return count;
}
The error messages are:
error: ‘s’ was not declared in this scope
if (s[i]==' '){
^
error: could not convert ‘count’ from ‘int’ to ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’
return count;
^~~~~
To compile your code, you must ensure that return type (count is an int) is compatible with the declared return type of the function (you said it would return string). So instead of:
string getWordCount(string sentence)
declare your function as :
int getWordCount(string sentence)
Note also that you use s[i], but s is not declared. You probably mean sentence[i].
Consider also solving the different algorithmic errors mentionned in the comments (i.e. wrong result for an empty string, for a string with only blank, and depending on the exercise narative, for a string where several consecutive spaces are used between two words) to finish your homework and improve your skills.
You are passing in a variable named sentence but parsing on a variable named s. Also, count is an int but your return type is string. Try this:
int getWordCount (string sentence)
{
int count = 1;
for (int i = 0; i < sentence.length (); i++)
{
if (sentence[i] == ' ')
count++;
}
return count;
}
What they said.
Plus ...Avoid indexing with square brackets. Use range-based for loops. Be careful about trivial input (no words, or even an empty string, in this case). Do not assume that white space is only spaces, or that it only comprises one character. Input parameters that a function does not modify can be declared const-reference, to avoid making an un-needed copy. Use #include <algorithm> for common tasks.
SPOILER ALERT. Read no more until you after you have finished the assignment.
#include <cctype>
#include <string>
int get_word_count(const std::string &sentence)
{
int count = 0;
bool scanning_a_word = false;
for (auto ch : sentence) {
if (!std::isspace(ch)) {
if (!scanning_a_word) {
count += 1;
scanning_a_word = true;
}
} else {
scanning_a_word = false;
}
}
return count;
}
Bonus (and better) solution. The following does not use a state-variable (scanning_a_word). I call that kind of code "bread crumb programming". You leave bread crumbs along the trail to show where you've been. Sometimes birds eat the bread crumbs. Look Ma, no crumbs!
#include <algorithm>
int get_word_count(const std::string &sentence)
{
int count = 0;
auto next = sentence.begin();
const auto done = sentence.end();
while(done != next) {
next = std::find_if_not(next, done, std::isspace);
if (done != next) {
count += 1;
next = std::find_if(next, done, std::isspace);
}
};
return count;
}
Generally, when a variable is not declared within a scope you defined it inside something locally and it does not exist after that block of code (i.e. for loop) has finished executing. Or, you have not declared the variable at all.
error: ‘s’ was not declared in this scope
if (s[i]==' '){
^
Assuming you were trying to iterate through the parameter you passed in, which is a string called sentence, I either change the variable name to s of the parameter, copy the string into another string called s, or change s to sentence in the loop. The different variations are shown below:
// change parameter name to s
string getWordCount(string s)
{
int count = 1;
for(int i = 1; i < sentence.length(); i++)
{
if (s[i]==' ')
count++;
}
return count;
}
// change s to sentence inside the loop
string getWordCount(string sentence)
{
int count = 1;
for(int i = 1; i < sentence.length(); i++)
{
if (sentence[i]==' ')
count++;
}
return count;
}
// create a string s, and copy sentence into string s
string getWordCount(string sentence)
{
int count = 1;
string s = strcpy(s, sentence);
for(int i = 1; i < sentence.length(); i++)
{
if (s[i]==' ')
count++;
}
return count;
}
For your second error, generally this error occurs when there is an issue with casting a variable type to another type. In your case, the below error occurs because you are declaring a function will return a string, however, you are trying to return an int.
error: could not convert ‘count’ from ‘int’ to ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’
return count;
^~~~~
To fix this error, simply change the return type to int. However, if you really want to return the count as a string for some reason, convert the integer to a string before returning. Both variations are shown below.
// Change return type to int to match count's type
int getWordCount(string sentence)
{
int count = 1;
...
...
return count;
}
// If you really need to send count back as a string for some reason, convert the int to string
string getWordCount(string sentence)
{
int count = 1;
...
...
return itoa (count);
}
Please note: this is only describing why your compilation errors are occurring and how to fix them so that you can continue on with your homework assignment. This is not describing what is wrong, logically, with your code.
Related
I am trying to remove duplicates from a string. The code goes like:
#include<iostream>
#include<stdio.h>
#include<string.h>
void removeDup(std::string s, std::string &ex)
{
int hash[256] = {0};
int k = 0;
for (int i = 0; i < s.size(); ++i)
{
if (hash[s[i]] == 0)
{
ex[k++] = s[i];
//std::cout<<ex[k-1];
}
hash[s[i]] = 1;
}
}
int main()
{
std::string s;
std::getline(std::cin, s);
std::string ss;
removeDup(s, ss);
std::cout<<ss<<std::endl;
return 0;
}
Now in main function I have printed the value of ss (which is passed as reference in removeDup function) but it prints nothing. Why is it so? Doesn't the value of string elements gets updated in called function?
Also, when I pass the string by address then I just get the first value printed.
eg :
void removeDup(std::string s, std::string *ex)
{
// same as above body function body
}
int main()
{
......
removeDup(s, &ss);
std::cout<<ss<<std::endl;
return 0;
}
In the output I just get the first letter of whatever is there in s. I can't understand. I am not much familiar with strings in programming languages. Kindly help.
This comes down to the fact that std::string::operator[](size_t index) expects passed index to be lower that string's size().
That means you need to either initialize ss with constructor (variant 2) that will fill it with input's size() worth of ' ''s or, better, use push_back() (ideally in conjunction with reserve() as a way to append elements to the output string.
So I am trying to Merge Sort the letters of a string so that they are in order. Capitalization does not matter since the homework does not require it. For some reason I cannot get templet[index] = split[leftfirst]. I get an "no suitable conversion function from std::string to char exists". Heres my merge function
void merge(string *split, int leftfirst, int leftlast, int rightfirst, int rightlast)
{
string templet;
int index = leftfirst;
int savefirst = leftfirst;
while ((leftfirst <= leftlast) && (rightfirst <= rightlast))
{
if (split[leftfirst] < split[rightfirst])
{
templet[index] = split[leftfirst];
leftfirst++;
}
else
{
templet[index] = split[rightfirst];
rightfirst++;
}
index++;
}
while (leftfirst <= leftlast)
{
templet[index] = split[leftfirst];
leftfirst++;
index++;
}
while (rightfirst <= rightlast)
{
templet[index] = split[rightfirst];
rightfirst++;
index++;
}
for (index = savefirst; index <= rightlast; index++)
split[index] = templet[index];
}
Any help is appreciated.
split is a string*, which means split[some] will not get a character out of the string, it will rather get a string from a string array.
Easiest way to fix this is to change the function definition to have string &split, if you want to modify the variable.
I am trying to find a string which is inside 2D char array and return it's index. For example:
char idTable[255][32];
char tester[] = { 't','e','s','t','e','r','\0' };
memcpy(idTable[43], tester, 7);
uint8_t id = getID(name[0]);
//name is returned from function "char **name = func();"
//but I have the same results when I try using normal char array...
I've had partial success with the first part of the below code, but it is finding a match if a part of the word is the same (one, oneTwo). If I add "else if" to the first "if" it always goes to the "else if".
The rest of the file prints different results for
printf("idTable string lenght:\t %u\n", strlen(idTable[index]));
and
printf("foundMatch string lenght:\t %u\n", strlen(foundMatch));
, unless I add printf("Index:\t %i\n", index);.
uint8_t getID(char *name) {
printf("\nInserted name:\t %s\n", name);
uint8_t index;
for (uint8_t r = 0; r < 255; r++) {
if (strstr(idTable[r], name) != NULL) {
printf("Found '%s' in position:\t %d\n", name, r);
index = r;
}
}
printf("Index:\t %i\n", index); // THIS LINE
char foundMatch[strlen(idTable[index])];
printf("idTable string lenght:\t %u\n", strlen(idTable[index]));
for (uint8_t c=0; c<strlen(idTable[index]); c++) {
foundMatch[c] = idTable[index][c];
}
printf("foundMatch string lenght:\t %u\n", strlen(foundMatch));
if (strcmp(foundMatch, nodeName) == 0) {
printf("Confirmed\n");
return index;
} else {
printf("Second test failed\n");
return 0;
}
}
Why am I getting this strange results and is there a better way to do this?
I don't know how you are initializing your idTable entries, but if you are using the method that you showed at the start of the question you'll have problems. You can't assume all of the space reserved by idTable is initialed to 0's, so idTable[43] isn't a null terminated string. Therefore idTable[43] need not compare equal to the null terminated string "tester".
Also your getID function doesn't return anything despite its signature. So it won't even compile as-is.
Here's a solution in actual C++, not C.
std::array<std::string, 255> idTable;
idTable.at(43) = "tester";
std::pair<std::size_t, std::size_t> findInIdTable(std::string const& what) {
for (unsigned i = 0; i < idTable.size(); ++i) {
std::size_t pos = idTable.at(i).find(what);
if (pos != std::string::npos) {
return std::make_pair(i, pos);
}
}
// if the code reaches this place, it means "not found". Choose how you want to deal with it
// my personal suggestion would be to return std::optional<std::pair<...> instead.
}
If you want to discard the pos value, it's easy to change as well.
Live On Coliru
In the category: Use C++
Of course, use std::array<char, 32> or std::string if possible. I stuck with your choices for this answer:
Live On Coliru
#include <algorithm>
#include <iostream>
#include <cstring>
char idTable[255][32] = { };
int main() {
using namespace std;
// initialize an entry
copy_n("tester", 7, idTable[43]);
// find match
auto match = [](const char* a) { return strcmp(a, "tester") == 0; };
auto index = find_if(begin(idTable), end(idTable), match) - idTable;
// print result
cout << "match at: " << index;
}
Prints
match at: 43
You need to add a nul to the end of the foundMatch array after copying in the idTable row:
foundMatch[strlen(idTable[index])] = '\0';
right before the 'foundMatch string lenght' (length) message.
strlen is an expensive function that walks the string every time. You should call that once, store it in a local variable, then reference that variable rather than calling strlen repeatedly.
I have a class that has one constructor that takes a string;
when a literal was passed in to create a new instant it worked fine.
Now when I create a string variable to have read in it throws an error saying there are conflicting definitions. The variable is able to be passed to a non-class function successfully.
Here is the code:
/*********************
*
*
*draw a box around
*words
*each word gets its
*own line
*********************/
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
class Box
{
short width;// allows for an empty box to appear as two lines
short height;// makes an empty box a 2x2 box
string text;
//will only be constructed with a word
public:
Box(string& words): text(words)
{
height = calc_height()+2;
cout<<height -2<<endl<<text<<endl;
width = calc_Max_length();
cout<<width<<endl<<text;
}
private:
short calc_height()
{
long total = text.length();
string space = " ";
short num_words =1; // calculated by the number of spaces, i know poor option but still hey itll mostly work assuming one word at min
bool afterword = false;
for(int i =0; i<text.length(); i++)
{
if(text[i] == ' ')
{
if(afterword)
{
num_words+=1;
afterword=false;
}
}
else
{afterword=true;}
// cout<<i<<'\t'<<num_words<<endl;
}
// cout<<num_words;
return num_words;
}
short calc_Max_length()
{
short dist_between =0;
short max = 0;
short last = 0;
bool afterword = false;
for(int i =0; i<text.length(); i++)
{
if(text[i] == ' ')
{
// dist_between = i-last;
max = dist_between>max?dist_between:max;
last = i;
dist_between = 0;
}
else
{
dist_between++;
}
// cout<<i<<'\t'<<num_words<<endl;
}
max = dist_between>max?dist_between:max;
return max;
}
};
void takes_string(string& s)
{
cout<<s;
return;
}
int main(void)
{
string input = "crappy shit that sucks";
takes_string(input);
// cin>>input;
Box(input);
return 0;
}
Box(input);
...is equivalent to...
Box input;
That is, it's trying to create a variable of type Box with identifier input, but there's already a std::string called input, hence the redefinition error.
What you obviously want - a temporary Box constructed from the input string - should be written - in C++11 - like this...
Box{input};
FWIW, a good compiler should make this pretty clear in the error message, e.g. from GCC on coliru.stackedcrooked.com:
main.cpp: In function 'int main()':
main.cpp:99:18: error: conflicting declaration 'Box input'
Box(input);
^
main.cpp:96:16: note: previous declaration as 'std::string input'
string input = "crappy shit that sucks";
^
I'm a little confused by the class code. Here's what I'm trying to do:
//Program takes "string text" and compares it to "string remove". Any letters in
//common between the two get deleted and the remaining string gets returned.
#include <string>
#include "genlib.h"
string CensorString1(string text, string remove);
int main() {
CensorString1("abcdef", "abc");
return 0;
}
string CensorString1(string text, string remove) {
for (int i = 0; text[i]; i++){
for (int n = 0; remove[n]; n++){
if (i != n){
string outputString = ' '; //to store non repeated chars in,
//forming my return string
outputString += i;
}
}
}
return outputString;
}
I'm getting an error on the "outputString += 1" saying: "cannot convert from "char" to
std::basic_string
I'm also getting an error on the "return outputString" saying: undeclared identifier
???????
I get that I'm putting a "char" on a "string" variable but what if shortly that "char" will soon be a string? Is there a way to pass this?
I'm always forgetting libraries. Can someone recommend a couple of standard/basic libraries I should always think about? Right now I'm thinking , "genlib.h" (from class).
C++ is kicking my ass. I can't get around constant little errors. Tell me it's going to get better.
There are many errors in your code:
Your outputString needs to be in the outer scope (syntax)
You compare i to n instead of text[i] to remove[n] (semantic)
You are adding i to the output instead of text[i] (semantic)
You ignore the return of CensorString1 (semantic)
Here is your modified code:
string CensorString1(string text, string remove) {
string outputString;
for (int i = 0; text[i] ; i++){
for (int n = 0; remove[n] ; n++){
if (text[i] != remove[n]){
outputString += text[i];
}
}
}
return outputString;
}
This has some remaining issues. For example, using text[i] and remove[n] for termination conditions. It is also very inefficient, but it should be a decent start.
At any rate, strings are always double-quoted in C and C++. Single-quoted constants are char constants. Fix that and you should probably be all right.
Also, look at this SO question: How do you append an int to a string in C++?
Good luck at Stanford!
There are some problems there:
string outputString = ' '; will try to construct a string from a char, which you can't do. You can assign a char to a string though, so this should be valid:
string outputString;
outputString = ' ';
Then, outputString is only visible within your if, so it won't act as an accumulator but rather be created and destroyed.
You're also trying to add character indices to the string, instead of characters, which is not what I think you want to be doing. It seems like you're mixing up C and C++.
For example, if you want to print the characters of a string, you could do something like:
string s("Test");
for (int i=0;i<s.length();i++)
cout << s[i];
Finally, I'd say that if you want to remove characters in text that also appear in remove, you'd need to make sure that none of the characters in remove match your current character, before you add it to the output string.
This is an implementation of what I think you want, your code has multiple problems which just showed up described in multiple other answers.
std::string CensorString1(std::string text, std::string remove) {
std::string result;
for (int i = 0; i<text.length(); i++) {
const char ch = text[i];
if(remove.find(ch) == -1)
result.append(1,ch);
}
return result;
}