void main() {
char str1[4] = { 'A','B','C','D' };
char str2[3] = { 'A','B','D' };
cout << strlen(str2)
}
the results is 31, and I don't know why it happens
You need nul-terminators on your C-style strings.
#include <iostream>
#include <cstring>
int main() {
char str1[4+1] = { 'A','B','C','D', '\0' }; // same as = "ABCD"
char str2[3+1] = { 'A','B','D', '\0' }; // same as = "ABD"
std::cout << std::strlen(str2) << '\n';
}
C strings (as in arrays of chars) by standard are arrays which terminating character is '\0'.
When you assign a string like this:
char* a = "hello";
it's equivalent to:
char a[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
This kind of string works with strlen and similar (strcpy, strthis, strthat).
In C++ you should rather use the type String that you get including string. It's a class and you can use the functions of that class
#include <string>
...
std::string a = "hello";
int size = a.size();
When you do strlen of an array (actually the address for the first character), the strlen function iterates in your memory until it finds a \0, even if it goes out of your array and into whatever other data is in your memory.
The 31 you got means your strlen was going on for 31 times the size of a char in your memory before it finally met a \0 byte.
Related
I'm trying to store commands in a queue and read them from the queue later on. I'm using this queue because the code needs to run on an Arduino. When accessing the first (or any) character, I'm getting a segmentation fault. What am I doing wrong here?
int main() {
cppQueue q(sizeof(char*), 10);
char c1[] = {'a', 'b', 'c'};
q.push(&c1);
char *command;
q.pop(&command);
char first = command[0]; <-- error
// do stuff with first
return 0;
};
Thanks for any help!
PS: This works:
cppQueue q(sizeof(int), 10);
int x = 1;
q.push(&x);
int numba;
q.pop(&numba);
std::cout << numba << "\n"
Arrays are not pointers. Arrays can automatically converted to pointers in most case of expressions, but one of the exception is used with unary & operator.
With q.push(&c1);, the queue will read the contents of the array (plus some garbage for out-of-range region) instaed of a valid pointer value.
Use a pointer variable to feed the queue a pointer.
int main() {
cppQueue q(sizeof(char*), 10);
char c1[] = {'a', 'b', 'c'};
char* p = c1;
q.push(&p);
char *command;
q.pop(&command);
char first = command[0];
// do stuff with first
return 0;
}
void reverse(char[] x) {
char* pStart = x;
char* pEnd = pStart + sizeof(x) - 2;
while(pStart < pEnd) {
char temp = *pStart;
*pStart = *pEnd;
*pEnd = temp;
pStart++;
pEnd--;
}
}
int main() {
char text[] = ['h','e','l','l','o'];
reverse(text);
cout << text << endl;
return 0;
}
I am new to C++ and stack overflow.
I am trying to reverse a string using pointers... I don't quite understand what I did wrong. Please help me out.
Additional question: What is the difference between a string and an array of characters?
sizeof(x) with x being a parameter of type char[] of a function does not give you the number of characters in the string but the size of a char*, probably 8 on a 64 bit system. You need to pass a C-String and use strlen(x) instead. Write char text[] = {'h','e','l','l','o','\0'} or char text[] = "hello" in main.
Note that sizeof() needs to be evaluatable at compile time; this is not possible on arrays with undetermined size like char[]-typed function arguments. When using sizeof on a variables like your char text[] = {'h','e','l','l','o'}, however, sizeof(text) will result in the actual size of the array.
char x[] is the same as char* x and the sizeof(x) is therefore the size of a pointer. So, because you cannot calculate the size of an array outside of the block it is declared in, I would eliminate that part from your function.
It would be much easier to provide the function with pointers to the first and last characters to be replaced:
void reverse(char* pStart, char* pEnd)
{
while (pStart < pEnd)
{
char temp = *pStart;
*pStart = *pEnd;
*pEnd = temp;
pStart++;
pEnd--;
}
}
So now it is quite easy to call this function - take the address (using ampersand &) of the the relevant characters in the array: &text[0] and &text[4].
To display an array of characters, there is a rule, that such "strings" HAVE to have after the last character a NULL character. A NULL character can be written as 0 or '\0'. That is why it has to be added to the array here.
int main()
{
// char text[] = "hello"; // Same like below, also adds 0 at end BUT !!!in read-only memory!!
char text[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
reverse(&text[0], &text[4]);
std::cout << text << std::endl;
return 0;
}
Answers to Why this program compiles fine in C & not in C++? explain that unlike the C language, the C++ language does not tolerate an initializer string for a char array that is not long enough to hold the terminating null character. Is there a way to specify an unterminated char array in C++ without bloating the string by a factor of four in the source code?
For example, in C and in C++, the following are equivalent:
const char s[] = "Hello from Stack Overflow";
const char s[] = {'H','e','l','l','o',' ','f','r','o','m',' ','S','t','a','c','k',' ','O','v','e','r','f','l','o','w','\0'};
Because the string "Hello from Stack Overflow" has length 25, these produce a 26-element char array, as if the following had been written:
const char s[26] = "Hello from Stack Overflow";
const char s[26] = {'H','e','l','l','o',' ','f','r','o','m',' ','S','t','a','c','k',' ','O','v','e','r','f','l','o','w','\0'};
In C only, a program can exclude the terminating null character, such as if the string's length is known out of band. (Look for "including the terminating null character if there is room" in chapter 6.7.9 of the C99 standard.)
const char s[25] = "Hello from Stack Overflow";
const char s[25] = {'H','e','l','l','o',' ','f','r','o','m',' ','S','t','a','c','k',' ','O','v','e','r','f','l','o','w'};
But in C++, only the second is valid. If I know I will be manipulating the data with functions in the std::strn family, not the std::str family, is there a counterpart in the C++ language to the shorthand syntax of C?
My motivation differs from that of the other question about unterminated char arrays in C++. What motivates this is that several names of items in a game are stored in a two-dimensional char array. For example:
const char item_names[][16] = {
// most items omitted for brevity
"steel hammer",
{'p','a','l','l','a','d','i','u','m',' ','h','a','m','m','e','r'}
};
If there is no shorthand to declare an unterminated char array, then maximum-length names will have to be written character-by-character, which makes them less readable and less maintainable than to shorter names.
It is possible but I would agree with Alan Stokes' "Why"
For example using C++: Can a macro expand "abc" into 'a', 'b', 'c'?
It could be tweaked father to allow operate on any provided array and constrain it by length 16.
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
template <unsigned int N>
constexpr char get_ch (char const (&s) [N], unsigned int i)
{
return i >= N ? '\0' : s[i];
}
#define STRING_TO_CHARS_EXTRACT(z, n, data) \
BOOST_PP_COMMA_IF(n) get_ch(data, n)
#define STRING_TO_CHARS(STRLEN, STR) \
BOOST_PP_REPEAT(STRLEN, STRING_TO_CHARS_EXTRACT, STR)
const char item_names[][16] = { // most items omitted for brevity
"steel hammer",
STRING_TO_CHARS(16, "palladium hammer"),
//{'p','a','l','l','a','d','i','u','m',' ','h','a','m','m','e','r'},
};
but it could cost you more trouble in a long run...
the disadvantage of c-style array is that it can not be passed to or returned from functions (pass or return char* can give you an array of char* but not array of char[] in the end), we can use std::array to get around this
the advantage of c-style array is that small string literal can be used to initialize larger char[] in a char[][]'s initialize list (as in your example), for std::array we use std::max to simulate this
#include<array>
#include<utility>
#include<algorithm>
#include<iostream>
template<size_t string_length, typename T, T... ints, size_t string_literal_size>
constexpr std::array<char, string_length> generate_string_impl(std::integer_sequence<T, ints...> int_seq, char const(&s)[string_literal_size])
{
return { {s[ints]...} };
}
template<size_t string_length, size_t string_literal_size>
constexpr std::array<char, string_length> generate_string(char const(&s)[string_literal_size])
{
return generate_string_impl<string_length>(std::make_index_sequence<string_literal_size - 1>{}, s);
}
template<size_t ...string_literals_size>
constexpr std::array < std::array<char, std::max({ string_literals_size... }) - 1 > , sizeof...(string_literals_size) > generate_array_of_strings(char const(&...s)[string_literals_size])
{
return { generate_string < std::max({ string_literals_size... }) - 1 > (s)... };
}
int main()
{
constexpr auto array_of_string1 = generate_array_of_strings("1234", "12345", "123456");
//std::array<std::array<char,6>,3>{{
// {{ '1', '2', '3', '4', '\0', '\0' }},
// {{ '1', '2', '3', '4', '5', '\0' }},
// {{ '1', '2', '3', '4', '5', '6' }}
//}}
//std::array<std::array<char,6>,3> satisfies StandardLayoutType requirement
char const(&array_of_string2)[std::size(array_of_string1)][6] = reinterpret_cast<char const(&)[std::size(array_of_string1)][6]>(array_of_string1);
char const(*p_array_of_string2)[std::size(array_of_string1)][6] = reinterpret_cast<char const(*)[std::size(array_of_string1)][6]>(&array_of_string1);
for (int i = 0; i != 3; ++i)
{
for (int j = 0; j != 6; ++j)
{
std::cout << i << "," << j << " " << array_of_string2[i][j] << " " << (*p_array_of_string2)[i][j] << std::endl;
}
}
}
why this code gives the wrong output?? Output is 5 and 9, shouldn't it be 5 and 4.
Here is the code
int main
{
char a[10] ={'a','b','c','d','e'};
char c[] = {'q','t','y','t'};
cout<<strlen(c)<<endl<<strlen(a);
return 0;
}
You have undefined behaviour, because you're calling strlen with a pointer to a character array that is not null-terminated (c). You need to pass null-terminated strings for this to work. This is an example, fixing that and some other errors, and including the required headers:
#include <iostream> // std:cout, std::endl
#include <cstring> // std::strlen
int main()
{
char a[10] ={'a','b','c','d','e'}; // OK, all remaining elements
// initialized to '\0'.
// Alternative: char a[10] = "abcde"
char c[] = {'q','t','y','t', '\0'}; // or char c[] = "qtyt";
std::cout << std::strlen(c) << std::endl;
std::cout << std::strlen(a) << std::endl;
}
c needs a null character at the end for strlen to work.
You can use
char c[N] = {'q','t','y','t'};
where N is 5 or greater.
or
char c[] = {'q','t','y','t', '\0'};
or
char c[] = "qtyt";
to add a null character at the end of c.
I have a homework, It is:
Write the code of function below, this function should count number of bytes inside of s till it is not '\0'.
The function:
unsigned len(const char* s);
Really I do not know what this homework mean, can anyone write this homework's code please?
Further more can anyone please explain what does "Const char* s" mean? If you can explain with some examples it would be perfect.
Here is a code which I'm trying to do:
unsigned len(const char* s)
{
int count=0;; int i=0;
while (*(s+i)!=0)
{
count++;
i++;
}
return count;
}
But in the main function I do not know what should I write, BTW I have written this:
const char k='m';
const char* s=&k;
cout << len(s) << endl;
The result always is 4! really I do not know what should I do for this question, if I can store only one character in const char, so the result should be the same always. What this question is looking for exactly?
The homework means you should write a function that behaves like this:
int main() {
char s[] = {'a','b','c','\0'};
unsigned s_length = len(s);
// s_length will be equal to 3 ('a','b','c', not counting '\0')
}
I think it's unlikely that anyone will do you homework for you here.
Presumably your class has covered function parameters, pointers, and arrays if you're being asked to do this. So I guess you're asking about const. const char* s means that s points to a const char, which means you're not allowed to modify the char. That is, the following is illegal:
unsigned len(const char *s) {
*s = 'a'; // error, modifying a const char.
}
Here are the basic things you need to know about pointers to write the function. First, in this case the pointer is pointing at an element in an array. That is:
char A[] = {'a','b','c','\0'};
char const *s = &A[0]; // s = the address of A[0];
The pointer points to, or references, a char. To get that char you dereference the pointer:
char c = *s;
// c is now equal to A[0]
Because s points at an element of an array, you can add to and subtract from the pointer to access other elements of the array:
const char *t = s+1; // t points to the element after the one s points to.
char d = *t; // d equals A[1] (because s points to A[0])
You can also use the array index operator:
char c = s[0]; // c == A[0]
c = s[1]; // c == A[1]
c = s[2]; // c == A[2]
What would you used to look at each element of the array sequentially, with an increasing index?
Your proposed solution looks like it should work correctly. The reason you're getting a result of 4 is just coincidence. You could be getting any results at all. The problem with the way you're calling the function:
const char k='m';
const char* s=&k;
cout << len(s) << endl;
is that there's no '\0' guaranteed to be at the end. You need to make an array where one of the elements is 0:
const char k[] = { 1,2,3,0};
const char* s = &k[0];
cout << len(s) << '\n'; // prints 3
char m[] = { 'a', 'b', 'c', 'd', '\0', 'e', 'f'};
cout << len(m) << '\n'; // prints 4
char const *j = "Hello"; // automatically inserts a '\0' at the end
cout << len(j) << '\n'; // prints 5
In C (and by extension C++), strings can be represented as a sequence of characters terminated by a null character. So, the string "abc" would be represented as
'a', 'b', 'c', '\0'
This means, you can get the length of a C string by counting each character until you encounter a null. So if you have a null terminated const char* string, you can find out the length of that string by looping over the string and incrementing a counter variable until you find the '\0' character.
it means you have a string like hello world Every string terminates with a \0. That means it looks like this: hello world\0
Now step over the char array (char* s) until you find \0.
Update:
\0 is in fact only one single character of value 0x00. \ is used to tell visualize that this is meant instead of the number 0 in a string.
Example:
0abc\0 -> string starting with number 0 and is terminated with 0x0.
EDIT
char * indicates the type of the variable s. It is a pointer to a character array. const means that this character array is readonly and can't be changed.
Do you actually mean "count the characters till you find a '\0'"?
If so, you could implement it like this:
for each character
if it is not 0
increment x (where x is variable holding number of characters found)
otherwise
stop looking
return x
I am not going to write your homework as well :P, but let me give you some hint: it's called "pointer arithmetic". So, a pointer is a thing exactly just as it names says: a pointer to a memory "cell". As you know all variables in the memory are stored in "cells", that you can refer by an address. A C string is stored in continuous cells in the memory, so for example "abc" would look like something like (the '\0' is added by the compiler when you define a string literal with quotes):
+----+----+----+----+
|'a' |'b' |'c' |'\0'|
+----+----+----+----+
^
s
and you also get the address of the first char. Now, to get the address of 'b', you can simple add one to s like this: (s + 1). To get what is actually in the cell where s points to, you should use the * operator:
*s = 'a' or *(s + 1) = 'b'. This is called pointer arithmetic.
Note: in this case adding one to the pointer shifts to the next cell, because char is one byte long. If you define a pointer to bigger structure (long int for example of 4 bytes) adding one will move to the to the position in the memory where your next structure would begin (in case of long int it will move +4 bytes).
Now that should be enough help to finish your hw.
OK , I have found my answer, just check if I'm true:
#include <iostream>
using namespace std;
unsigned len(const char*);
int main()
{
const char* s = "Hello";
cout << len(s) << endl;
return 0;
}
unsigned len(const char* s)
{
int count=0;; int i=0;
while (*(s+i)!=0)
{
count++;
i++;
}
return count;
}
So it is showing that I have set "Hello" into const char* s; So for const char* variables I should use strings like "Hello" with the sign ("). Is that True?