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.
Related
I'm currently solving problems for my high school final exam at programming in C++. I tried solving a problem in CodeBlocks, but it gives me this error at line 13:
error: invalid conversion from 'const char*' to 'int' [-fpermissive]
I don't see what is wrong.
The problem is about removing the last consonant from a string. The string is "mare frig saci" and it should produce "mare frig sai", removing the last 'c'.
Here is my code:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char s[256];
int i;
cin.get(s,256);
for(i=strlen(s)-1;i=0;i--)
{
if(strchr(s,"aeiou")!=0)
strcpy(s+i+1,s+i-1);
}
cout<<s;
return 0;
}
There are a few problems:
i=0 is not a condition, it's an assignment. i>=0 is probably what you're looking for here
strchr take in a string and char (1), and return a pointer (2), not an int to be compared. Both (1) and (2) condition isn't sastified. In any case, strchr is not ideal to use here.
I recommended using std::string (as it's more easy to use and standard in C++) and std::string::find_last_of, which find the last character in string inside a set of characters, exactly what you wanted here:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s; getline(std::cin, s);
string cons = "bcdfghjklmnpqrstvwxyz";
size_t pos = s.find_last_of(cons);
if (pos != string::npos) //if a consonant is found
{
s.erase(pos, 1);
}
cout << s;
}
std::strchr - The valid signatures are
const char* strchr( const char* str, int ch );
char* strchr( char* str, int ch );
So, you are supplying it with the wrong things.
std::strcpy - "The behavior is undefined if the strings overlap" - so you can't use std::strcpy to move the end of the string to the new place. Instead use std::memmove.
Since the string you mention contains a space at the end, you must add space to the list of vowels.
You assign 0 to i instead of checking it's value.
Example:
#include <cstring>
#include <iostream>
int main() {
char s[256] = " mare frig saci ";
for (size_t len = strlen(s), i = len; i-- > 0;) { // corrected loop
if (std::strchr("aeiou ", s[i]) == nullptr) { // corrected check
std::memmove(s + i, s + i + 1, len - i); // corrected move
break; // and break out
}
}
std::cout << s << '\n';
}
I am well aware that the instructions for this are highly innefficient/almost obsolete. I actually developed a much simpler solution using strings, but for education purposes, my university has decided to make it a requirement that we solve this issue by the use of pointers and char arrays rather than strings.
Basically, I need to pass a predefined char array (a specific phrase) and have it returned reversed.
So far, my output is absolute gibberish (Some characters which I cannot even type here) so I assume I must be doing something very wrong, but I can't see why.
To experiment, I tried to manually assign the *ptr_cha at the end of the function body to be something like "Hello", but then I'm met with type conversion errors. If I manually assign temp[0] to be "hello", and skip out the for cycle and simply say at the end that *ptr_cha[0] is equal to temp[0], I still get gibberish.
And if I try to output the contents of clone at the start of the function (after saying it's equal to ptr_cha[0]), it says the contents are "d", a letter which is not even present in the original sentence.
This is my whole code:
#include <iostream>
#include <wchar.h>
#include <locale.h>
#include <array>
using namespace std;
void invertChar(char *ptr_cha[]);
int main()
{
setlocale(LC_ALL, "");
char sentence[] {"Pablito clavó un clavito que clavito clavó Pablito"};
char *ptr_sentence[] {nullptr};
*ptr_sentence = sentence;
invertChar(ptr_sentence);
cout << ptr_sentence[0];
};
void invertChar(char *ptr_cha[]) {
char clone[] = {""};
char temp[] = {""};
ptr_cha[0] = clone;
int length = sizeof(clone)/sizeof(*clone);
int j = length;
for(int i = 0; i < length; i++) {
temp[i] = clone[j];
j--;
};
*ptr_cha[0] = temp[0];
};
As mentioned, the idea is for sentence to be set to its inverted form and displayed in the output.
As an additional, side question: Why is calculating the length of a char array in c++ so complicated/verbose? For strings there's a simple method, here you have to do this whole "trick" of dividing the sizeof the array by the sizeof its reference. I don't even see how the storage size of the array divided by the storage size of its pointer could return the length of the array...
Let me break down what's happening in each step. If you're using an IDE I highly recommend you to debug your program and see what's happening in each step. (In your code I assumed that you wanted to reverse 'sentence' and not return a copy of its reversed version.)
wchar.h and array are not used here, you can just delete those lines.
Other than that, you shouldn't pass a character string to a function like that. See this how to do properly.
#include <iostream>
#include <wchar.h> // Not used.
#include <locale.h>
#include <array> // Not used.
using namespace std;
void invertChar(char *ptr_cha[]);
Here, you should just pass sentence to invertChar, ptr_sentence is unnecessary and strange (char* ptr_sentence would be enough because now it's an array that contains pointers to chars and you store the address of sentence in its first slot).
int main()
{
setlocale(LC_ALL, "");
char sentence[] {"Pablito clavó un clavito que clavito clavó Pablito"};
char *ptr_sentence[] {nullptr};
*ptr_sentence = sentence;
invertChar(ptr_sentence);
cout << ptr_sentence[0];
};
void invertChar(char *ptr_cha[]) {
char clone[] = {""};
char temp[] = {""};
You are assigning clone to ptr_cha[0], now ptr_cha[0] is referencing clone and not to sentence. At this point you cannot reach sentence.
ptr_cha[0] = clone;
The first line below would be more descriptive written like this: int length = sizeof(clone) / sizeof(clone[0]). This divides the size of clone with the size of its first element, basically giving you the number of elements clone has. It's important to divide by the element size because what if clone uses something to store characters that isn't 1 byte long like char. You can get the number of elements of any array with this trick.
int length = sizeof(clone)/sizeof(*clone);
int j = length;
for(int i = 0; i < length; i++) {
Remember that both temp and clone are empty strings, more precisely they have 1 element and that's the \0 character that indicates the end of the string.
In the first run of the loop you are doing this: temp[0] = clone[1] but clone doesn't have a second element (index 1). At this point you are accessing something that's out of the array and assigning it to temp where it gets interpreted as a char, resulting in some "gibberish".
temp[i] = clone[j];
j--;
};
*ptr_cha[0] = temp[0];
};
Overall, I would recommend you to look into pointers and how they are working because they can be a little tricky and confusing.
Working C(++) implementation:
#include <iostream> // cout
#include <locale.h> // setlocale
#include <string.h> // strlen
void reverse(char* string)
{
// Check whether our pointer really points to something or not.
if (string == nullptr) return;
// 'strlen' returns the size of a '\0' terminated character sequence (including the '\0').
// We subtract 1 from the length because we don't want to swap the terminating
// '\0' character with the first one.
const int length = strlen(string) - 1;
for (int i = 0, j = length; i < j; ++i, --j) {
const char temp = string[i];
string[i] = string[j];
string[j] = temp;
}
}
int main()
{
setlocale(LC_ALL, "");
char sentence[] = "Pablito clavó un clavito que clavito clavó Pablito";
reverse(sentence);
std::cout << sentence << '\n';
return 0;
}
C++ implementation just for comparison:
#include <algorithm> // reverse
#include <iostream> // cout
#include <locale> // locale, locale::global
#include <string> // string
void reverse(std::string& string)
{
std::reverse(string.begin(), string.end());
}
int main()
{
std::locale::global(std::locale(""));
std::string sentence = "Pablito clavó un clavito que clavito clavó Pablito";
reverse(sentence);
std::cout << sentence << '\n';
return 0;
}
I'm a newbie in C++ learning the language and playing around. I wrote a piece of code which behavior I don't understand. Could someone explain why the code below prints out random junk and not the first character of the first string in the list (that is a).
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <ctime>
#include <climits>
#include <stdio.h>
char* str2char(std::string str)
{
char cset[str.size()+1]; // +1 for the null character
for(int i = 0; i < str.size(); i++)
{
cset[i] = str[i];
}
cset[str.size()] = '\0';
return cset;
}
int main (int argc, char * const argv[]) {
std::vector< std::string > ladontakadet;
ladontakadet.push_back("aabcbbca");
ladontakadet.push_back("abcdabcd");
ladontakadet.push_back("cbbdcdaa");
ladontakadet.push_back("aadcbdca");
ladontakadet.push_back("cccbaaab");
ladontakadet.push_back("dabccbaa");
ladontakadet.push_back("ccbdcbad");
ladontakadet.push_back("bdcbccad");
ladontakadet.push_back("ddcadccb");
ladontakadet.push_back("baccddaa");
std::string v = ladontakadet.at(0);
char *r;
r = str2char(v);
std::cout << r[0] << std::endl;
return 0;
}
Why is my returning garbage, when I'm expecting it to output a?
Thnx for any help!
P.S. The output of this code is random. It doesn't always print the same character..:S
It's because you return a pointer to a local variable, a local variable that goes out of scope when the function returns.
You are already using std::string for the argument, use it instead of the array and the return pointer.
If your aim is to pass the content of a std::string to a function modifying the content of a char*:
#include <iostream>
#include <vector>
void f(char* s) {
s[0] = 'H';
}
std::vector<char> to_vector(const std::string& s) {
return std::vector<char>(s.c_str(), s.c_str() + s.size() + 1);
}
int main(void)
{
std::string s = "_ello";
std::vector<char> t = to_vector(s);
f(t.data());
std::cout << t.data() << std::endl;
}
Your function is returning garbage because you're returning the address of a local variable which goes out of scope after your function returns. It should probably look like this:
char* str2char(const std::string &str)
{
char *const cset = new char[str.size() + 1]; // +1 for the null character
strcpy(cset, str.c_str());
return cset;
}
You will need to delete your variable r by doing delete[] r;. Ideally though you wouldn't be using raw pointers, and you would use std::string for everything, or wrap the char * in a std::unique_ptr.
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;
}
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).