c++ char array null character while loop - c++

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;

Related

*char conversion to/from bool in call to strstr

I have code that is supposed to remove all characters in one C-string from another.
The problem arises when I try to use the function strstr: both an array and a char* get converted to bool. Obviously it doesn't work because strstr needs to receive 2 char* arguments.
#include <iostream>
#include <ctype.h>
#include <string.h>
#include <malloc.h>
using namespace std;
char* temp_char(char* orig,char* del)
{ char *str_temp, *temp, *p, *c;
char symbol[2];
int i=0;
int len = strlen(orig);
temp=(char *)calloc(len,1);
str_temp = (char *)calloc(len,1);
strcpy(str_temp,orig);
for(i=0;i<strlen(del);i++){
symbol[0]=del[i];
symbol[1]=0;
temp[0]=0;
while( p=strstr(str_temp,del)!=NULL){
strncat(temp,str_temp,p-str_temp);
p++;
str_temp=p;
}
strcat(temp,str_temp);
strcpy(str_temp,temp);
}
cout<<temp;
return temp;
}
int main () {
char a[]="stuccsess",b[]="test";
temp_char(a,b);}
Any help would be appreciated.
You have two errors in one line of your code. The first is not addressing the issue that the != operator has higher priority than =. Thus, in the following line:
while( p=strstr(str_temp,del)!=NULL) {
the comparison is actually:
while( p = ( strstr(str_temp,del)!=NULL ) ){
So, you are attempting to assign the result of the != test, which will be a bool value, to a char* variable (p).
You can fix this, easily, by putting the assignment expression in parentheses.
However, although that will fix the compiler error, it will not address the second error. Just a few lines above that while statement, you assign one of the characters of the del string to the first of the symbol string (and, properly, add a nul terminator to that) … but you never then actually use that symbol string. Instead, you pass the entire del string as the second argument in the call to strstr. You should be passing your created symbol as that second argument.
So, changing that while line to the following will make the code work:
while ((p = strstr(str_temp, symbol)) != nullptr) { // Use nullptr in C++
But that leaves other errors in your function. How will you ever be able to free the memory allocated in the str_temp = (char*)calloc(len, 1); call? Once you have subsequently modified that str_temp pointer (in the str_temp = p; line), you no longer have the original pointer value, which must be used when calling free(). So, you need to save that value, just after you have made the allocation. (The temp memory pointer is returned, so that can be freed in the main function.)
There are other issues in your code that could be improved, like using new[] and delete[] in C++, rather than the old, C-language calloc, and that your index and length variables should really be of size_t type, rather than int. Here's a version with the corrections and suggestions discussed applied:
#include <iostream>
#include <cstring>
using std::cout;
char* temp_char(char* orig, char* del)
{
size_t len = strlen(orig);
char* temp = new char[len + 1];
char* str_temp = new char[len + 1];
char* save_temp = temp; // Save it so we can call delete...
strcpy(str_temp, orig);
for (size_t i = 0; i < strlen(del); i++) {
char symbol[2];
symbol[0] = del[i];
symbol[1] = 0;
temp[0] = 0;
char* p;
while ((p = strstr(str_temp, symbol)) != nullptr) {
strncat(temp, str_temp, static_cast<size_t>(p - str_temp));
p++;
str_temp = p;
}
strcat(temp, str_temp);
strcpy(str_temp, temp);
}
cout << temp;
delete[] save_temp; // ... don't forget to free this.
return temp;
}
int main()
{
char a[] = "stuccsess", b[] = "test";
char* answer = temp_char(a, b);
delete[] answer; // We should free the memory allocated!
return 0;
}
But your approach is far more complicated than it need be. You can simply loop through the original string and check each character to see if it is in the 'delete' string (using the strchr function, for example); if it is not (i.e. that strchr returns nullptr), then append the character to the accumulated temp and increase the running length:
char* temp_char(char* orig, char* del)
{
size_t len = strlen(orig);
char* temp = new char[len + 1];
int newlen = 0;
for (char* cp = orig; *cp != '\0'; ++cp) {
if (strchr(del, *cp) == nullptr) temp[newlen++] = *cp;
}
temp[newlen] = '\0'; // Add null terminator
std::cout << temp;
return temp;
}

Copying a C-style string into memory allocated on free store?

I'm doing an exercise in which I have to copy a c-style string into memory allocated on free store. I am required to do it without using subscripting and relying solely on pointer arithmetic. I wrote the following function-
char* str_dup(const char* s)
{
// count no. of elements
int i = 0;
const char* q = s;
while (*q) { ++i; ++q; }
//create an array +1 for terminating 0
char* scpy = new char[i + 1];
//copy elements to new array
while (*s)
{
*scpy = *s;
++s;
++scpy;
}
*scpy = 0;
return scpy;
}
The function is returning random characters. But if I change it into this-
char* str_dup(const char* s)
{
// count no. of elements
int i = 0;
const char* q = s;
while (*q) { ++i; ++q; }
//create an array +1 for terminating 0
char* scpyx = new char[i + 1];
char* scpy = scpyx;
//copy elements to new array
while (*s)
{
*scpy = *s;
++s;
++scpy;
}
*scpy = 0;
return scpyx;
}
it works. Can someone explain me why first code is not working and second is working?
The first code is not working since you return the final value of scpy, which at that point points at the terminating NUL character, and not the start of the string.
One solution is to do as you did, and save a copy of the original pointer to have something to return.
You should really use strlen() and memcpy(), they make this easier but perhaps they're off-limits to you.

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

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.

How to copy a string into a char array with strcpy

I my trying to copy a value into a char.
my char array is
char sms_phone_number[15];
By the way, could tell me if I should write (what the benefic/difference?)
char * sms_phone_number[15]
Below displays a string: "+417611142356"
splitedString[1]
And I want to give that value to sms_from_number
// strcpy(sms_from_number,splitedString[1]); // OP's statement
strcpy(sms_phone_number,splitedString[1]); // edit
I've got an error, I think because splitedString[1] is a String, isn't?
sim908_cooking:835: error: invalid conversion from 'char' to 'char*'
So how can I copy it correctely.
I also tried with sprintf without success.
many thank for your help.
Cheers
I declare spliedString like this
// SlitString
#define NBVALS 9
char *splitedString[NBVALS];
I have that function
splitString("toto,+345,titi",slitedString)
void splitString(char *ligne, char **splitedString)
{
char *p = ligne;
int i = 0;
splitedString[i++] = p;
while (*p) {
if (*p==',') {
*p++ = '\0';
if (i<NBVALS){
splitedString[i++] = p;
}
}
else
{
p++;
}
}
while(i<NBVALS){
splitedString[i++] = p;
}
}
If I do a for with splitedString display, it display this
for(int i=0;i<4;i++){
Serialprint(i);Serial.print(":");Serial.println(splitedString[i]);
}
//0:toto
//1:+4176112233
//2:14/09/19
I also declared and want to copy..
char sms_who[15];
char sms_phone_number[15];
char sms_data[15];
//and I want to copy
strcpy(sms_who,splitedString[0]
strcpy(sms_phone_number,splitedString[1]
strcpy(sms_date,splitedString[2]
I know, I am very confused with char and pointer * :o(
The declaration:
char * SplittedString[15];
Declares an array of pointers to characters, a.k.a. C-style strings.
Given:
const char phone1[] = "(555) 853-1212";
const char phone2[] = "(818) 161-0000";
const char phone3[] = "+01242648883";
You can assign them to your SplittedString array:
SplittedString[0] = phone1;
SplittedString[1] = phone2;
SplittedString[2] = phone3;
To help you a little more, the above assignments should be:
SplittedString[0] = &phone1[0];
SplittedString[1] = &phone2[0];
SplittedString[2] = &phone3[0];
By definition, the SplittedStrings array contains pointers to single characters, so the last set of assignments is the correct version.
If you are allowed, prefer std::string to char *, and std::vector to arrays.
What you need is a vector of strings:
std::vector<std::string> SplittedStrings(15);
Edit 1:
REMINDER: Allocate space for your spliedString.
Your spliedString should either be a pre-allocated array:
char spliedString[256];
or a dynamically allocated string:
char *spliedString = new char [256];
Strings and Chars can be confusing for noobs, especially if you've used other languages that can be more flexible.
char msg[40]; // creates an array 40 long that can contains characters
msg = 'a'; // this gives an error as 'a' is not 40 characters long
(void) strcpy(msg, "a"); // but is fine : "a"
(void) strcat(msg, "b"); // and this : "ab"
(void) sprintf(msg,"%s%c",msg, 'c'); // and this : "abc"
HTH

Replace specific character in a string in C++

I have a code like following -
Value = "Current &HT"; //this is value
void StringSet(const char * Value)
{
const char *Chk = NULL;
Chk = strpbrk(Value,"&");
if(Chk != NULL)
{
strncpy(const_cast<char *> (Chk),"&amp",4)
}
}
In above code I would like to replace "&" from Value with "&amp.It works fine if I have "&" single character but in current case strpbrk() return "&HT"and in below strncpy whole "&HT"is replaced.
Now I would like to know methods by which I can only replace a single character from a string.
You cannot replace one character in a C style string with several because you cannot know in a C style string how much room you have available to add new characters. You can only do this by allocating a new string and copying the old string to the new. Something like this
char* StringSet(const char* value)
{
// calculate how many bytes we need
size_t bytes = strlen(value) + 1;
for (const char* p = value; *p; ++p)
if (*p == '&')
bytes += 3;
// allocate the new string
char* new_value = new char[bytes];
// copy the old to the new and replace any & with &amp
char* q = new_value;
for (const char* p = value; *p; ++p)
{
*q = *p;
++q;
if (*p == '&')
{
memcpy(q, "amp", 3);
q += 3;
}
}
*q = '\0';
return new_value;
}
But this is terrible code. You really should use std::string.
I think you need some temp array to hold string past & and then replace & in original string and append temp array to original. Here is the above code modified, I believe you can use strstr instead of strchr it accepts char* as second argument.
void StringSet(char * Value)
{
char *Chk = NULL,*ptr = NULL;
Chk = strchr(Value,'&');
if(Chk != NULL)
{
ptr = Chk + 1;
char* p = (char*)malloc(sizeof(char) * strlen(ptr));
strcpy(p,ptr);
Value[Chk-Value] = '\0';
strcat(Value,"&amp");
strcat(Value,p);
free(p);
}
}
Thanks
Niraj Rathi
You should not modify a constant string, and certainly can't modify a string literal. Although it is much much better to use a std::string instead of dealing with resource management yourself, one way is to allocate a new c-style string and return a pointer to it:
char *StringSet(const char *Value) {
char buffer[256];
for (char *p = (char*)Value, *t = buffer; p[0] != 0; p++, t++) {
t[0] = p[0];
if (p[0] == '&') {
t[1] = 'a'; t[2] = 'm'; t[3] = 'p';
t += 3;
}
t[1] = 0;
}
char *t = new char[strlen(buffer)+1];
strcpy(t, buffer);
return t;
}
string str="Current &HT";
str.replace(str.find('&'),1,"&amp");