Initializing a string with a single character - c++

I want to initialize a std::string with a single character. The following code doesn't work:
int main()
{
string s = 'c';
cout<<s;
return 0;
}
Error:
error: conversion from ‘char’ to non-scalar type ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’ requested
string s = 'c';
But the following does work. Why is it so?
int main()
{
string s;
s = 'c';
cout<<s;
return 0;
}
Output:
c[Finished in 0.8s]

When you do
string s = 'c';
you are basically invoking constructor initialisation rather than an assignment operation. But there isn’t any constructor for std::string that takes only a single char as input. There is however one std::string(n, c), where n is the number of characters c in the string.
When you do
s = 'c'
you do an assignment operation, invoking the overloaded string::operator= (string& operator= (char c);) for std::string. Now this method is overloaded to accept a single char as input as well, as you can see from the code snippet at this reference as well as at this one.
std::string str1;
// ...
// (4) operator=( CharT );
str1 = '!';
Additionally, std::string::assign doesn’t accept a single char, similar to the constructor.

Related

Getting error while initializing string with string character array? [duplicate]

This question already has answers here:
no viable conversion from 'value_type' (aka 'char') to 'string' (aka 'basic_string<char, char_traits<char>, allocator<char> >')
(1 answer)
Initializing a string with a single character
(1 answer)
Closed 1 year ago.
I'm trying to initialize this string s1 but Idk why I'm getting this error, This may be due to s[0] is character but why everything turns fine when I initialize and declare same string s1 but in diffrent lines, one after another.
#include <bits/stdc++.h>
int main()
{
std::string s = "text";
std::string s1 = s[0];
std::cout << s1;
}
Error:
error: conversion from '__gnu_cxx::__alloc_traits<std::allocator<char>, char>::value_type'
{aka 'char'} to non-scalar type 'std::__cxx11::string' {aka
'std::__cxx11::basic_string<char>'} requested
std::string s1 = s[0];
^
This is working fine:
#include <bits/stdc++.h>
int main()
{
std::string s = "text";
std::string s1;
s1 = s[0];
std::cout << s1;
}
There's no constructor for char. There's a copy assignignment, which works for the second snippet.
However, you can write either like
std::string s1 ( 1, s[0] );
std::string s1 = s[0]; is initialization, it doesn't work because std::string doesn't have any constructor taking a single char.
s1 = s[0]; is assignment, it works because std::string has a operator= taking a single char.
If we take a look at the documentation, we can see that
std::string has no constructor that takes a char type - cppreference.com
It does have an overload for the operator= that can take a
char - cppreference.com
[The copy assignment that takes a char] replaces the contents with
character ch as if by assign(std::addressof(ch), 1)
As to why, consider the fact that the std::string already has so called fill-constructor, string s(n, val), that takes an initial value val and fills the string with n copies of it. So there's no need to have special case for n == 1:
std::string s1 = "text";
std::string s2(1, s[0]); // One char of value s[0]
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s = "text";
string s1;
s1 = s;
cout << s1;
}
the code should work now.

Why cant we assign char to strings?

in C++, I noticed if I make a string str="kls";, then I can't write string s1=str[0];
I have to instead write:
string s1;
s1=str[0];
Why so?
The reason is that the class std::string does not have a constructor that accepts a single argument of the type char. While there is a copy assignment operator that accepts as an argument a single character.
basic_string& operator=(charT c);
You could write
std::string s1( 1, str[0] );
or (there is used the initializating-list constructor)
std::string s1 = { str[0] };
or
std::string s1 = { str, 0, 1 };

Why I can't assign string::back to string?

I write a simple program:
Get last character of string1 and assign it to string2.
It's like:
#include<iostream>
#include<string>
int main(int argc, char const *argv[])
{
std::string s1 = "abc!";
std::string s2 = s1.back();
std::cout << s1;
return 0;
}
However, I get a compile error:
conversion from ‘__gnu_cxx::__alloc_traits<std::allocator<char> >::value_type {aka char}’ to non-scalar type ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’ requested
I don't know this error exactly means.
It's seems like some type conversion error occur.
But the return value of string::back should be char, right?
Why I can't assign it to another string?
And how I can give last character of s1 to s2?
It's because std::string does not have an implicit constructor which takes just a single character parameter, that's why conversion from char to std::string fails. Instead you can use:
// 1. Constructor with length + char
std::string s2(1, s1.back());
// 2. Constructor which takes an std::initializer_list<char>
std::string s2{s1.back()};
A string is a collection of characters, the back of a string is a character (i.e., just an element of the collection), not a string.
You can achieve what you want by using the following constructor overload of std::string:
std::string s2(1, s1.back());
That is, construct s2 as a one-character-length string with the value s1.back().
Hope you are trying to create a new string s2 out of the last character of string s1.
You can achieve that using the solution below:
#include<iostream>
#include<string>
int main()
{
std::string s1 = "abc!";
std::string s2;
s2 = s1.back();
std::cout << s1;
std::cout << s2;
return 0;
}

Swapping two pointers to char in c++ by real call by reference

