C++ Can't compare dereferenced char pointer to char - c++

I have an input string, and I want to find how many spaces are there in the string.
Here's my code
// input string
std::string str = "abc d e f";
// convert string to cstring
char* cstr = new char[str.length()+1];
std::strcpy(cstr, str.c_str());
// iterate through the cstring and count how many spaces are there
int num_of_spaces = 0;
char* ptr = cstr;
while (ptr) {
if (*ptr == ' ') {
++num_of_spaces;
}
++ptr;
}
However, I got an error message on the if (*ptr == ' ') line that says: Thread 1: EXC_BAD_ACCESS (code = 1, address=0x100200000)
Isn't *ptr a char type value because ptr is a char* pointer and I dereferenced it to *ptr. If so, why the comparison is not valid?

You don't want while (ptr), you want while (*ptr), that is, while the thing ptr points to isn't a zero character which marks the end of a C-style string.

Related

const void *pString to string

I have const void *pString which is a Pointer to the string to analyze. Assume it hold a value ABCD, I want to get the string ABCD from it, can someone help ?
When I try to use char *ptr = (char *) pString; then use
ptr[0] it gives A
ptr[1] it gives empty
ptr[2] it gives B
ptr[3] it gives empty and so on.
Use WCHAR string for ScriptStringAnalyse(),
then
...
wstring ws(...);
string str(ws.begin(), ws.end());
...
str[0]
WCHAR helped out here and I was able to get the output using the below snippet:
const WCHAR *ptr = (const WCHAR *)pString;
char *pmbbuf = (char*) malloc(len + 1);
if (pmbbuf != NULL) {
wcstombs(pmbbuf, (LPCWSTR) ptr, len);
string str = string(pmbbuf);
}

Using sscanf to extract an int from a string in C++

My function must process strings that look like say hello y(5) or data |x(3)|, and I need to be able to extract the integer shown and store it into a separate int variable called address. However, some strings passing through will not have any integers, and for these the address must default to 0. When a string contains an integer, it will always be in between parentheses. I've attempted to use sscanf, but, being very new to sscanf, I'm encountering problems.. For some reason, the address always reads as 0. Here's my code:
void process(string info)
{
int address = 0; // set to 0 in case info contains no digits
sscanf(info.c_str(), "%d", address);
.
.
.
// remainder of code makes other function calls using the address, etc
}
Any ideas as to why the sscanf fails to find the integer in between parentheses? Thanks!
why the sscanf fails to find the integer in between parentheses
The "%d" in sscanf(info.c_str(), "%d", address) will cause sscanf() to stop scanning once a non-numeric sequence detected. Text like "(5)" will simply stop scanning at the "(".
Instead code need to to skip over non-numeric text.
Pseudo-code
in a loop
search for any of "-+0123456789"
if not found return 0
convert from that point using sscanf() or strtol()
if that succeeds, return number
else advance to next character
Sample code
int address;
const char *p = info.c_str();
for (;;) {
p += strcspn(p, "0123456789+-");
if (*p == 0) return 0;
if (sscanf(p, "%d", &address) == 1) {
return address;
}
p++;
}
Notes:
The strcspn function computes the length of the maximum initial segment of the string pointed to by s1 which consists entirely of characters not from the string pointed to by s2. C11 7.24.5.3 2
If code wants to rely on " it will always be in between parentheses." and input like "abc()def(123)" does not occur which has preceding non-numeric data between ().:
const char *p = info.c_str();
int address;
if (sscanf(p, "%*[^(](%d", &address)==1) {
return address;
}
return 0;
or simply
int address = 0;
sscanf(info.c_str(), "%*[^(](%d", &address);
return address;
You could use something as simple as this where strchr finds the first occurrence of "(" then use atoi to return the integer which will stop at the first non-digit.
char s1[] = "hello y(5)";
char s2[] = "data [x(3)]";
char s3[] = "hello";
int a1 = 0;
int a2 = 0;
int a3 = 0;
char* tok = strchr( s1, '(');
if (tok != NULL)
a1 = atoi(tok+1);
tok = strchr( s2, '(');
if (tok != NULL)
a2 = atoi(tok+1);
tok = strchr(s3,'(');
if (tok != NULL)
a3 = atoi(tok+1);
printf( "a1=%d, a2=%d, a3=%d", a1,a2,a3);
return 0;
When a string contains an integer, it will always be in between
parentheses
To strictly conform with this requirement you can try:
void process(string info)
{
int address;
char c = '5'; //any value other than ) should work
sscanf(info.c_str(), "%*[^(](%d%c", &address, &c);
if(c != ')') address = 0;
.
.
.
}
link to a solution
int address;
sscanf(info.c_str(), "%*[^0-9]%d", &address);
printf("%d", address);
this should extract the integer between the parenthesis

Understanding code to reverse string

