An assignment wants me to make a function that makes all lowercase characters uppercase.
Here's my code:
main.cpp:
#include <iostream>
#include "Function.h"//Includes function file in main file
using namespace std;
int main(){
char a;
cout<<"Enter some words:";
cin.get(a);//Collects info from user
strcap(a);
cout<<a;
}
function.cpp:
#include <iostream>
#include "Function.h"
using namespace std;
char strcap(char a){
while (a!='\n'){
if (a>='a' && a<='z'){
a-=32;//
}
cin.get(a); //get the next letter
}
}
function.h:
#include <iostream>
char strcap(char a);
While the approach you have taken approximates a standard C approach, you have not provided adequate storage to read more than a single character. You could wrap your cin.get(a); strcap(a); cout << a; in a while loop, that would be an approach that is about a decade out of place in C++. Using std::basic::string provides automatic memory management for your input and std::transform makes it simple to apply a transformation to all elements of a container.
The example for std::transform provides exactly what you need, but it doesn't explain how to split the operation up into a separate header and source file. If after reading the documentation you are still stuck, the you can do something similar to the following.
Your header for function.h as you have it simply needs to provide for the declaration of strcap, e.g.
#include <string>
void strcap (std::string& s);
Your implementation for function.cpp likewise just needs to provide for the definition of strcap:
#include <cctype>
#include <algorithm>
#include "function.h"
void strcap (std::string& s)
{
std::transform (s.begin(), s.end(), s.begin(),
[](unsigned char c) -> unsigned char { return std::toupper(c); });
}
(note: the trailing-return-type "-> unsigned char" can be omitted above and it will be deduced properly)
Your main.cpp would then be:
#include <iostream>
#include "function.h"
int main (void) {
std::string s;
std::cout << "enter string: ";
if (getline (std::cin, s)) {
strcap(s);
std::cout << s << '\n';
}
}
Example Use/Output
Compile as you normally would, but you will require the language standard of at least -std=c++11, and then, e.g.
$ ./main
enter string: My dog has fleas
MY DOG HAS FLEAS
Also note, if you do not want to use std::transform, you can use a range-based-for loop to iterate over each character in your string converting to uppercase as well. Your strcap() function would then be:
void strcap (std::string& s)
{
for (auto& c : s)
c = toupper(c);
}
And if for some reason your compiler doesn't support the range-based for loop, then you can also use basic std::string:iterator to iterate over the string providing the conversion, e.g.
void strcap (std::string& s)
{
for (std::string::iterator it = s.begin(); it != s.end(); it++)
*it = toupper(*it);
}
There are several different approaches you can take.
Look things over and let me know if you have any further questions.
Code::Blocks Compiler Options
Just to make sure we are on the same sheet of paper, you should see:
Related
#include <iostream>
#include <numeric>
#include <ranges>
#include <vector>
#include <string>
#include <string_view>
int main() {
auto str = (
std::views::iota(1)
| std::ranges::views::take(5)
| std::ranges::views::transform([](int x) -> std::string_view {
return std::to_string(x) + "|";
})
| std::ranges::views::join
);
for (const char ch : str) {
std::cout << ch;
}
return 0;
}
I'm new to functional programming in cpp. I want to generate first five natural numbers and translate them to string, then join them and print it.
If I use std::string for return type of lambda for transform, it throws many error on compile time. I thought that I should change it into std::string_view. I changed so, and it compiled without compile error. However, if I use std::string_view there, the lambda function returns only reference for string, and translated string that on stack memory is removed on memory when lambda ends. So, the program doesn't print anything.
How can I fix it?
If I use std::string for return type of lambda for transform, it
throws many error on compile time.
What you have observed is a C++20 defect that has been resolved by P2328. If you use a newer compiler version that has already implemented P2328 (such as gcc-11.2), your code will be well-formed.
Before P2328, I think there is no simple solution in the standard.
So I recently discovered the use of map and vectors, however, I'm having trouble of trying to figure a way to loop through a vector containing strings.
Here's what I've tried:
#include <string>
#include <vector>
#include <stdio>
using namespace std;
void main() {
vector<string> data={"Hello World!","Goodbye World!"};
for (vector<string>::iterator t=data.begin(); t!=data.end(); ++t) {
cout<<*t<<endl;
}
}
and when I try to compile it, I get this error:
cd C:\Users\Jason\Desktop\EXB\Win32
wmake -f C:\Users\Jason\Desktop\EXB\Win32\exbint.mk -h -e
wpp386 ..\Source\exbint.cpp -i="C:\WATCOM/h;C:\WATCOM/h/nt" -w4 -e25 -zq -od -d2 -6r -bt=nt -fo=.obj -mf -xs -xr
..\Source\exbint.cpp(59): Error! E157: col(21) left expression must be integral
..\Source\exbint.cpp(59): Note! N717: col(21) left operand type is 'std::ostream watcall (lvalue)'
..\Source\exbint.cpp(59): Note! N718: col(21) right operand type is 'std::basic_string<char,std::char_traits<char>,std::allocator<char>> (lvalue)'
Error(E42): Last command making (C:\Users\Jason\Desktop\EXB\Win32\exbint.obj) returned a bad status
Error(E02): Make execution terminated
Execution complete
I tried the same method using map and it worked. The only difference was I changed the cout line to:
cout<<t->first<<" => "<<t->last<<endl;
Add iostream header file and change stdio to cstdio.
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
using namespace std;
int main()
{
vector<string> data={"Hello World!","Goodbye World!"};
for (vector<string>::iterator t=data.begin(); t!=data.end(); ++t)
{
cout<<*t<<endl;
}
return 0;
}
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> data = {"Hello World!", "Goodbye World!"};
for (std::vector<std::string>::iterator t = data.begin(); t != data.end(); t++) {
std::cout << *t << std::endl;
}
return 0;
}
Or with C++11 (or higher):
#include <iostream>
#include <vector>
#include <string>
typedef std::vector<std::string> STRVEC;
int main()
{
STRVEC data = {"Hello World!", "Goodbye World!"};
for (auto &s: data) {
std::cout << s << std::endl;
}
return 0;
}
From the Open Watcom V2 Fork-Wiki on the C++ Library Status page:
<string>
Mostly complete. Although there are no I/O operators, all other member functions and string operations are available.
A workaround (besides implementing the << operator) would be asking the string instances for the C string:
for (vector<string>::iterator t = data.begin(); t != data.end(); ++t) {
cout << t->c_str() << endl;
}
This of course only works as long as the strings don't contain zero byte values.
When I compile your code, I get:
40234801.cpp:3:17: fatal error: stdio: No such file or directory
#include <stdio>
^
You clearly have a header called "stdio" in your include path that you haven't shown us.
If you change that line to the standard #include <iostream>, then the only reported error is that you wrote void main() instead of int main(). Fix that, and it will build and run.
In passing, note also that using namespace should be avoided.
I found a solution to my own issue. Instead of using a c_str, I used std::string and switched to using the G++ compiler instead of Open Watcom
Instead of having:
char *someString="Blah blah blah";
I instead replaced it with:
string someString="Blah blah blah";
This way is much more efficient and easier.
I have a basic program that compares two strings :
#include <string>
#include <iostream>
using namespace std;
int main (int argc, char *argv[]) {
if(strcmp (argv[0],"./test") != 0) {
cout << "not equal" << endl;
} else {
cout << "equal" << endl;
}
return 0;
}
it compiles with gcc but not with clang :
> clang -o test test_clang.cpp
test_clang.cpp:7:6: error: use of undeclared identifier 'strcmp'
if(strcmp (argv[0],"./test") != 0) {
^
1 error generated.
Why doesn't it compile with clang ?
EDIT: People are getting harsh on stack overflow, up to the point that I am hesitating to post a question. The question above has a simple answer, fine, but is it normal to down-vote questions (twice in the first minute!) because they have a simple, yet non obvious, answer ?
Use
#include <string.h>
or
#include <cstring>
instead of
#include <string>
The string header is for the std::string from C++. string.h is for C zero terminated char* strings. cstring is like string.h but for C++.
The reason it worked with gcc is probably different warning/error level settings. It is possible to compile the code without #including the header and having the declaration of strcmp. The compiler will not be able to do type checking but the symbol still gets resolved by the linker.
You can also avoid using strcmp completely and write
#include <string>
#include <iostream>
int main (int argc, char *argv[]) {
std::string command = argv[0];
if( command != "./test" ) {
std::cout << "not equal" << endl;
} else {
std::cout << "equal" << endl;
}
return 0;
}
Using a std::string on one side of the comparison will cause the "./test" string to be converted into a std::string as well and the comparison will be done by the == operator of the std::string class.
You're not including the correct header file
#include <cstring>
You need to #include <cstring> (or possibly #include <string.h>.)
Many compilers include extra standard headers when you include another. The Standard allows this; it's your responsibility to use the headers that guarantee declarations for what you use, not just headers that happen to have the declarations for your compiler.
You have to include <cstring>. <string> is the header for C++ strings.
I'm trying to find an element in a vector of structs. The code works when searching in a case-sensitive manner. When I try enhancing it to be case-insensitive, I run into two issues.
Simply including boost/algorithm/string.hpp breaks the previously working VS2010 build. The error is "'boost::phoenix::bind' : ambiguous call to overloaded function". Builds OK in Xcode. Any way to disambiguate the bind?
I guess I've got the syntax wrong in the second (commented out) find_if line, adding the istarts_with call. I get errors from the phoenix headers saying "error: no type named 'type'". Assuming issue #1 can be fixed, how should I correct this line?
Thanks!
Code:
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp> // This include breaks VS2010!
#include <boost/phoenix/bind.hpp>
#include <boost/phoenix/core.hpp>
#include <boost/phoenix/operator.hpp>
#include <boost/phoenix/stl/algorithm.hpp>
using namespace boost::phoenix;
using boost::phoenix::arg_names::arg1;
using boost::istarts_with;
using std::string;
using std::cout;
// Some simple struct I'll build a vector out of
struct Person
{
string FirstName;
string LastName;
Person(string const& f, string const& l) : FirstName(f), LastName(l) {}
};
int main()
{
// Vector to search
std::vector<Person> people;
std::vector<Person>::iterator dude;
// Test data
people.push_back(Person("Fred", "Smith"));
// Works!
dude = std::find_if(people.begin(), people.end(), bind(&Person::FirstName, arg1) == "Fred");
// Won't build - how can I do this case-insensitively?
//dude = std::find_if(people.begin(), people.end(), istarts_with(bind(&Person::FirstName, arg1), "Fred"));
if (dude != people.end())
cout << dude->LastName;
else
cout << "Not found";
return 0;
}
You'd need two binds to make it work. First define:
int istw(string a, string b) { return istarts_with(a,b); }
and then use the following as the predicate for the find_if:
bind(&istw,bind(&Person::FirstName, arg1),"fred")
Two comments:
Make sure you're using the right bind, namely, use boost::phoenix::bind.
The definition of istw is probably unnecessary but I could not find the right way to replace it.
I'm having trouble understanding where I went wrong with my code:
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char* argv[]) {
string str = "";
cin >> str;
remove(str.begin(), str.end(), ' ');
cout << str;
cin.ignore();
}
The error says "'remove': function does not take 3 arguments (C2660)"
Try adding
#include <algorithm>
"algorithm" is an STL header containing a lot of functions, including std::remove, which the OP is trying to call. The error he got was because there is another function that takes a single argument, called "remove", which deletes a file.