Different output with string and char array - c++

When I am using the following code to convert an string to a float, it is working fine. But the next code gives the error. Please tell me why is this happening? String is a char array only is what I read.
Code1 (working)
#include<iostream>
#include<stdlib.h>
using namespace std;
int main()
{
char str[]="301.23";
float f=atof(str);
cout<<sizeof(str)<<" is size with contents "<<str<<endl;
cout<<sizeof(f)<<" is size with contents "<<f<<endl;
return 0;
}
Code 2(not working)
#include<stdlib.h>
#include<string>
#include<iostream>
using namespace std;
int main()
{
string str="301.23";
float f=atof(str);
cout<<sizeof(str)<<" is size with contents "<<str<<endl;
cout<<sizeof(f)<<" is size with contents "<<f<<endl;
return 0;
}
Error:
error: cannot convert std::string to const char* for argument 1 to double atof(const char*)
Please help

std::string is not a char array.
Use str.c_str() to get a const char* and you should be fine

Syntax:
#include <stdlib.h>
double atof( const char *str );
The input string is a sequence of characters that can be interpreted as a numeric value of the specified return type.
The function stops reading the input string at the first character that it cannot recognize as part of a number. This character can be the null character that ends the string.
The atof() function expects a string in the following form:
Read syntax diagramSkip visual syntax diagram
>>-+------------+--+-----+--+-digits--+---+--+--------+-+------->
'-whitespace-' +- + -+ | '-.-' '-digits-' |
'- – -' '-.--digits-----------------'
Therefore your problem lies in the atof funcion which is not designed to accept string at it doesn't store characters in integer form.
Hope this helped.. :D

Try using #include<cstring> in place of #include <string>
Technically, You're only guaranteed std::string, but all popular implementations just pull in the C header and add a using statement...
is a C++ standard library include, and is C standard library include.

Related

How & makes a reference to a string variable in C++?

I am little confused about the use of & literal with strings. I see a big difference in the output of following two codes:
#include <iostream>
using namespace std;
int main()
{
char st[]="This is a Sample String";
cout<<st[0];
return 0;
}
Output: T
#include <iostream>
using namespace std;
int main()
{
char st[]="This is a Sample String";
cout<<&st[0];
return 0;
}
Output: This is a Sample String
I know & is used as a reference operator to pass the value by reference. But my question is how & actually works here.
Array of characters is also called string in C++. And in C++ if you want to print the Starting address of the string then it will not print the starting address of the string it will print the whole string.
The operator& have different meaning in different situation in C++. And the meaning of & is decided by its context(where it is using).

Warnings and Errors with declaration of multi-character character

Screenshot 1
Here's my code.
#include<iostream>
#include<conio.h>
#include<string.h>
using namespace std;
class Dragon
{
public:
char element[30];
int energy;
};
int main()
{
Dragon dragon;
char name[30];
cout<<"Enter element.\n\n";
cin>>name;
if(name=='Hell')
{
strcpy(dragon.element,"Hell Dragon");
dragon.energy=15000000;
}
else if(name=='Dark')
{
strcpy(dragon.element,"Dark Dragon");
dragon.energy=1000000;
}
else
cout<<"Unknown Dragon.";
cout<<"\nDragon's element = "<<dragon.element<<"\nDragon's energy level = "<<dragon.energy;
getch();
return 0;
}
Just tried this program on my own in C++ and have problems in fixing the following errors-
Errors and Warnings
If you do have an idea on how I can modify this, please help me out.
Thank you.
One cause of your issues is that == can't be used to compare contents of character arrays.
Solution 1: Use std::string
The std::string data type is the preferred data structure in C++ for text strings.
The std::string has overloaded == for comparing strings.
The std::string also has a find method for searching for a substring.
Solution 2: Use strcmp
The C language uses character arrays for strings. The C language also has str*() functions for processing character arrays.
The C++ language uses the str*() functions for processing the C-Style strings (character arrays).
Use strcmp to compare character arrays with string literals:
if (strcmp(name, "Hell") == 0)
You may also want to use strstr for finding substrings or strchr for finding characters in a character array (C-style string).

no matching function for call to c++ string error

I am trying this code to perform the following function : given an input file and a word(string) output should be the lines in the file containing the given word along with the line number. But I am getting an error saying "no matching function for call to ..." in the line where I am performing string operation (strstr). Here is my code. Please help me solve this. I am facing the same error in other programs also where ever I perform operations involving strings.
#include<iostream>
#include<fstream>
#include<string.h>
#include<stdio.h>
using namespace std;
int main()
{
int x;
char c;
ifstream iFile1, iFile2;
ofstream oFile;
char file1[50], file[50];
char word[50];
cout << "First file?\n";
gets(file1);
std::string str;
cout << "Word?\n";
gets(word);
iFile1.open(file1);
while (std::getline(iFile1, str)) {
x++;
if (strstr(str, word)) {
cout << "%d\t,x";
cout << str;
}
}
}
error: no matching function for call to 'strstr(std::string&,char[50])'
if(strstr(str,word))
^
char * strstr (char * str1, const char * str2 );
This is the signature of the strstr function, which requires both elements to be char*, but you are passing as first element a std::string&.
To fix this, try:
if (strstr(str.c_str(), word))
The c_str() method returns a char * to an array that contains the elements of the string
Also please note that the gets function is deprecated
Not the right answer, but still important to point out:
<string.h> is not <string>
<string.h>, and <cstring>, are header files defining several functions to manipulate C Strings and arrays (Source)
<string> defines std::string, which has the handy member function .c_str() allowing you to use functions which want a parameter of char*