I am struggling to understand the code below which is used to reverse a null-terminated string. I have written comments explaining the lines I am struggling to understand.
void reverse(char *str)
{
char *end = str;
char tmp;
if (str) // I don't understand what is happening within this if loop and how this is carried out for `str` which is not Boolean
{
while (*end) // I dont know what this means either
{
++end;
}
--end;
while (str < end)
{
tmp = *str
*str++ = *end //I am confused as to why this is not just *str = *end
*end-- = tmp; //Similarly, why is this not *end = tmp
}
}
}
if (str) means
Check if str a pointer to char is not NULL. Same as: if (str != NULL)
while (*end) check that the char pointed to by end is not the null-terminating character. Same as: while (*end != '\0')
*str++ = *end Assign the char pointed to by end to str and then advance str pointer by 1 char. *end-- advances end backwards by 1 char.
while (str < end) Compare the addresses as numbers (and not the values the pointers point to). This only makes sense if both pointers refer to different positions in the same memory block e.g. a c string in this case or any array. If str points to the 1st element of the string and end to the 2nd, then str < end will be true. The actuals chars in the 1st and 2nd positions will are not taken into account
*end = str; means the value of end pointer contains characters of string str
if (str) means check if str pointer isn't null ,so it's always true when str point to char.
while (*end) means check if end points to char , when pointer is null the condition is terminated , so when pointer reach the end of string end, while condition break and end pointer value contains the last char of string end.
*str++ = *end this statement can be break down to 2 statements to understand it :
first *str=*end; replace char value pointed by str with char pointed by end.
second *str++; move pointer to next character in string str after replacing.
*end-- = tmp; this statement can be break down to 2 statements to understand it :
first *end = tmp; replace char value pointed by end with tmp char.
second *end--; move pointer to previous char in string end after replacing.
I hope the idea is clear for you.
know that *end = str;
end = is the pointer here
They're checking the string if is not null if it is null ,if is should take the value of the char and assign to it
in your case the string is temp
i want you understand what char temp is doing and *end as pointer treat *end as a string meaning *end should not be null ,temp is character
while (*end)
++end;
it is telling that while end is not null, meaning the results should be a string ( e.g. a name like john)
--end it is telling you that the null should be clear
then it should go to another while
while (str < end) because the string is null
take char temp take to be a string
*str++ = *end then allow characters to make it a string or a name
or increement the character to make it a string
end-- = tmp // they are assign the string to that null string to have a vlue

c++ char array null character while loop

I have a function that keeps on incrementing the char, so it will display the next char in the ascci code, but my problem is it never breaks the loop
char * myFunction (char* &text)
{
char *temp = (char *)malloc(strlen(text));
char *tmp = temp;
while(*tmp != '\0')
{
*tmp = *text++; //im incrementing the text
tmp +=1;
}
return temp;
}
char *text = "hello";
cout<<myFunction(text)<<endl;
while(tmp != '\0')
to be
while(*tmp != '\0')
tmp is the address of the start of the string which will never be '\0'
there are lots of problems in your code, I summarized them in comments below:
// Making your argument char*& allows you to modify text variable from
// calling function, I dont think this was your intention. If you just
// want to pass string to this function change its type to `const char*`.
// I dont think this return value you really want here, now you have char, but I
// suppose you want to return string, so it should be `char*` or `const
// char*`
char myFunction (char* &text)
{
// sizeof(text) will return 4bytes, which is size of pointer,
// you want strlen(text)+1 here to get length of string + 1
// char for zero (end of string)
char *temp = (char *)malloc(sizeof(text));
char *tmp = temp;
// You should dereference *tmp, but tmp is uninitialized here,
// I think you want to use *text here.
while(tmp != '\0')
{
*tmp = *text++; //im incrementing the text
// You are incrementing value pointed by tmp,
// if you want to increment tmp to next string
// element use tmp++;
*tmp +=1;
}
// Here assign zero to last element of text
// temp is char* and your return value is char, this is wrong,
// you should change return value of myFunction to char*. Also
// remember to call free() on returned string once its no
// longer needed - otherwise you will introduce memory leaks
return temp;
}
// This should be `const char *text = "hello";` In c++ string
// literals are of type `const char*`
char *text = "hello";
cout<<myFunction(text)<<endl;

C++ strtok function

char ParseCmd(char *buf,int len)
{
char *p;
p = strtok(buf," ");
return *p;
}
Why does this function only return first symbol in a whole buffer? If I set buffer to a "fsa rew qwe" it returns only "f" instead of the expected "fsa".
"mˣ*" - that is now im getting. why ?
char dum = *InstList->Lines->GetText();
LoadLibrary("SyntaxP.dll");
char *dum1 = ParseCmd(&dum,32);
InstList->Lines->Add(dum1);
Because your return type is char which represents a character and you dereference the pointer returned by strtok().
Because you are returning a char value, which means only the first character of the string pointed by pointer p.You should return a char * from your function.
Your function should have the prototype:
char* ParseCmd(char *buf,int len);
^^^^^
Online Demo:
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
char* ParseCmd(char *buf,int len)
{
char *p;
p = strtok(buf," ");
char *ptr = (char *)malloc(strlen(p)+1);
strncpy(ptr,p,strlen(p));
return ptr;
}
int main()
{
char array[]="fsa rew qwe";
char* ret = ParseCmd(array,11);
printf("[%s]",ret);
/*If You Forget this,You cause a Memory Leak*/
free(ret);
return 0;
}
Output:
[fsa]
Disclaimer: I have not really used any C++ in the code because since You are using strtok and char * instead of string I believe the Q is more C than C++.
Like any C-style string, p is actually a character array. If you dereference it, you get a character. Have your ParseCmd return p instead of return *p.