How to compare litere with an array of char with "(" - c++

I have problem to compare litere with an array of char with "(". I need a function to compare each array element with sign, but i don't know how to do it? Please help me.
#include<iostream>
using namespace std;
int v( const string &p )
{
int lvl=0;
int indeks=-1;
for(int i=0;i<=p.size();i++)
{
if(p[i]=="(")
lvl--;
// else if(p[i]=="}")
// lvl++;
// else if(p[i]=="+")
//indeks=i;
//cout<<p[i]<<'\n';
}
//cout<<lvl;
}
int main()
{
//string j;
string p;
cin>>p;
v(p);
getchar();
}

Compare with '('.
Single quote '' is used for character.
Double quote "" is used for strings.

Related

Garbage values are printing even after null character

This code is for printing left recursion alternatives in a production.But when printing alternatives at last garbage values are being added.Why am i getting such error?
how to resolve such problem?in the image the output is displayed.but that is the wrong output
#include<iostream>
#include<cstring>
using namespace std;
class production
{
private:
char lhs;
char rhs[10][10],lr[10][10];
int noa;
public:
production()
{
noa=0;
}
void makeprod(char *str)
{
lhs=str[0];
char r[20];
strcpy(r,str+3);
int j=0;
for(int i=0;r[i]!='\0';i++)
{
if(r[i]!='/')
rhs[noa][j++]=r[i];
else
{
rhs[noa++][j]='\0';
j=0;
}
}
noa++;
}
void checkLR()
{
int ct=0,m=0;
for(int i=0;i<noa;i++)
if(lhs==rhs[i][0])
{
strcpy(lr[m],rhs[i]);
m++;
ct++;
}
if(ct>0)
{
for(int k=0;k<ct;k++)
cout<<"Left recursion at "<<lr[k]<<"\n";
}
else
cout<<"no\n";
}
void printprod()
{
cout<<"LHS = "<<lhs<<"\n";
cout<<"RHS = ";
for(int i=0;i<noa;i++)
cout<<rhs[i]<<" ";
}
};
int main()
{
production p;
char str[20];
cout<<"enter a production\n";
cin>>str;
p.makeprod(str);
p.printprod();
p.checkLR();
return 0;
}
In makeprod you're checking your input string for / to add the termination character to your rhs-array, and thus your input string has to end with the / sign. You have several choices :
either initialize your arrays with 0, so the rhs-array is always null-terminated (independently from your question : It's always good practice to initialize your variables)
add a null-termination sign (0) to rhs when the end of your input string is reached
edit: Just place a memset(rhs, 0, sizeof(rhs)*sizeof(char)); (the same for lr) in your constructor and the output should be fine. This will initialize your arrays with zeroes and thus the string is null-terminated.
But you really should add some overflow checking.
You are propably incrementing noa one time too much in makeprod().
That makes the for loop in printprod() access rhs 1 element after its end.

Debug my reimplementation of strtok and split

I'm supposed to be writing code that takes a string of comma separated values without spaces (ex. my,name,is,jack). First we had to write a function
string nextstring(string str, int start_index)
that returns a single "value" from your initial string depending on the start index. The second part of the problem was to write a function
int split(string str, string a[], int max_size)
that will identify all the values in the initial string and put them in a string array and then return the total number of values stored in the array; i.e. if you had initially input my,name,is it would return 3.
My function never returns the correct value and whatever it returns changes depending on what the length of the words are.
#include <iostream>
#include <string>
using namespace std;
string nextstring(string str, int start_index);
int split(string str, string a[], int max_size);
int main()
{
string str;
int cnt;
string a[100];
cout<< "what is your string" << endl;
getline(cin, str);
cnt= split(str, a, 100);
cout << "There are " << cnt << " values in this string" << endl;
for(int i=0; i<cnt; i++)
{
cout << a[i] << endl;
}
return 0;
}
string nextstring(string str, int start_index)
{
string ans;
if(str[start_index] == ',' || str[start_index] == '\0')
{
ans=" ";
}
else{
ans=str[start_index]+nextstring(str, start_index+1);
}
return ans;
}
int split(string str, string a[], int max_size)
{
int j=0;
int ans=0;
double k=0;
while(j<max_size)
{
a[j]= nextstring(str,k);
string check=a[j];
if(isalpha(check[0])!= 0)
{
ans++;
}
k=k+a[j].length();
j++;
}
return ans;
}
It seems that your problem is that while(j<max_size){...} leads to j being incremented up to max_size. The line a[j]= nextstring(str,k); is at some points reading values that are outside your string which is really bad!
Replacing while(j<max_size){...} by while(j<max_size && k<str.length()){...} seems to be enough to make your code work!
Apart from that:
k has no reason to be a double! It should be an int (or something similar).
Since you are already using string, you should also learn to use vector. split is better written as:
int split(string str, vector<string> &a, int max_size)
{
int ans=0;
int k=0;
while(k<str.length())
{
string next = nextstring(str,k);
if(isalpha(next[0])!= 0)
{
ans++;
a.append(next);
}
k += next.length();
}
return ans;
}
The problem in your approach is to identify the end of the string, as there is no null terminator in a c++ string. Consider to update nextstring() to look for the end of string in a different manner:
string nextstring(string str, int start_index)
{
...
if(start_index == str.size() || str[start_index] == ',' ) //<===
{
ans=" ";
}
...
}
online demo
Additional recommendation
Note that it is not very nice to return a blank string when in reality it should be empty to reflect its real value (e.g. ",,"). You have no choice because otherwise you would have no mean in the calling function, to determine that the end of string was reached. But the consequence is thar all your strings have a trailing blank.
When you call recursively the function adding char to build the return string, you risk to have a considerable overhead. You could consider avoiding this, by replacing the else part:
ans=str.substr(start_index, str.find(',', start_index+1)-start_index);
However, as you have no trailing blank anymore, you need to adapt split() so to adapt its way to count the total number of chars parsed:
k=k+a[j].length()+1; // +1 because there's no longer a trailing blank.
Online demo

what is the issue with the below code?

The question is to replace the spaces contained in a string with a "%20". So basically need to insert this in a string wherever there is a space. Therefore, I want to replace all spaces with %20 but only partial string is getting replaced. I can see the correct o/p in the replace function
#include<iostream>
#include<string>
using namespace std;
int spaces(char* s,int size) /*calculate number of spaces*/
{
int nspace=0;
for(int i=0;i<size;i++)
{
if(s[i]==' ')
{
nspace++;
}
}
return nspace;
}
int len_new_string(char* inp,int l) /*calculate the length of the new string*/
{
int new_length=l+spaces(inp,l)*2;
return new_length;
}
char* replace(char* s,int length) /*function to replace the spaces within a string*/
{
int len=len_new_string(s,length);
char new_string[len];
int j=0;
for(int i=0;i<length;i++)
{
if(s[i]==' ') /*code to insert %20 if space is found*/
{
new_string[j]='%';
new_string[j+1]='2';
new_string[j+2]='0';
j=j+3;
}
else /*copy the original string if no space*/
{
new_string[j]=s[i];
j++;
}
}
cout<<"Replaced String: "<<new_string<<endl;
return s=new_string;
}
int main()
{
char str[]="abc def ghi ";
int length=sizeof(str)/sizeof(str[0]);
cout<<"String is: "<<str<<endl;
char *new_str=replace(str,length);
cout<<"Replaced String is: "<<new_str<<endl;
}
The char array should go out of scope and be released. The only reason you don't get a segfault is that apparently no other program has reserved the memory in that spot yet. To avoid this, try using a char array with padding, handing it over by reference or pointer and filling it in place:
void replace(char *in, char *out, size_t length)
{
/* copy as-is for non-spaces, insert replacement for spaces */
}
int main()
{
char str[]="abc def ghi";
size_t buflen(strlen(str)+2*spaces(str, strlen(str)));
char output[buflen+1];
memset(output, 0, buflen+1);
replace(str, output, strlen(str));
}
Another option is to new[] the return array (remember to delete[] it afterwards, then!) or, which I think you left out for a reason, use std::string all along to avoid the array issue.

reverse a string using pointers

I have to admit, i have no idea how to use pointers, but I tried non the less. the problem with my program is that it shows the string in reverse, except for what was the first letter being missing and the entire string is moved one space forward with the first element being blank.
for example it show " olle" when typing "hello".
#include <iostream>
#include <string>
using namespace std;
string reverse(string word);
int main()
{
char Cstring[50];
cout<<"enter a word: ";
cin>>Cstring;
string results = reverse(Cstring);
cout <<results;
}
string reverse(string word)
{
char *front;
char *rear;
for (int i=0;i< (word.length()/2);i++)
{
front[0]=word[i];
rear[0]=word[word.length()-i];
word[i]=*rear;
word[word.length()-i]=*front;
}
return word;
}
The new code works perfectly. changed the strings to cstrings. the question technicaly asked for cstrings but i find strings easier so i work with strings then make the necesary changes to make it c string. figured out ho to initialize the rear and front as well.
#include <iostream>
#include <cstring>
using namespace std;
string reverse(char word[20]);
int main()
{
char Cstring[20];
cout<<"enter a word: ";
cin>>Cstring;
string results = reverse(Cstring);
cout <<results;
}
string reverse(char word[20])
{
char a='a';
char b='b';
char *front=&a;
char *rear=&b;
for (int i=0;i< (strlen(word)/2);i++)
{
front[0]=word[i];
rear[0]=word[strlen(word)-1-i];
word[i]=*rear;
word[strlen(word)-1-i]=*front;
}
return word;
}
char *front;
char *rear;
then later
front[0]=word[i];
rear[0]=word[strlen(word)-1-i];
Not good. Dereferencing uninitialized pointers invokes undefined behavior.
Apart from that, your code is overly complicated, it calls strlen() during each iteration (and even multiple times), which is superfluous, and the swap logic is also unnecessarily complex. Try using two pointers instead and your code will be much cleaner:
void rev_string(char *str)
{
char *p = str, *s = str + strlen(str) - 1;
while (p < s) {
char tmp = *p;
*p++ = *s;
*s-- = tmp;
}
}
The thing is, however, that in C++ there's rarely a good reason for using raw pointers. How about using std::reverse() instead?
string s = "foobar";
std::reverse(s.begin(), s.end());
inline void swap(char* a, char* b)
{
char tmp = *a;
*a = *b;
*b = tmp;
}
inline void reverse_string(char* pstart, char* pend)
{
while(pstart < pend)
{
swap(pstart++, pend--);
}
}
int main()
{
char pstring[] = "asfasd Lucy Beverman";
auto pstart = std::begin(pstring);
auto pend = std::end(pstring);
pend -= 2; // end points 1 past the null character, so have to go back 2
std::cout << pstring << std::endl;
reverse_string(pstart, pend);
std::cout << pstring << std::endl;
return 0;
}
you can also do it like this:
#include <iostream>
#include <cstring>
using namespace std;
string reverse(char word[20]);
int main()
{
char Cstring[20];
cout<<"enter a word: ";
cin>>Cstring;
string results = reverse(Cstring);
cout <<results;
}
string reverse(char word[20])
{
char a='a';
char b='b';
char *front=&a;
char *rear=&b;
for (int i=0;i< (strlen(word)/2);i++)
{
*front=word[i];
*rear=word[strlen(word)-1-i];
word[i]=*rear;
word[strlen(word)-1-i]=*front;
}
return word;
}
it successfully works on my system ,i.e. on emacs+gcc on windows 7
Taken from C How To Program Deitel & Deitel 8th edition:
void reverse(const char * const sPtr)
{
if (sPtr[0] == '\0')
return;
else
reverse(&sPtr[1]);
putchar(sPtr[0]);
}

passing vector<char> to a pointer char*

how do I pass a char vector to a char*? I know this problem could easily be solved with a predefined char[] array with a SIZE const, but I want the flexibility of a vector because there will be no predefined size.
using namespace std;
//prototype
void getnumberofwords(char*);
int main() {
//declare the input vector
vector<char> input;
/*here I collect the input from user into the vector, but I am omitting the code here for sake of brevity...*/
getnumberofwords(input);
//here is where an ERROR shows up: there is no suitable conversion from std::vector to char*
return 0;
}
void getnumberofwords(char *str){
int numwords=0;
int lengthofstring = (int)str.size();
//this ERROR says the expression must have a case
//step through characters until null
for (int index=0; index < lengthofstring; index++){
if ( *(str+index) == '\0') {
numwords++;
}
}
}
You can use data() member to get the pointer to the underlying array:
getnumberofwords(input.data());
The most obvious is to pass &your_vector[0]. Be sure to add a NUL to the end of your vector first though.
Alternatively, use std::string instead of std::vector<char>, in which case you can get a NUL-terminated string with the c_str member function.
Edit: I have to wonder, however, why getnmberofwords would be written to accept a char * unless it's some old C code that you just can't get away from using.
Given a typical definition of "word" counting some words that start out in a string can be done something like this:
std::istringstream buffer(your_string);
size_t num_words = std::distance(std::istream_iterator<std::string>(buffer),
std::istream_iterator<std::string>());
You should pass the reference of the vector to the function getnumberofwords.
void getnumberofwords(vector<char>& str){
int numwords=0;
int lengthofstring = str.size();
for (int index=0; index < lengthofstring; index++){
if ( str[index] == '\0') {
numwords++;
}
}
}
There is no method for converting the type from vector to pointer.
here's what I ended up doing which worked:
#include <iostream>
#include <cstring>
#include <string>
#include <iomanip>
using namespace std;
//prototype
void getnumberofwords(char*);
void getavgnumofletters(char*, int);
int main() {
const int SIZE=50;
char str[SIZE];
cout<<"Enter a string:";
cin.getline(str, SIZE);
getnumberofwords(str);
return 0;
}
void getnumberofwords(char *str){
int numwords=0;
int lengthstring=strlen(str);
//step through characters until null
for (int index=0; index < lengthstring; index++){
if (str[index] ==' ') {
numwords++;
}else{
continue;
}
}
numwords+=1;
cout<<"There are "<<numwords<<" in that sentence "<<endl;
getavgnumofletters(str, numwords);
}
void getavgnumofletters(char *str, int numwords) {
int numofletters=0;
double avgnumofletters;
int lengthstring=strlen(str);
//step through characters until null
for (int index=0; index < lengthstring; index++){
if (str[index] != ' ') {
numofletters++;
}else{
continue;
}
}
avgnumofletters = (double)numofletters/numwords;
cout<<"The average number of letters per word is "<<setprecision(1)<<fixed<<avgnumofletters<<endl;
}
/*