I am trying to swap two points on const char with real call-by-reference. But I have problems.
void swap(const char *&str1, const char *&str2) { //swap char pointers
const char *one = str1;
str1 = str2;
str2 = one;
}
int main(void){
const char *str1 = "Apple";
const char *str2 = "Potato";
swap(*str1, *str2);
return 0.0;
}
I keep on getting this error:
invalid conversion from 'char' to 'const char'
You shouldn't be dereferences the pointers when calling swap. You need to call:
swap(str1, str2);
Or, better still, use std::swap.
Also, if you're trying to run the code you've written they you'll need to either prototype swap or swap the functions around:
void swap(const char *&str1, const char *&str2)
{
const char *one = str1;
str1 = str2;
str2 = one;
}
int main(void)
{
const char *str1 = "Apple";
const char *str2 = "Potato";
swap(str1, str2);
return 0;
}
Also, main returns an int, not a float
You should use std::swap (located in either the <algorithm> or <utility> header) instead of rolling your own:
std::swap(str1, str2);
Also, you should consider using std::string instead of const char* in general:
std::string str1 = "Apple";
std::string str2 = "Potato";
of course the std::swap algorithm will still work just fine.
And finally, neither void in the argument list of main nor return 0.0 are necessary in C++.
Here's the code revisited with the advices above:
#include <algorithm>
#include <string>
#include <iostream>
int main() {
std::string str1 = "Apple";
std::string str2 = "Potato";
std::swap(str1, str2);
}
and here's the live example.
In response to Mr. Cthulhu down here, I'll try to answer the question more explicitly.
Your error is caused by the fact that by dereferencing the pointers of type const char* you are actually getting an expression of type const char& which is obviously incompatible with the type expressed in your swap function. Here's the correct call to the function:
swap(str1, str2);
But the again, why replicating the code of std::swap? (this is a rhetorical question, in case you were wondering wether to flag this as "not an answer")
You're defining swap() after you're calling it. In C++, functions should be defined before they are called. Move the definition of swap() to the top of the file, above main(). You will then get this error:
test.cpp:11: warning: converting to ‘int’ from ‘double’
Your main() function should return 0 (an int), not 0.0 which is a double.
Fixing this, you'll finally get this error:
test.cpp: In function ‘int main()’:
test.cpp:10: error: invalid initialization of reference of type ‘const char*&’ from expression of type ‘const char’
test.cpp:1: error: in passing argument 1 of ‘void swap(const char*&, const char*&)’
This is because you're dereferencing your arguments to swap(). Remove the * and the program now works fine.
However, you should simply remove your swap() function altogether, #include <utility>, and use std::swap().

Unexpected problems concatenating strings

I'm trying to concatenate strings using +, but there is some weird stuff going on. Here is my "Grade" class I have for a class project:
#pragma once
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Grade {
private:
string className;
string student;
string letter;
public:
Grade(string c, string s, string l) : className(c), student(s), letter(l) {}
string getLetterGrade() const { return letter; }
string getClassName() const { return className; }
string getStudent() const { return student; }
void setLetterGrade(string l) { letter = l; return;}
void setClassName(string c) { className = c; return;}
void setStudnet(string s) { student = s; return;}
string toString() const { string output = "hello"+student; return output; }
};
Obviously, the toString() method isn't currently what I want it to be.
If I run the toString() as above, I get "hello529173860" out, as expected. However, if I change the line to:
string toString() const { string output = student+"hello"; return output; }
then the output is "hello3860". This isn't just putting the hello string on the front, but its replacing characters from the student string in the process... somehow?
Furthermore, if I try to use:
string toString() const { string output = "hello"+" world"; return output; }
I get an error:
Grade.h: In member function ‘std::string Grade::toString() const’:
Grade.h:29:53: error: invalid operands of types ‘const char [6]’ and ‘const char [7]’ to binary ‘operator+’
string toString() const { string output = "hello"+" world"; return output; }
^
I'm really at a loss for what it going on here... especially since I have done string concatenation earlier in the program without issue.
What I would like is to output something like:
"student+[some white space]+letter+[some white space]+className"
A std::string can be added to anything (another std::string, double-quoted string literal, char) and provide intuitive results, but if you try to add a double-quoted string literal to another string literal or a char then it won't "work":
a string literal added to a char or other integral value will undergo Standard Conversion to a const char*, then any number added to the pointer will move along the literal that number of characters: if the offset isn't inside the string literal then you get undefined behaviour if you dereference (use) the resultant pointer,
two string literals just can't be added, even after decaying to two pointers, so you'll get a compile-time error.
Sometimes you will want to explicitly construct a std::string so that concatenation with other values works as you'd like: e.g. my_string = std::string("hello ") + my_const_char_ptr + '\n'.
Examples:
std::string s = "Hello";
s + " World"; // ok
"Hello " + s; // ok
"Hello " + "World"; // NOT ok - two string literals
s += " World"; // ok
s += " Goodbye " + "World"; // NOT ok - "+" evaluated before "+="
s += std::string(" Goodbye ") + "World"; // OK - right-hand-side no longer two literals
// BUT may be slower than two "s +="
The constant strings "hello" and "world" are nothing but compile time constants of type const char*. Just like you cannot add two int pointers:
int *p1, *p2;
p1+p1; // Error
You cannot add two (const) char* objects. This is against the C/C++ language rules. If you must concatenate two const-char-pointers, you can just place them together:
"hello" "world"
This technique is mainly useful if you use them along with macros. For example:
// Over simplified
#define ONE(_x) _x
#define TWO(_x) _X
ONE("This is") TWO(" concatenation")
If you are adding two (or more) runtime C-Strings, you must use strXXX functions (like strcat), or better use std::string.
There is no operator + for character arrays. So it is obvious that this code
string toString() const { string output = "hello"+" world"; return output; }
is invalid.
In this expression "hello"+" world" there are used two string literals that have the types correspondingly const char[6] and const char[7]. The operator + is not defined for arrays.
You could just write
string toString() const { return string( "hello" ) + " world"; }
In this case there is used the operator + overloaded for the class std::string. Declaration of the local variable input is redundant. So you could simplify the function even the following way
string toString() const { return "hello world"; }