Converting Const char * to Unsigned long int - strtoul

I am using the following code to convert Const char * to Unsigned long int, but the output is always 0. Where am I doing wrong? Please let me know.
Here is my code:
#include <iostream>
#include <vector>
#include <stdlib.h>
using namespace std;
int main()
{
vector<string> tok;
tok.push_back("2");
const char *n = tok[0].c_str();
unsigned long int nc;
char *pEnd;
nc=strtoul(n,&pEnd,1);
//cout<<n<<endl;
cout<<nc<<endl; // it must output 2 !?
return 0;
}
Use base-10:
nc=strtoul(n,&pEnd,10);
or allow the base to be auto-detected:
nc=strtoul(n,&pEnd,0);
The third argument to strtoul is the base to be used and you had it as base-1.
You need to use:
nc=strtoul(n,&pEnd,10);
You used base=1 that means only zeroes are allowed.
If you need info about integer bases you can read this
The C standard library function strtoul takes as its third argument the base/radix of the number system to be used in interpreting the char array pointed to by the first argument.
Where am I doing wrong?
nc=strtoul(n,&pEnd,1);
You're passing the base as 1, which leads to a unary numeral system i.e. the only number that can be repesented is 0. Hence you'd get only that as the output. If you need decimal system interpretation, pass 10 instead of 1.
Alternatively, passing 0 lets the function auto-detect the system based on the prefix: if it starts with 0 then it is interpreted as octal, if it is 0x or 0X it is taken as hexadecimal, if it has other numerals it is assumed as decimal.
Aside:
If you don't need to know the character upto which the conversion was considered then passing a dummy second parameter is not required; you can pass NULL instead.
When you're using a C standard library function in a C++ program, it's recommended that you include the C++ version of the header; with the prefix c, without the suffix .h e.g. in your case, it'd be #include <cstdlib>
using namespace std; is considered bad practice

Write a program that reads a string of characters including punctuation and writes what was read but with the punctuation removed

Here's my attempt at it:
#include <iostream>
#include<string>
using namespace std;
int main()
{
string s("hello world!..!.");
for (auto &c : s)
if(!ispunct(c))
{
cout<<s;
}
}
Here's the output
hello world!..!.hello world!..!.hello world!..!.hello world!..!.hello world!..!.
hello world!..!.hello world!..!.hello world!..!.hello world!..!.hello world!..!.
hello world!..!.
Here's another attempt:
#include <iostream>
#include<string>
using namespace std;
int main()
{
string s("hello world!..!.");
for (auto &c : s)
if(!ispunct(c))
{
cout<<c;
}
}
This gives the correct output (i.e : hello world)
Why won't cout<<s; give me the correct output? After all c is a reference, so any changes to c would also apply to s. Or am I wrong about this?
This is why i don't really like the auto feature, auto in your case is a char and there is no elimination from the string.
LE: ispunct doesn't remove the character from the string, it doesn't even know (or care) that you have a string, it only returns true if the character is punctuation character or false if not, and based on that return the cout statement is executed with the character that is not punctuation or not executed for punctuation character.
s is the entire string, so cout<<s sends the entire string to your output stream :\
Your second attempt works because you're sending individual characters to the stream. In the first attempt though, you're sending the whole string for each character that exists in the string. Count the number of non-punct characters in your string, then count the number of times the string was printed out ;)
ispunct does not eliminate the character that is a punct. It only returns 0 or non-zero to indicate
if it is punct or no.
When you encounter a character that is not punct, it returns 0. And you enter your if. You are printing s that is the whole string.
Whereas, with cout<<c you only print the character (which is non punct, since you are now in the loop)
One more variant, using STL algorithms:
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
using std::cout;
using std::endl;
using std::string;
using std::back_inserter;
using std::copy_if;
int main()
{
string s("hello world!..!.");
string result = "";
copy_if(begin(s), end(s),
back_inserter(result),
[](char c){return !ispunct(c);}
);
cout << result << endl;
}
For real world code it's recommended to prefer suitable STL algorithms if available over a loop, because saying copy_if states your intent clearly, and does not focus on the individual steps to take. Whether or not it's better in this example I don't want to judge. But it's certainly good to keep this possibility in mind!
One more thing: It's generally regarded a bad thing to write using namespace std, because this can lead to name collisions when a future version of C++ introduces new keywords which you've already defined yourself in your own code. Either use the prefix std:: all the time, or follow the way I've shown in my example, this keeps your code safe.