I am trying to write code to check whether two C-string variables are the same barring the difference of capitalization. Given the two input books BOOKS, the program should return 1, and with Incorrect correct, it should return 0. My code doesn't print it accurately.
#include <iostream>
#include <cctype>
#include <cstring>
using namespace std;
int Judge_Char(const char* str1,const char* str2){
char first[20],second[20];
for(int i=0;i<20;i++){
first[i]=str1[i];
second[i]=str2[i]; //assigned pointers to variable
} //bc I didn't know other ways to compare
int k=0,l=0;
for(k=0;first[k]!='\0';k++);
for(l=0;second[l]!='\0';l++); //got the length of the chars here
for(int i=0;i<k;i++){
first[i]=toupper(first[i]);
} //i converted them to same case here
for(int i=0;i<l;i++){
second[i]=toupper(second[i]);
}
for(int n=0;n<k;n++){
for(int m=0;m<l;m++){
if(first[n]==second[m]){
return 1; // i check whether they are same or not
}
else{
return 0;
}
}
}
}
int main()
{
char a[20],b[20];
cin>>a>>b;
int flag=Judge_Char(a,b);
cout<<flag<<endl;
return 0;
}
Two things annoy me about C++:
There is no standard definition for pi (yet we have an extremely sophisticated random number library some of which requires a value for pi to be defined for it to be implementable).
There is no standard way of comparing two strings on a case-insensitive basis. A subset of the general case compare problem is defined by isupper, islower, toupper, and tolower. Yes indeed a full locale-aware case-insensitive compare is beyond the scope of the C++ standard library, but one could be conceived in simpler terms.
In Windows you use ::_stricmp and #include <string.h>
In Unix you use strcasecmp and #include <strcasecmp>
An example where it's useful, even if it doesn't support the German SS, Norwegian Slashed o, &c. &c.
struct iLT
{
bool operator()(const std::string& lhs, const std::string& rhs) const {
return strcasecmp(lhs.c_str(), rhs.c_str()) < 0;
}
};
typedef std::map<std::string, double, iLT> MapWithCaseInsensitiveKeys;
Related
I want to write a function which takes as input a pointer to a vector pointer which point to a string (Dictionary) and a pointer which points to a char (p). The function will check if the char is in the Dictionary and if it isn't there it adds the p in the vector Dictionary.
My code:
#include <iostream>
#include <string>
#include <vector>
using std::string;
using std::vector;
std::vector<string *> dictionary;
void manageDictionary(vector<string *> * dictionary, char *p) {
for (unsigned int i = 0; i < (*dictionary).size(); i++) {
string * pstring = (*dictionary).at(i);
if ((*pstring).compare(p)) {
(*dictionary).push_back(p);
}
}
}
However, the visual studio compiler shows I have an error in the if statement just before the push_back method (.). When I hover on the error, it says "no instance of overloaded function".
I added the std::vector<string *> dictionary; at the beginning, still cannot figure out where the problem is.
dictionnary is a vector of std::string*. std::string* and char* are totally unrelated types. To convert from char* to std::string* will require you to create a new string that contains the value of p for your dictionnary, rather than passing a char* directly. This change will allow your example to compile, but the resulting function is error prone.
#include <string>
#include <vector>
using std::string;
using std::vector;
void manageDictionnary(vector<string *> * dictionnary, char *p) {
for (unsigned int i = 0; i < (*dictionnary).size(); i++) {
string * pstring = (*dictionnary).at(i);
if ((*pstring).compare(p)) {
(*dictionnary).push_back(new string(p));
// Make a new string ^^^^^^^^^^
}
}
}
This solution will require you to delete your strings manually which is not the way things are done in c++. Changing from std::vector<std::string*> to simply std::vector<std::string> will solve this problem, and avoid you headaches in the future. There are other unnecessary pointers that can be removed. Since at(i) returns a string& then we should change pstring to string&. Since dictionnary is not optional (can't be nullptr) and always points to the same vector we can also change it to a vector<string>&.
void manageDictionnary(vector<string> & dictionnary, char *p) {
for (unsigned int i = 0; i < dictionnary.size(); i++) {
string & pstring = dictionnary.at(i);
if (pstring.compare(p)) {
dictionnary.push_back(p);
}
}
}
This latest version will work fine and is much more in line with c++'s philosophy for resource management. I recommend you read on a few topics :
Standard algorithms like std::find.
Range-based for loops.
const-correctness.
pointer vs reference.
Additionally, consider using std::set<string> or std::unordered_set<string> for a more convenient representation of a dictionnary.
In the future, note that the preferred way to access a pointer's methods is ptr->foo() rather than (*ptr).foo().
There are the atox, strtox and stox families that I know of, but I can't seem to find any iterator based string to int conversions in the Standard Library or Boost.
The reason I need them is because I am having a parser whose match result is a range referencing the input string. I might very well have an input string like
...8973893488349798923475...
^begin ^end
so I need 738934883 as an integer.
Of couse, I could first take begin and end to construct an std::string to use with any of above families, but I would very much like to avoid that overhead.
So my question: Is there anything in the Standard Library or Boost accepting iterators as input, or do I have to write my own.
Boost does actually support this, using the Lexical Cast library. The following code uses a substring range to parse the number without performing any dynamic allocation:
#include <boost/lexical_cast.hpp>
#include <string>
#include <iostream>
int convert_strings_part(const std::string& s, std::size_t pos, std::size_t n)
{
return boost::lexical_cast<int>(s.data() + pos, n);
}
int main(int argc, char* argv[])
{
std::string s = "8973893488349798923475";
// Expect: 738934883
std::cout << convert_strings_part(s, 2, 9) << std::endl;
return 0;
}
The output (tested on OS X with Boost 1.60):
738934883
The lexical cast library has some great features for conversion to and from strings, though it isn't as well known as some of the others for some reason.
Until gavinb's answer, I was not aware of any such library function. My try would have been this, using any of atox and strtox as follows (you could avoid a dependency on boost library then, if wanted):
::std::string::iterator b; // begin of section
::std::string::iterator e; // end of section, pointing at first char NOT to be evaluated
char tmp = *e;
*e = 0;
int n = atoi(&*b);
*e = tmp;
If you only had const_iterators available, you would have to apply a const_cast to *e before modifying.
Be aware that this solution is not thread safe, though.
You could do it with strstream but it was depracated. Below two examples, with strstream and boost arrays:
http://coliru.stacked-crooked.com/a/04d4bde6973a1972
#include <iostream>
#include <strstream>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/copy.hpp>
int main()
{
std::string in = "8973893488349798923475";
// ^^^^^
auto beg = in.begin()+2;
auto end = in.begin()+6;
// strstream example - DEPRECATED
std::istrstream os(&*beg, end-beg);
int n;
std::string ss;
os >> n;
std::cout << n << "\n";
// Boost example
namespace io = boost::iostreams;
int n2;
io::array_source src(&*beg, end-beg);
io::stream<io::array_source> os2(src);
os2 >> n2;
std::cout << n2 << "\n";
return 0;
}
With modern STL implementations std::string(begin,end) is not that bad - SSO eliminates any allocations for strings, smaller than ~15 chars (22 for 64bit).
I was trying to use char* pointers to refer to strings and vector<char> & dynamic arrays & I have a doubt with the following results :-
CODE 1:-
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout<<"executing...\n";
string s="abcde";
char *c=&s[0];
cout<<c<<"\n";
s.~string();
cout<<c<<"\n";
cout<<"executed";
return 0;
}
The output of this code is :-
executing...
abcde
abcde
executed
CODE 2:-
#include <iostream>
#include <vector>
using namespace std;
int main()
{
cout<<"executing...\n";
vector<char> v {'a','b','c','d','e'};
char *p=&v[0];
cout<<p<<"\n";
v.~vector();
cout<<p<<"\n";
cout<<"executed";
return 0;
}
The output for this code is :-
executing...
abcde
executed
CODE 3 (with dynamic arrays):-
#include <iostream>
using namespace std;
int main()
{
cout<<"executing...\n";
char* c=new char[20] {'a','b','c','d','e'};
char *p=c;
cout<<p;
delete[] c;
cout<<"\n"<<p<<"\n";
cout<<"executed";
return 0;
}
The output for this code is similar to CODE 2:-
executing...
abcde
executed
I want to know why CODE 1 produces an output different from CODE 2 & CODE 3 ? What problem does string have that it behaves differently from vector<char> & dynamic arrays ?
All the snippets of code access data that has been deleted, which has no defined behavior. Therefore, any further assumption is meaningless and left to the single case. Whether you're accessing a vector, char*, string there's no difference: it's always the same violation.
Well I guess this example is good enough to show that your objects of string & vector are deleted twice hence leading to undefined behaviour :-
#include <iostream>
using namespace std;
class X
{
int x;
public:
X()
{
cout<<"constructing\n";
}
// other member functions...
~X()
{
cout<<"destroying\n";
}
};
int main()
{
X object;
object.~X();
return 0;
}
Output will be :-
constructing
destroying
destroying
When behaviour is undefined there is no use of thinking about "WHY SUCH AN OUTPUT", etc stuffs !! Even I had a doubt regarding the reference counting of C++ strings but as many people are saying strings are no longer reference counted so CODE 1 is also producing undefined behaviour. However I liked you experimenting with codes. It's necessary to learn a language properly. Keep it up !!!
#include <iostream>
#include <string>
#include <utility>
using namespace std;
string num1="123456789123456789";
std::pair<int*,int*> cpy(){
int a[(num1.size()%9==0)? num1.size()/9 : num1.size()/9+1];
int b[(num1.size()%9==0)? num1.size()/9 : num1.size()/9+1];
return make_pair(a,b);
}
int main(void){
return 0;
}
-------------------------------------------------------
//if by this style, it can be compiled
std::pair<int*,int*> cpy(){
const int N=5;
int a[5];
int b[5];
return make_pair(a,b);
}
I am writing a program to calculate Big Number such as 19933231289234783278, So I need split the number using 1 000 000 000 system
Why can't return a pair by this way?
You can't return a pair this way, because you are passing wrong types. In this case, array doesn't decay to pointer.
If you change the last line in the function to this :
return make_pair(&a[0],&b[0]);
it will compile, but it will still not work, as you are returning pointers to arrays, which are destroyed, once the function cpy() ends.
By the way, variable lenghts array are not standard c++.
You are trying to return pointer to a temporary value. As result the pointers will be point to a garbage.
Also you trying to cast string with decimal notation to integer.
You should return the pair of integers, which will be obtained by parsing the string at the numbers.
You can see the link below.
http://interactivepython.org/runestone/static/pythonds/BasicDS/ConvertingDecimalNumberstoBinaryNumbers.html
Can anyone explain to me why im getting a ".exe has encountered a problem and needs close"error, it compiles and works sometimes when i fiddle with the char array, but when it does work i sometimes get strange characters at the end of the string.
#include <iostream>
using namespace std;
char* StrReverse3(char*);
char* StrReverse3(char* str)
{
char *p;
int length=0,start=0,end=0;
length=strlen(str);
for(start=0,end=length-1;end>= 0,start<=length-1;end--,start++)
{
p[start]=str[end];
}
return p;
}
int main()
{
char str[100]="Saw my reflection in snow covered hills";
StrReverse3(str);
cin.get();
return 0;
}
You are not initializing p. It's an uninitialized pointer that you are writing to.
Since you are writing this in C++, not C, I'd suggest using std::string and std::reverse:
#include <string>
#include <algorithm>
#include <iostream>
int main()
{
std::string str = "Saw my reflection in snow covered hills";
std::reverse(str.begin(), str.end());
std::cout << str;
return 0;
}
Output:
sllih derevoc wons ni noitcelfer ym waS
See it working online at ideone
char *p; is never initialized, yet p[start] is used as the destination of an assignment. Don't you get compiler warnings from this? I'm amazed it even "works sometimes".
You are accessing memory that wasn't allocated by your program (p can point anywhere!). This is the reason for the problems you have.
I strongly encourage you to
read into the topic of dynamically allocating memory with new and delete to understand a very important topic
read into the standard template library, especially std::string. You should not use raw pointers like char*, always use standard types when possible.
#include <iostream>
#include <cstring>
using namespace std;
char* StrReverse3(char* str){
int length=0,start=0,end=0;
length=strlen(str);
for(start=0,end=length-1;end > start;end--,start++){
char temp;
temp = str[start];
str[start]=str[end];
str[end]=temp;
}
return str;
}
int main(){
char str[100]="Saw my reflection in snow covered hills";
cout << StrReverse3(str);
cin.get();
return 0;
}