Trying to concatenate array of c-strings with delimiter - c++

Here is my code
int main(int argc, char *argv[]) {
char const *strings[10] = {"dhh", "aci", "cdh"};
join_def(strings, 'l');
return EXIT_SUCCESS;
}
// part 1 read lines
void join_def(char const **strings, char delim) {
char *t = new char[100];
//int length = 0;
t[0] = '\0';
int x = sizeof(strings);
std::cout << delim << std::endl;
for (int i = 0; i < x; i++) {
int size = 0;
while(strings[i][size]!='\0'){
size++;
std::cout << strings[i][size] << std::endl;
}
}
}
I have spent hours now I just can't get to concatenate it
For this task, I cannot use cstring or anything other than iostream so please don't suggest.
The output needs to be a c-string = "dhhlacilcdh"

First, you cannot determine the number of elements in an array passed to a function, as that array will decay to a simple pointer. So, your sizeof(strings) expression will evaluate (at compile time) to the (fixed) size, in bytes, of a pointer. For the function to be 'aware' of how many elements there are in an array, it needs to be explicitly told (by way of an extra argument).
Second, you have your i' and size indexes the wrong way round in the std::cout << strings[i][size] << std::endl; line and, further, you increment size before printing the relevant character, whereas it should be incremented after you've printed it.
The code below also does the actual concatenation of the strings, and the modified join_def function now returns a pointer to that result (which must be freed when you're finished with it);
#include <iostream>
char* join_def(char const** strings, char delim, int x)
{
char* t = new char[100];
int length = 0;
t[0] = '\0';
//int x = sizeof(strings);
std::cout << delim << std::endl;
for (int i = 0; i < x; i++) {
int size = 0;
while (strings[i][size] != '\0') {
std::cout << strings[i][size] << std::endl;
t[length++] = strings[i][size]; // Append this character
size++;
}
t[length++] = delim; // Append delimiter
}
t[length] = '\0'; // Append nul-terminator
return t;
}
int main()
{
char const* strings[10] = { "dhh", "aci", "cdh" };
char* result = join_def(strings, 'l', 3);
std::cout << result << std::endl;
free(result);
return 0;
}
Note, also, that I have moved the join_def function code to before the main (which calls it). If you don't do this, then will at least have to provide a (forward) declaration of that function before main (just a char* join_def(char const** strings, char delim, int x); on its own will do).
Feel free to ask for further clarification and/or explanation.

I'm not exactly sure what you're trying to do, but maybe this helps?
#include <iostream>
// part 1 read lines
void join_def(char const **strings, char delim)
{
char *t = new char[100];
//int length = 0;
t[0] = '\0';
int x = 0;
for (int i = 0; strings[i] != nullptr; i++)
x += sizeof(strings[i]) - 1;
std::cout << delim << std::endl;
for (int i = 0; strings[i] != nullptr; i++)
{
int size = 0;
while (strings[i][size] != '\0')
{
size++;
std::cout << strings[i][size] << std::endl;
}
}
}
int main(int argc, char *argv[])
{
char const *strings[] = {"dhh", "aci", "cdh", nullptr};
join_def(strings, 'l');
return EXIT_SUCCESS;
}

this is what you are looking for?
look that I remove all the std::endl because it like '\n'
also i moved your size++ after the std::cout
#include <iostream>
// part 1 read lines
void join_def(char const **strings, char delim,int length) {
char *t = new char[100];
//int length = 0;
t[0] = '\0';
int x = length;
for (int i = 0; i < x; i++) {
int size = 0;
while(strings[i][size]!='\0'){
std::cout << strings[i][size]; //<--print befure increment size
size++;
}
std::cout << delim;
}
}
int main(int argc, char *argv[]) {
char const *strings[] = {"dhh", "aci", "cdh"};
join_def(strings,'|',3); //<- need to send the length of the char* array
return EXIT_SUCCESS;
}

Related

How to reverese a c-style string

I would like to reverse a c-style string and came up with the following code.
Play with the code
#include <iostream>
void reverse_c_str(char *c)
{
char *new_c = c;
for (; *new_c; ++new_c){} // find '\0'
--new_c; // new_c is now at the actual last char, which is 'g'
while (c < new_c) // swap chars
{
char tmp = *c;
*c = *new_c; // crash
*new_c = tmp;
--new_c;
++c;
}
}
int main()
{
char *c = "my string";
reverse_c_str(c);
std::cout << c << '\n';
}
Unfortunately, my code has an error, which I marked with // crash. Why does this line crash?
"my string" is a string literal, it is const.
It can be cast to a non-const char * for reasons of compatibility with C, but modifying a constant invokes undefined behavior. In some cases the OS will prevent it (as when it's stored in a read-only section), which is probably what you're observing.
Make a copy of the string in automatic storage, then you'll be able to modify it:
int main()
{
char c[] { "my string" };
reverse_c_str(c);
std::cout << c << '\n';
}
And of course there is a templated soultion:
#include <cstring>
template<std::size_t N>
void reverse_c_str(char (&str)[N]) {
std::size_t len = N-1;
for (std::size_t i = 0; i < len/2; ++i) {
str[i] ^= str[len-i-1];
str[len-i-1] ^= str[i];
str[i] ^= str[len-i-1];
}
}
int main() {
char c[] {"123"};
reverse_c_str(c);
char c2[] {""};
reverse_c_str(c2);
char c3[] {"4321"};
reverse_c_str(c3);
return 0;
}
Use std::swap and std::strlen. I made example for you here.
#include <iostream>
#include <cstring>
void reverse_c_str(char *c) {
int length = std::strlen(c);
for (int i = 0; i < length / 2; i++)
std::swap(c[i], c[length - i - 1]);
}
int main()
{
char c[] { "my string" };
reverse_c_str(c);
std::cout<<c << std::endl;
return 0;
}
Output:
gnirts ym
Another one version of function reverse_c_str
void reverse_c_str(char *c) {
if(*c) {
for(auto begin = c, end = c + std::strlen(c) - 1;
begin < end; ++begin, --end
) {
std::swap(*begin, *end);
}
}
}

Why it gives me an extra words?

Write and test your own function char * funct (char * str, int x) inverting (except for the character at position n) the string str and returning the modified str as the result. The use of the function funct could be:
This is main:
#include <iostream>
#include <cstring>
using namespace std;
char* funct(char *str, int x);
int main() {
char str1 [] = "Hello cpp";
cout << str1 << endl; // Hello cpp
cout << funct (str, 1) << endl; // pepC ollH // the character at position 1 ('e') stays in place
return 0;
}
This is my function:
char* funct(char *str, int x) {
int counter = 0;
do {
counter++;
str++;
} while (*str);
str--;
char *wskTmp = str;
for (int i = 0; i < counter ; i++) {
*wskTmp = *str;
str--;
wskTmp++;
}
*wskTmp = '\0';
wskTmp = wskTmp - counter;
for (int i = 0; i < counter - x -1; i++) {
wskTmp++;
}
char tmp;
for (int i = 0; i < counter-3; i++) {
tmp = *(wskTmp - 1);
*(wskTmp - 1) = *wskTmp;
*wskTmp = tmp;
wskTmp--;
}
return str;
}
Output:
Hello Cpp
Hello CppepC ollH
It should be:
Hello Cpp
pepC ollH
Why it gives me Hello Cp before "pepC ollH"?
Your code is very confusing and is a very roundabout way of accomplishing this task, so I restructured it a bit:
#include <cstring>
#include <iostream>
using namespace std;
char *funct(char *str, int x) {
// keep track of the original start
char *origStr = str;
// iterate through the string to find the end
do {
str++;
} while (*str);
// decrease the string so it's on the last byte, not the nullbyte
str--;
// create a start and end
char *start = origStr;
char *end = str;
if (start - origStr == x) {
start ++;
}
if (end - origStr == x) {
end--;
}
// if start >= end then we've finished
while (start < end) {
// swap values at start and end
char temp = *start;
*start = *end;
*end = temp;
// move the pointers closer to each other
start++;
end--;
// skip the index x
if (start - origStr == x) {
start++;
}
// skip the index x
if (end - origStr == x) {
end--;
}
}
// make sure to return the actual start
return origStr;
}
int main() {
char str1[] = "Hello cpp";
cout << str1 << endl; // Hello cpp
cout << funct(str1, 1) << endl; // pepC ollH // the character at position 1
// ('e') stays in place
return 0;
}

Remove substrings from a C-style string "in place" in C++ code

I had an interview task to remove substring from a current string without using string functions or additional memory...I tried just with strlen but didn't find the way to change it in place...
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
int main()
{
char * str = "this that there";
char * substr = "th";
removeSubstr(str,substr);
cout<<str; //should be now "is at ere"
return 0;
}
void removeSubstr(char * str, const char * substr){
}
Since you remove characters from the original string, the string is shrinking, so you do not need additional space. You just have to copy characters from a higher index (source) to a lower index (destination).
If the source index points to a position that starts with the searched substring, you must skip it.
The skip function simply compares the beginning of the source string against the substring, and returns the source (if it does not start with the substring) or the source plus the length of substring (if it starts with the substring).
Demo
#include <iostream>
char* skip_if( char* s, const char* ss )
{
char* p = s;
const char* pp = ss;
while( *p == *pp && *p )
p++, pp++;
return *pp ? s : p;
}
void remove( char* s, const char* ss )
{
char *ps = s; // source
char *pd = s; // destination
while( *ps )
{
ps = skip_if( ps, ss );
*pd++ = *ps++;
}
*pd = 0;
}
int main()
{
using namespace std;
char str[] = "this that there this that there";
const char* substr = "th";
remove( str, substr );
cout << str;
return 0;
}
The string functions exist for a reason. If you are not to use them, can you create them from scratch?
If so, here is my solution to the problem. Very educational to write custom string functions with the const requirements.
As mentioned in the comments, this won't work unless the string passed in can be modified, so I made it a non-constant string.
Let me know if this meets the interview challenge:
#include <iostream>
bool myStrnCmp(char *str1, const char *str2, int len) {
char *cptr1 = (char *) str1;
char *cptr2 = (char *) str2;
for (int i = 0; i < len; i++) {
if (*(cptr1 + i) != *(cptr2 + i))
return false;
}
return true;
}
int mystrlen(const char* str) {
int i = 0;
while(*(str + i) != '\0')
i++;
return i;
}
int findSubStr(char *str, const char *substr) {
int position = 0;
int len = mystrlen(substr);
while(*(str + position) != '\0') {
for (int i = 0; i < len; i++) {
if (myStrnCmp(str + position + i, substr, len))
return position + i;
}
++position;
}
return -1;
}
void myStrCpy(char *str, const char *substr) {
memmove(str, substr, mystrlen(substr) + 1);
}
void removeSubstr(char *str, const char *substr) {
int position = findSubStr(str, substr);
while(position >= 0) {
myStrCpy(str + position, str+position+mystrlen(substr));
position = findSubStr(str, substr);
}
}
int main() {
char str[]{"this that there"};
char* substr = "th";
removeSubstr(str,substr);
std::cout<<str; //should be now "is at ere"
return 0;
}

Reading input not knowing its size in c++

I have not found good answer for my question so i decided to ask my own question.
I need to read input from console with my own function in following format:
a RL
b RLRL
c RLLL
...
in general:
(character)(space)(character sequence or empty)(new line character)
I want to read it into char arrays one by one. I mean I want to read one line, do something with data, then read second one and so on...
Problem is that I do not know number of lines and I do not know how to stop it.
Checking if it is new line character (ASCII 10) does not work because it is in every single line.
There is my code:
#include <iostream>
#include <cstdio>
using namespace std;
int input_size;
char c;
bool finish;
inline int read(char* v, char* arr) {
int counter = 0;
c = getchar();
*v = c; //Pobranie wartości węzła
input_size++;
char* tmp = arr;
c = getchar();
c = getchar();
while (c != 32 && c != 10) {
input_size++;
*tmp++ = c;
c = getchar();
counter++;
}
if(c == 10)
finish = false;
return counter;
}
void show(char* t, int c) {
char* tmp = t;
for(int i = 0; i < c; i++) {
cout << *tmp;
tmp++;
}
delete[] tmp;
}
int main()
{
finish = true;
char* a = new char[1];
char* b = new char[64];
while(finish) {
int c = read(a, b);
cout << "char: " << *a << endl;
cout << "char sequence: ";
show(b,c);
cout << endl;
}
return 0;
}

Question on reversing a string

I get the following output: olleh�hello but can't figure out where I'm going wrong!
int main()
{
char hello[6] = "hello";
char temp[6];
unsigned int t = 0;
for(int i=strlen(hello)-1;i>=0;i--)
{
if(t<strlen(hello))
{
temp[t] = hello[i];
t++;
}
}
cout << temp;
return 0;
}
You need a null terminator at the end of the string:
int main()
{
char hello[6] = "hello";
char temp[6];
unsigned int t = 0;
for(int i=strlen(hello)-1;i>=0;i--)
{
if(t<strlen(hello))
{
temp[t] = hello[i];
t++;
}
}
temp[t] = '\0';
cout << temp;
return 0;
}
you tagged the question as [C++], so here's C++ way to reverse string:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::string hello = "hello";
std::reverse(hello.begin(), hello.end());
std::cout << hello << std::endl;
}
it's difficult to make any mistake here
You aren't terminating temp with a null (\0), so temp isn't a valid string and cout doesn't know quite what to do with it. Your problem will go away if you add:
temp[5] = 0;
after the for loop.