So i'm experimenting with arrays when I come across a bit of a problem
code:
#include <iostream>
#include <windows.h>
using namespace std;
int main(int argc, char** argv) {
char items[] = {'bread', 'water', 'crisps', 'sweets', 'vegetables'};
for (int i = 0; i < strlen(items); i++) {
cout << items[i] << endl;
}
return 0;
}
What's happening is that when the code is ran, it's only outputting the last letter of each item, so 'd' 'r' 's' 's' 's'. I know i'm clearly doing something wrong here but I can't figure out what. I've been surfing on stackoverflow/google for a question like this but clearly what I have done is so obviously wrong, no one has asked!
Any help or a nudge in the right direction to particular documentation would be appreciated!
Thanks.
Need an array of character pointers.
Need to use double quotes
Read a book on C++
i.e. code should be
#include <iostream>
#include <windows.h>
using namespace std;
int main(int argc, char** argv) {
char *items[] = {"bread", "water", "crisps", "sweets", "vegetables"};
for (int i = 0; i < (sizeof(items) / sizeof(*items)); i++) {
cout << items[i] << endl;
}
return 0;
}
Any of these items in the initializer list
{'bread', 'water', 'crisps', 'sweets', 'vegetables'};
is a multicharacter literal. According to the C++ Standard
A multicharacter literal, or an ordinary character literal containing
a single c-char not representable in the execution character set, is
conditionally-supported, has type int, and has an
implementation-defined value.
You need to use string literals. I think that what you want is the following
#include <iostream>
int main(int argc, char** argv)
{
const char *items[] = { "bread", "water", "crisps", "sweets", "vegetables" };
for ( const char *s : items ) std::cout << s << std::endl;
return 0;
}
Related
I have a char pointer , then i convert it into string format. So i would like to capitalize the first character of each word in this string, I wrote the code below :
#include <iostream>
#include <cstring>
#include <stdlib.h>
#include <time.h>
#include <string>
using namespace std;
void transform(char *s);
int main(int argc, char const *argv[])
{
char *str = new char[255];
strcpy(str, "jimmy catter");
string s;
s+=str; //convert char to string
std::cout<<s<<endl;
for (int i = 0; i < s.length(); ++i)
{
if (s[i] == ' ')
{
if (islower(s[i+1])==1)
{
s[i+1] = toupper(s[i+1]);
}
}
}
std::cout<<s<<endl;
return 0;
}
I would like to the output shoule be "Jimmy Catter" , but the result i got is still in the lower format. Could you please help look with this ?
So basically, there are two things here:
islower() should be treated as if it returns a bool, even if it says it returns an int. This is because for a bool, the actual value is false if 0 and true if any value other than 0. This means that if you wanted to still compare to a numerical value you would say islower(s[i]) != 0 since 1 is not the only valid internal value for true.
For the first character (J), there isn't a space before it. So, what we can do is check the current character is the first character OR if the previous character is space. Basically, instead of checking the current character and changing the next character, we check the previous character (or if it's the first character) and then change the current character.
#include <iostream>
#include <cstring>
#include <stdlib.h>
#include <time.h>
#include <string>
using namespace std;
void transform(char *s);
int main(int argc, char const *argv[])
{
char *str = new char[255];
strcpy(str, "jimmy catter");
string s;
s+=str; //convert char to string
std::cout<<s<<endl;
for (int i = 0; i < s.length(); ++i) {
if (i == 0 || s[i - 1] == ' ') {
if (islower(s[i])) {
s[i] = toupper(s[i]);
}
}
}
std::cout<<s<<endl;
return 0;
}
First thing to note here is that islower returns non zero(>0) number if argument is lowercase instead of 1.
Second you are trying to capitalize char by checking if char before it was whitespace. Nothing wrong with this approach but it won't work on first character so you can do it by adding an extra line before the loop. So with some tweaking it works fine now:
#include <iostream>
#include <cstring>
#include <stdlib.h>
#include <time.h>
#include <string>
using namespace std;
// void transform(char *s);
int main(int argc, char const *argv[])
{
string s = "jimmy catter ";
/*
char *str = new char[255];
strcpy(str, "jimmy catter");
string s;
s+=str; //convert char to string
*/
std::cout<<s<<endl;
s[0]=toupper(s[0]);
for (int i = 0; i < s.length()-1; ++i)
{
if (s[i] == ' ')
{
if (islower(s[i+1])>=1)
{
s[i+1] = toupper(s[i+1]);
}
}
}
std::cout<<s<<endl;
return 0;
}
You may use ASCII notations because they are quite clear to understand and execute in such programs.
I modified your code a little bit in the loop part and it gives correct output. Have a look at it.
for (int i = 0; i < s.length(); ++i)
{
if(!i&&97<=s[i]<=122) //handles border condition where first letter is small case
{
s[i] = s[i]-32;
}
if ((i!=s.length-1)&&s[i] == ' ') //prevents invalid output where last character is a space
{
if (97<=s[i+1]<=122) //checks if letter after space is small case
{
s[i+1] = s[i+1]-32;
}
}
}
std::cout<<s<<endl;
return 0;
}
#include<fstream>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
for (int i=1; i<argc ; i++)
{
cout<< argv[i]<< endl;
if( argv[i] == 'all')
cout<<"hey"<< endl;
}
i am passing "1 all emptyfile" through the command files. but i want to compare when argue[i] is equal to all, i want it to print hey
i get this error "Comparison between pointer and integer ('char *' and 'int')" at the if( argv[i] == 'all') anyway i could do it ?
C-style strings can't be compared directly, and even worse, 'all' isn't a string (you probably meant "all", note the quotes).
The C-way to compare them is to use strcmp:
#include <cstring>
if (std::strcmp(argv[i], "all") == 0) { ... }
Since you are using C++, you can use std::string which will allow you to compare strings directly.
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
string s = "all";
for (int i=1; i<argc ; i++)
{
cout<< argv[i]<< endl;
if( argv[i] == s)
cout<<"hey"<< endl;
}
}
Note: all is in double-quotes.
Output when you run the program:
>a.exe all
all
hey
This is although a code specific question but the output is quite bizarre.
I am aware of STL string etc. I was fooling around when I noticed something strange, and could not find a reason for it. :(
See the Two Codes below and the output.
[Code #1] (https://ideone.com/ydB8sQ)
#include <iostream>
#include <vector>
#include <cstdlib>
#include <cstdio>
using namespace std;
class str
{
private:
vector<char> A;
public:
str(const char *S) {
int sz = sizeof(S);
cerr << sz << endl;
for (int i = 0; i < sz; ++i) {
cout << S[i];
//A.push_back(S[i]); //!-- Comment --!//
}
}
};
int main(int argc, char const *argv[])
{
str A("");
return 0;
}
In this, An Empty String is passed and is printed. The Vector A does nothing but is relevant to this problem. In the first version, A is untouched, and the code prints garbage value. (see ideone O/P)
In this second version ( see A.push_back is now uncommented )
[Code #2] (https://ideone.com/PPHGZy)
#include <iostream>
#include <vector>
#include <cstdlib>
#include <cstdio>
using namespace std;
class str
{
private:
vector<char> A;
public:
str(const char *S) {
int sz = sizeof(S);
cerr << sz << endl;
for (int i = 0; i < sz; ++i) {
cout << S[i];
A.push_back(S[i]);
}
}
};
int main(int argc, char const *argv[])
{
str A("G");
return 0;
}
The Output is :
Gvector
This is across GCC / MinGW x64. This one never prints garbage value but always contains the word 'vector'.
Where is the char* in the function pointing to?
Why would 'vector' be there anyways?
Also, the size of char * is 8.
EDIT : This does not happen if it isn't wrapped around a 'class'.
The word 'vector' appears always. I supposed it was random garbage value but then how come ideone still has the same word in its memory?
The main problem in your code is in line int sz = sizeof(S);. sizeof(S) is always equal to sizeof(char *) which seems to be 8 on your system. sizeof gives you number of bytes for variable itself. If you want to know number of bytes in string to which your char pointer points, you should use strlen function instead.
You get that vector string in output randomly, as you are accessing memory which is not in allocated space. Accessing such memory is undefined behavior, so you get your undefined result.
Let's say you have:
const char * something = "m";
How would one make this uppercase, using toupper (or something else, if applicable)?
I want to use a char * instead of a string (I can use a string, but then I have to use str.c_str()).
So, how can I make char * something = "m"; contain "M"?
I find you choice of C strings disturbing.. but anyway.
You can't change a string literal (char *something). Try an array:
char something[] = "m";
something[0] = toupper(something[0]);
To change an entire string:
char something[] = "hello";
char *p = something;
while (*p) {
*p = toupper(*p);
p++;
}
As explained in the very famous C book - The C Programming Language by Kernighan & Ritchie in section 5.5 Character Pointers and Functions,
char amessage[] = "now is the time"; /* an array */
char *pmessage = "now is the time"; /* a pointer */
`amessage` is an array, just big enough to hold the
sequence of characters and `'\0'` that initializes it.
Individual characters within the array may be changed
but `amessage` will always refer to the same storage.
On the other hand, `pmessage` is a pointer, initialized
to point to a string constant; the pointer may subsequently
be modified to point elsewhere, but the result is undefined
if you try to modify the string contents.
OTOH, in C, to convert to upper case letters, you can use the following program as a reference.
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int i=0;
char str[]="Test String.\n";
char c;
while (str[i]) {
c=str[i];
putchar(toupper(c));
i++;
}
return 0;
}
In C++
#include <iostream>
#include <string>
#include <locale>
using namespace std;
int main ()
{
locale loc;
string str="Test String.\n";
for (size_t i=0; i<str.length(); ++i)
cout << toupper(str[i],loc);
return 0;
}
EDIT: Adding pointer version (as requested by #John) for the C version
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int i=0;
char str[]="Test String.\n";
char *ptr = str;
while (*ptr) {
putchar(toupper(*ptr));
ptr++;
}
return 0;
}
Hope it helps!
You can use the same algorithmic approach that you know for std::string for raw arrays:
char s[] = "hello world";
std::transform(s, s + std::strlen(s), s, static_cast<int(*)(int)>(std::toupper));
You cannot do this for immutable string literals (like const char * s = "hello world;") for obvious reasons, so you won't get around an additional allocation/copy for that.
Update: As Ildjarn says in the comment, it's important to note that string literals are always read-only, even though for historical reasons you are allowed to bind them to a pointer-to-mutable, like char * s = "hello world";. Any decent C++ compiler should slap you in the face if you attempt this, but it is valid C++ -- but any attempt to actually modify any element of s is undefined behaviour.
You can convert C-string to std::string and then use boost::to_upper to change string in place or boost::to_upper_copy to create upper case copy of the string. Here is the code example:
#include <iostream>
#include <boost/algorithm/string/case_conv.hpp>
int main ()
{
char const * s = "Test String.\n";
std::string str(s);
std::cout << boost::to_upper_copy(str).c_str() << std::endl;
return 0;
}
Hope this helps.
You could do:
#include <algorithm>
#include <iterator>
#include <ctype.h>
char test[] = "m";
std::transform(std::begin(test), std::end(test), std::begin(test), ::topper);
This applies the ::toupper function to character of the string. This is the ::toupper function in the global namespace that comes from C. std::toupper has multiple overloads and ::toupper looks more elegant than static_cast<int (*)(int)>(&std::toupper).
I've been trying to run a program that will invert the order of a string and to run it, I have to type a second argument in prompt.
int main(int argc, char* argv[])
{
string text = argv[2];
for (int num=text.size(); num>0; num--)
{
cout << text.at(num);
}
return 0;
}
e.g. ./program lorem result: merol
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
string text = argv[1];
for (int num=text.size() - 1; num >= 0; num--)
{
cout << text.at(num);
}
return 0;
}
You missed the includes and used string::at wrong. There are size() chars in the string but you start counting at 0. Then the loop has to run until num >= 0 and not num > 0. You also used the wrong index into argv.
This would still be an abomination of C++. A clearer way would be:
#include <iostream>
#include <string>
#include <algorithm>
int main(int argc, char* argv[])
{
std::string text = argv[1];
for(std::string::reverse_iterator it = text.rbegin(); it != text.rend(); ++it) {
std::cout << *it;
}
std::cout << std::endl;
//or if you want further usage of the reversed string
std::reverse(text.begin(), text.end());
std::cout << text;
return 0;
}
I think you're getting an exception because num is out of bounds. size() is returning a value one larger than the biggest valid index into the string, so at() is throwing an exception.