I am very new new to cpp and trying to replace second occurrence of '*' with '!' char in a given string using following method.
#include <iostream>
#include <string.h>
using namespace std;
void replaceChar(char **inp){
char *tmp = *inp;
const char *c = "*";
char *cmark = strstr(tmp,c);
cout<< *cmark;
if(cmark != NULL && strlen(cmark) > 1){
cmark++;
if(strstr(cmark,c)){
int len = strlen(cmark);
cout<<"len"<<len;
for(int i=0;i<len;i++){
if(cmark[i] == '*'){
cout<<"i.."<<i;
cmark[i] = '!';//error point
}
}
}
}
}
int main() {
char * val = "this is string*replace next * with ! and print";
replaceChar(&val);
cout<<"val is "<< val;
return 0;
}
I am getting run time error on error point line.If I comment out this line I am getting correct index of '*' to be replaced.
Is it possible to replace '*' with '!' using cmark[i] = '!'?
Check this difference between char s[] and char *s in C
#include <iostream>
#include <string.h>
using namespace std;
void replaceChar(char *inp){
char *tmp = inp;
const char *c = "*";
char *cmark = strstr(tmp,c);
cout<< *cmark;
if(cmark != NULL && strlen(cmark) > 1){
cmark++;
if(strstr(cmark,c)){
int len = strlen(cmark);
cout<<"len"<<len;
for(int i=0;i<len;i++){
if(cmark[i] == '*'){
cout<<"i.."<<i;
cmark[i] = '!';
}
}
}
}
}
int main() {
char val[] = "this is string*replace next * with ! and print";
replaceChar(val);
cout<<"val is "<< val;
return 0;
}
There is no need to pass pointer to pointer in method.
Instead you can just pass original pointer to string.
You can do it in much simpler way.
void replaceChar(char *inp){
int i;
int second = 0;
/* Strings in C\C++ is null-terminated so we use it to determine
end of string */
for (i = 0; inp[i] != '\0'; ++i) {
if (inp[i] == '*') {
/* Use flag to determine second occurrence of * */
if (!second) {
second = 1;
} else {
inp[i] = '!';
break;
}
}
}
}
Related
for part of a school lab I need to read in unique words and their corresponding count with a struct. I am new to structs so please bear with me. I am getting an access violation when I try to write the adress of the current word to the character pointer inside of the current instance of my struct. I have read that this is due to dereferencing a nullptr. I have tried to understand this, but I just don't get it. I have resized arrays just like this on regular char** arrays for accepting new words. I am at a loss, any help would be greatly appreciated. The input file used here is just random words separated by non letter characters but not - or , Here is my code:
#define _CRT_SECURE_NO_WARNINGS
#define _CRTDBG_MAP_ALLOC
#include <iostream>
#include <iomanip>
#include <fstream>
#include <limits>
using std::cin;
using std::cout;
using std::endl;
using std::setw;
using std::right;
using std::left;
using std::ifstream;
using std::ofstream;
const int BUFFER = 100; //I figure this buffer is big enough for any given word
struct Word_Count_STRUCT
{
char* WORD = nullptr;
int COUNT = 0;
};
int main()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
//Input for phrase
ifstream iphrase;
//Output to CSV (word count)
ofstream o_count;
//Word Exceptions
ifstream xinWord;
char wordbuffer[BUFFER] = { '\0' };
char ch = 0;
Word_Count_STRUCT** uniquewords = nullptr;
Word_Count_STRUCT** temp = nullptr;
int k = 0;
int wordcount = 0;
char* cword = nullptr; //Current Word
bool NextWord_flag = false;
bool interwordpunct = false;
bool NewWord_flag = true;
iphrase.open("C:\\Users\\me\\Desktop\\henroE.txt");
if (iphrase.is_open())
{
while (!iphrase.eof())
{
iphrase.get(ch);
if (isalpha(ch) || ch == '\'' || ch == '-')
{
wordbuffer[k] = ch;
++k;
NextWord_flag = true;
if (ch == '\'' || ch == '-')
interwordpunct = true;
}
if ( (NextWord_flag == true) && (!isalpha(ch)) && (interwordpunct == false) )
{
k = 0;
cword = new char[strlen(wordbuffer) + 1];
strcpy(cword, wordbuffer);
memset(wordbuffer, '\0', sizeof(wordbuffer));
for (int i = 0; (i < wordcount) && (NewWord_flag == true); ++i)
{
int cmp = _stricmp(uniquewords[i]->WORD, cword);
if (cmp == 0)
{
NewWord_flag = false;
uniquewords[i]->COUNT++;
delete[] cword;
}
}
if (NewWord_flag == true)
{
temp = new Word_Count_STRUCT * [wordcount + 1]();
for (int i = 0; i < wordcount; ++i)
{
temp[i] = uniquewords[i];
}
delete[] uniquewords;
temp[wordcount]->WORD = cword;
temp[wordcount]->COUNT++;
uniquewords = temp;
++wordcount;
NextWord_flag = false;
}
interwordpunct = false;
NewWord_flag = true;
}
}
}
I get an error on this line:
temp[wordcount]->WORD = cword;
I also get an error on the int value COUNT as well if I comment the line above it out. So I am guessing it is something with how I initialized the struct.
Worth noting that if I do not initialize this call:
temp = new Word_Count_STRUCT * [wordcount + 1]();
and instead just leave it as
temp = new Word_Count_STRUCT * [wordcount + 1];
I get another access violation but for reading instead of writing at 0xFFFFF...
At a loss, thank you for any help :)
You've got a number of things wrong. First, using fixed-length character buffers instead of C++ strings is about 20 years out of date and WILL cause buffer overflow errors unless you are exceedingly careful.
But this is an issue:
temp = new Word_Count_STRUCT * [wordcount + 1]();
for (int i = 0; i < wordcount; ++i)
{
temp[i] = uniquewords[i];
}
delete[] uniquewords;
But where did you allocate uniquewords? You declared it.
You also allocate cword outside a loop but the delete it inside a loop -- which seems really fishy, too.
But note that all you've allocated are pointers. I don't see you actually allocating the structure you're trying to put data in.
I have a character array like below:
char array[] = "AAAA... A1... 3. B1.";
How can I split this array by the string "..." in Arduino? I have tried:
ptr = strtok(array, "...");
and the output is the following:
AAAA,
A1,
3,
B1
But I actually want output to be
AAAA,
A1,
3.B1.
How to get this output?
edit:
My full code is this:
char array[] = "AAAA... A1... 3. B1.";
char *strings[10];
char *ptr = NULL;`enter code here`
void setup()
{
Serial.begin(9600);
byte index = 0;
ptr = strtok(array, "..."); // takes a list of delimiters
while(ptr != NULL)
{
strings[index] = ptr;
index++;
ptr = strtok(NULL, "..."); // takes a list of delimiters
}
for(int n = 0; n < index; n++)
{
Serial.println(strings[n]);
}
}
The main problem is that strtok does not find a string inside another string. strtok looks for a character in a string. When you give multiple characters to strtok it looks for any of these. Consequently, writing strtok(array, "..."); is exactly the same as writing strtok(array, ".");. That is why you get a split after "3."
There are multiple ways of doing what you want. Below I'll show you an example using strstr. Unlike strtokthe strstr function do find a substring inside a string - just what you are looking for. But.. strstr is not a tokenizer so some extra code is required to print the substrings.
Something like this should do:
int main()
{
char array[] = "AAAA... A1... 3. B1...";
char* ps = array;
char* pf = strstr(ps, "..."); // Find first substring
while(pf)
{
int len = pf - ps; // Number of chars to print
printf("%.*s\n", len, ps);
ps = pf + 3;
pf = strstr(ps, "..."); // Find next substring
}
return 0;
}
You can implement your own split as strtok except the role of the second argument :
#include <stdio.h>
#include <string.h>
char * split(char *str, const char * delim)
{
static char * s;
char * p, * r;
if (str != NULL)
s = str;
p = strstr(s, delim);
if (p == NULL) {
if (*s == 0)
return NULL;
r = s;
s += strlen(s);
return r;
}
r = s;
*p = 0;
s = p + strlen(delim);
return r;
}
int main()
{
char s[] = "AAAA... A1... 3. B1.";
char * p = s;
char * t;
while ((t = split(p, "...")) != NULL) {
printf("'%s'\n", t);
p = NULL;
}
return 0;
}
Compilation and execution:
/tmp % gcc -g -pedantic -Wextra s.c
/tmp % ./a.out
'AAAA'
' A1'
' 3. B1.'
/tmp %
I print between '' to show the return spaces, because I am not sure you want them, so delim is not only ... in that case
Because you tagged this as c++, here is a c++ 'version' of your code:
#include <iostream>
using std::cout;
using std::endl;
#include <vector>
using std::vector;
#include <string>
using std::string;
class T965_t
{
string array;
vector<string> strings;
public:
T965_t() : array("AAAA... A1... 3. B1.")
{
strings.reserve(10);
}
~T965_t() = default;
int operator()() { return setup(); } // functor entry
private: // methods
int setup()
{
cout << endl;
const string pat1 ("... ");
string s1 = array; // working copy
size_t indx = s1.find(pat1, 0); // find first ... pattern
// start search at ---------^
do
{
if (string::npos == indx) // pattern not found
{
strings.push_back (s1); // capture 'remainder' of s1
break; // not found, kick out
}
// else
// extract --------vvvvvvvvvvvvvvvvv
strings.push_back (s1.substr(0, indx)); // capture
// capture to vector
indx += pat1.size(); // i.e. 4
s1.erase(0, indx); // erase previous capture
indx = s1.find(pat1, 0); // find next
} while(true);
for(uint n = 0; n < strings.size(); n++)
cout << strings[n] << "\n";
cout << endl;
return 0;
}
}; // class T965_t
int main(int , char**) { return T965_t()(); } // call functor
With output:
AAAA
A1
3. B1.
Note: I leave changing "3. B1." to "3.B1.", and adding commas at end of each line (except the last) as an exercise for the OP if required.
I looked for a split function and I didn't find one that meets my requirement, so I made one and it works for me so far, of course in the future I will make some improvements, but it got me out of trouble.
But there is also the strtok function and better use that.
https://www.delftstack.com/es/howto/arduino/arduino-strtok/
I have the split function
Arduino code:
void split(String * vecSplit, int dimArray,String content,char separator){
if(content.length()==0)
return;
content = content + separator;
int countVec = 0;
int posSep = 0;
int posInit = 0;
while(countVec<dimArray){
posSep = content.indexOf(separator,posSep);
if(posSep<0){
return;
}
countVec++;
String splitStr = content.substring(posInit,posSep);
posSep = posSep+1;
posInit = posSep;
vecSplit[countVec] = splitStr;
countVec++;
}
}
Llamada a funcion:
smsContent = "APN:4g.entel;DOMAIN:domolin.com;DELAY_GPS:60";
String vecSplit[10];
split(vecSplit,10,smsContent,';');
for(int i = 0;i<10;i++){
Serial.println(vecSplit[i]);
}
String input:
APN:4gentel;DOMAIN:domolin.com;DELAY_GPS:60
Output:
APN:4g.entel
DOMAIN:domolin.com
DELAY_GPS:60
RESET:true
enter image description here
I am making a function called removeString(). It's purpose is to remove a string from a text
example: if the text is "the wrong son" and I want to remove "wrong" to be "the son", I use this function.
The prototype is:
void removeString(char source[], int start, int numofchrem);
and the program is like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void removeString(char source[], int start, int numofchrem)
{
int i, j, k;
char n[20];
j = start + numofchrem - 1;
for (i = 0; i < numofchrem; i++)
{
if (source[start] == '\0')
break;
source[j] = '\b';
j--;
}
printf("%s", source);
}
int main()
{
char text[] = "the wrong son";
void removeString(char source[], int start, int numofchrem);
removeString(text, 4, 6);
}
when I made the program I debugged first the characters inside the source it was like this
"the \b\b\b\b\b\bson"
When I print the text inside source using:
printf("%s",source);
The program showed only "son" not "the son". So if anyone could help me I would be so grateful.
You need to move "son" (and the '\0') back, over what you want to replace
void removeString(char source[], int start, int numofchrem)
{
char *d = source + start; // d points to "wrong..."
char *s = source + start + numofchrem; // s points to "son"
while (*s != '\0') {
*d = *s; // replace 'w' with 's', 'r' with 'o', ...
d++; // point to next: "rong...", "ong...", "ng..."
s++; // point to next: "on", "n"
}
*d = '\0'; // terminate string
}
It should convert a string like this: Example: HEloOO, should be converted into : heLOoo . For some reason it doesn't work,it just wont convert the letters from uppercase to lowercase and vice versa any help would be appreciated ?
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void rek(char array[], int d)
{
int counter=0;
if(d==0)
{
printf("%s \n",array);
printf("%d \n",counter);
}
else
{
if((array[d]>='A' && array[d]<='Z')&&(array[d-1]>='A' && array[d-1]<='Z'))
{
array[d]=array[d]+32;
array[d-1]=array[d-1]+32;
counter++;
rek(array,d-2);
}
if((array[d]>='a' && array[d]<='z')&&(array[d-1]>='a' && array[d-1]<='z'))
{
array[d]=array[d]-32;
array[d-1]=array[d-1]-32;
counter++;
rek(array,d-2);
}
}
}
int main()
{
char array[100];
int d;
gets(array);
d=strlen(array);
rek(array,d);
return 0;
}
Your function does not call itself when two adjacent characters have different cases. Also you can get different results when the string is processed from the start or from the end.
I would write the function the following way
#include <stdio.h>
#include <ctype.h>
char * rek(char *s)
{
if (s[0] && s[1])
{
size_t i = 1;
if (islower((unsigned char)s[0]) && islower((unsigned char)s[1]))
{
s[0] = toupper((unsigned char)s[0]);
s[1] = toupper((unsigned char)s[1]);
++i;
}
else if (isupper((unsigned char)s[0]) && isupper((unsigned char)s[1]))
{
s[0] = tolower((unsigned char)s[0]);
s[1] = tolower((unsigned char)s[1]);
++i;
}
rek(s + i);
}
return s;
}
int main( void )
{
char s[] = "HEloOO";
puts(rek(s));
return 0;
}
The program output is
heLOoo
The main problem is that you recur only if your have a pair of upper-case or lower-case letters. Otherwise, you drop off the end of your if, return to the calling program, and quit converting things.
The initial problem is that you've indexed your string with the length. A string with 6 characters has indices 0-5, but you've started with locations 5 and 6 -- the final 'O' and the null character.
The result is that you check 'O' and '\0'; the latter isn't alphabetic at all, so you drop through all of your logic without doing anything, return to the main program, and finish.
For future reference, Here's the debugging instrumentation I used. Also see the canonical SO debug help.
#include<stdio.h>
#include<string.h>
#include<ctype.h>
void rek(char array[], int d)
{
int counter=0;
printf("ENTER rek %s %d\n", array, d);
if(d==0)
{
printf("%s \n",array);
printf("%d \n",counter);
}
else
{
printf("TRACE 1: %d %c%c\n", d, array[d-1], array[d]);
if((array[d]>='A' && array[d]<='Z')&&(array[d-1]>='A' && array[d-1]<='Z'))
{
printf("TRACE 2: upper case");
array[d]=array[d]+32;
array[d-1]=array[d-1]+32;
counter++;
rek(array,d-2);
}
if((array[d]>='a' && array[d]<='z')&&(array[d-1]>='a' && array[d-1]<='z'))
{
printf("TRACE 3: lower case");
array[d]=array[d]-32;
array[d-1]=array[d-1]-32;
counter++;
rek(array,d-2);
}
}
}
int main()
{
char *array;
int d;
array = "HEloOO";
d=strlen(array);
rek(array,d);
printf("%s\n", array);
return 0;
}
I come up with this dirty solution:
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
string solve(const string& str)
{
if (str.empty()) {
return "";
}
if (str.front() >= 'a' && str.front() <= 'z') {
return (char)toupper(str.front()) + solve(str.substr(1));
}
if (str.front() >= 'A' && str.front() <= 'Z') {
return (char)tolower(str.front()) + solve(str.substr(1));
}
}
int main()
{
string str;
cin >> str;
cout << solve(str) << endl;
return 0;
}
This is my attempt at taking an input and then produce an output with the words in the reverse order. Note: I can only use pointers.
Input: What is your name?
Output: name? your is What
I have looked at the other solutions posted here and thought tried to implement them as much as possible but I keep running into problems. Currently it only displays the first letter of the line. I would appreciate any help to fix it!
#include <iostream>
using namespace std;
#include <cstring>
int main( )
{
char input[255] = {' '};
char *head, *tail;
char temp;
int i = 0;
cin >> input;
head = input;
tail = input;
while(*tail!='\0')
{
tail++;
}
while (tail <= head){
temp = *head;
*head=*tail;
*tail=temp;
*head++;
*tail--;
}
cout << input;
cout << endl;
return 0;
}
Try this. Without anything referring STL.
#include <iostream>
#include <cstring>
using namespace std;
int main(int argc, char **argv)
{
char input[255];
char *head; // head of a word.
char *tail; // tail of a word.
cin.getline(input, 255); // read a whole line.
tail = input + strlen(input) - 1; // if you can use <cstring>?
while (tail >= input) {
if (*tail == 0 || *tail == ' ') {
tail--; // move to the tail of a word.
} else {
tail[1] = 0;
head = tail;
while (head >= input) {
if (head == input || *(head - 1) == ' ') {
cout << head << " "; // output a word.
tail = head - 1; // seek the next word.
break;
}
head--; // move to the head of a word.
}
}
}
cout << endl;
return 0;
}
How about something like this pseudo-codeish:
read_input_into_string();
trim_leading_and_trailing_whitespace();
convert_multiple_whitespace_in_string_to_single_space();
for (char* current_string_ptr = find_end_of_string();
current_string_ptr > start_of_input;
current_string_ptr--)
{
if (*current_string_ptr == ' ')
{
// +1 because `current_string_ptr` is at the space,
// and we want to print the word without leading spaces
std::cout << (current_string_ptr + 1) << ' ';
// Terminate string at the space
*current_string_ptr = '\0';
}
}
It's not complete (i.e. won't print the first word in the input), but I leave that as an exercise for the reader. :)
Low-level:
void reverseStr(const char* str, char* szBuffer)
{
int j = strlen(str) - 1, i = j, k = 0;
if(j < 0)
return;
while(j >= 0){
if(j-1 < 0 || *(str+j-1) == ' '){
strncpy(szBuffer+k, str+j, i-j+1);
szBuffer[k+i-j+1] = ' ';
k += i-j+2;
i = j-2;
j -= 2;
}
else{
--j;
}
}
szBuffer[k-1] = '\0';
}
int main(int argc, char** argv)
{
const char* str = "this is a string?";
char szBuffer[256];
reverseStr(str, szBuffer);
std::cout << szBuffer;
}