Sorting char arrays by swapping pointers, C++ - c++

I am trying to sort an array of char pointers (char * _string) by swapping pointers.
I have this method, and what I want to do is use the values I get from _string and sort them by not manipulating _string, but the empty helper array (char * _output) which I also hand over to the method.
Can anyone help me and tell me what I am doing wrong?
void sortAsc(char* _string, char* _output)
{
int length = strlen(_string);
// output and string now point to the same area in the memory
_output = _string;
for( int i = 0; i < length; i++) {
for( int j = 0; j < length; j++) {
if( *(_output) > (_output[j] ) ) {
// save the pointer
char* tmp = _output;
// now output points to the smaller value
_output = _output+j;
// move up the pointer to the smaller value
_output + j;
// now the pointer of the smaller value points to the higher value
_output = tmp;
// move down to where we were + 1
_output - j + 1;
}
}
}
//_output[length]='\0';
//delete chars;
}
In my main-Method, I do something like this:
char * string = {"bcdae"};
char * output = new char[5];
sortAsc(string, output);
After that code, I want the output array to contain the sorted values.

Let's do the selection sort for a 10 size int array using pointer notation, you can simply change it to an array list.
*---*---*---*---*---* ........
a[] = | 1 | 2 | 4 | 0 | 3 | ........
*---*---*---*---*---* ........
^--------We start here looking for the smaller numbers and sort the array.
for( i = 0; i < 10; i++ ){
k = i;
bypass = *( a + i );
for( j = i + 1; j < 10; j++ ){
/* To get Increasing order. */
if( bypass > *( a + j ) ){
bypass = *( a + j );
k = j;
}
}
if ( k != i ){
*( a + k ) = *( a + i );
*( a + i ) = bypass;
}
}

This sorts the string into an already allocated buffer, and if the buffer isn't large enough tells you how big it has to be:
std::size_t sortAsc(char const* string, char* dest, std::size_t dest_length) {
std::size_t str_length = strlen(string);
char const* str_end = string + str_length;
if (dest_length < str_length+1)
return str_length+1;
std::copy( string, str_end, output );
output[str_length] = '\0';
std::sort( output, output+strlen(output) );
return str_length+1;
}
This does the poor "allocate a new string" pattern, using the above implementation:
char* allocate_and_sortAsc(char const* string) {
std::size_t str_length = strlen(string);
char* retval = new char[str_length+1];
std::size_t count = sortAsc( string, retval, str_length+1);
ASSERT( count <= str_length );
return retval;
}
And don't use variable names that start with an _, it is a bad practice because it wanders really near compiler reserved names. _Capital is reserved everywhere, and _lower in global scope, and foo__bar everywhere.

Related

Is there an alternative to the std::string substring?

Given a string s = "RADILAMIA" I want to take all the substrings of length 4 (or something else).
If len == 4 then the substrings are: "RADI","ADIL","DILA","ILAM","LAMI","AMIA". It seems easy to do that by using the std::string substr method:
vector<string> allSubstr(string s,int len) {
vector<string>ans;
for(int i=0;i<=s.size()-len;i++) {
ans.push_back(s.substr(i,len));
}
return ans;
}
substr's time complexity is unspecified, but generally linear against the length of the substring.
Can I do this without std::string substr. Any substring and the previous substring differ in only one letter. Is there any better way to reduce the time complexity?
string_view (C++17) has a constant time substr:
vector<string_view> allSubstr(const string_view& s, int len) {
vector<string_view> ans;
and.reserve(s.size() - len + 1);
for (int i = 0 ; i <= s.size() - len; ++i) {
ans.push_back(s.substr(i, len));
}
return ans;
}
Just make sure that s outlives the return value of the function.
There can be millions of different approaches. Here is my algorithm.
vector<string> allSubstr(string s,int len) {
vector<string>ans;
ans.reserve(s.size() - len );
for(size_t i=0;i<=s.size()-len;i++)
{
ans.emplace_back( s.begin() +i, s.begin() + i + len );
}
return ans;
}
It is tested. I mean it wouldn't matter what you are using but emplace_back above can make a difference since there won't be copy cost. Also you add reserve for more performance.
No matter what you do, you still need O(NL) time to write all your substrings into the vector.
The fastest thing would be probably:
vector<string> ans(s.size()-len);
for(int i=0;i<=s.size()-len;i++) {
ans[i] = s.substr(i, len);
}
Because push_back is slowish, and should generally be avoided if possible. It is overused.
PS: maybe this code would be even faster:
vector<string> ans(s.size()-len);
for(int i=0;i<=s.size()-len;i++) {
ans[i].append(s.begin()+i, s.begin()+i+len);
}
Probably you could use an array of chars instead. For example, you have got your word:
char s[] = "RADILAMIA";
To deal with all necessary substrings you can use such approach:
int substLength = 4;
int length = strlen(s);
char buffer[256];
for (int i = 0; i < length - substLength + 1; i++) {
strncpy(buffer, s + i, substLength);
buffer[substLength] = '\0';
cout << buffer << endl;
}
Using the char array you easily can access to the start of any substring by adding the necessary index to the beginning of the array.
It pays to revisit the docos
// string proto(len);
vector<string> result(s.size()-len, string(len, char(32))); // preallocates the buffers
const char *str=s.c_str();
const char* end=str+s.size()-len;
for(size_t i=0; str<end; str++, i++) {
result[i].assign(str, len); // likely to result in a simple copy in the preallocated buffer
}
The complexity is the same O(len*s.size()) - one can only hope for a smaller proportionality factor.
C is not always faster than C++ but #Fomalhaut was right to post the performant core solution in C. Here is my (C program) complete version, based on his algorithm. Without using strncpy, too.
Here it is on the godbolt.
#ifdef __STDC_ALLOC_LIB__
#define __STDC_WANT_LIB_EXT2__ 1
#else
#define _POSIX_C_SOURCE 200809L
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <malloc.h>
//////////////////////////////////////////////////////////////
// array of buffers == a_of_b
typedef struct a_of_b {
const unsigned size;
unsigned count ;
char ** data ;
} a_of_b ;
a_of_b a_of_b_make ( const unsigned size_ )
{
return (a_of_b){ .size = size_, .count = 0, .data = calloc(1, sizeof(char * [size_] ) ) } ;
}
a_of_b * a_of_b_append ( a_of_b * self, const unsigned len_, const char str_[len_] )
{
assert( self->data ) ;
assert( self->size > self->count ) ;
self->data[ self->count ] = strndup( str_, len_ ) ;
self->count += 1;
return self ;
}
a_of_b * a_of_b_print ( a_of_b * self , const char * fmt_ )
{
for (unsigned j = 0; j < self->count; ++j)
printf( fmt_ , self->data[j]);
return self ;
}
a_of_b * a_of_b_free ( a_of_b * self )
{
for (unsigned j = 0; j < self->count; ++j)
free( self->data[j]) ;
free( self->data) ;
self->count = 0 ;
return self ;
}
//////////////////////////////////////////////////////////////
a_of_b breakit ( const unsigned len_, const char input_[len_], const unsigned substLength )
{
assert( len_ > 2 ) ;
assert( substLength > 0 ) ;
assert( substLength < len_ ) ;
const unsigned count_of_buffers = len_ - substLength + 1;
a_of_b rez_ = a_of_b_make( count_of_buffers +1 ) ;
for (int i = 0; i < count_of_buffers ; i++) {
a_of_b_append( &rez_, substLength, input_ + i ) ;
}
return rez_ ;
}
//////////////////////////////////////////////////////////////
static void driver( const char * input_, const unsigned substLength )
{
printf("\n");
a_of_b substrings = breakit( strlen(input_), input_, substLength );
a_of_b_print( & substrings , "%s ");
a_of_b_free( & substrings);
}
//////////////////////////////////////////////////////////////
int main () {
driver( "RADILAMIA", 4) ;
driver( "RADILAMIA", 3) ;
driver( "RADILAMIA", 2) ;
driver( "RADILAMIA", 1) ;
return EXIT_SUCCESS;
}
And the program output is:
RADI ADIL DILA ILAM LAMI AMIA
RAD ADI DIL ILA LAM AMI MIA
RA AD DI IL LA AM MI IA
R A D I L A M I A
Enjoy.

Segmentation Fault in Vectors

So, I'm doing the famous "The Blocks Problem" from UVa Online Judge.
My approach is quite stupid, and that's because I wanted to play with vectors. So, I got vectors for pointers to each blocks in piles, and those vectors are stored in a vector called collection.
In order to find all the blocks, I have a vector called blockCollection, where pointers to all the blocks are stored inside.
The code has passed the samples provided. I will try to edit and provide comments later.
Full Source:
#include <iostream>
#include <vector>
struct Block
{
int id;
std::vector<Block*>* where;
};
int positionInVector(Block* b);
int main(int argc, const char * argv[])
{
std::vector<std::vector<Block*>*> collection;
std::vector<Block*> blockCollection;
std::string command = "", command2 = "";
int blockCount = 0, k = 0, A = 0, B = 0;
while ( std::cin >> blockCount )
{
std::vector<Block*>* vectors = new std::vector<Block*>[blockCount];
Block* blocks = new Block[blockCount];
for ( k = 0 ; k < blockCount ; ++ k)
{
blocks[k].id = k;
blocks[k].where = &vectors[k];
vectors[k].push_back(&blocks[k]);
blockCollection.push_back(&blocks[k]);
collection.push_back(&vectors[k]);
}
std::cin >> std::ws;
while ( std::cin >> command )
{
if ( command == "quit" ) break;
std::cin >> A >> command2 >> B;
Block* blockA = blockCollection[A];
Block* blockB = blockCollection[B];
std::vector<Block*>* vectorA = blockA -> where;
std::vector<Block*>* vectorB = blockB -> where;
//exception handle
if ( A > blockCount || B > blockCount ) continue;
if ( A == B ) continue;
if ( vectorA == vectorB ) continue;
if ( command == "move" )
{
//move anything on top of A to its original position
int positionOfBlockAInVectorA = positionInVector(blockA);
for ( int i = positionOfBlockAInVectorA + 1 ; i < vectorA -> size() ; ++ i )
{
Block* blockToBeMoved = *(vectorA -> begin() + i);
std::vector<Block*>* destinationVector = collection[blockToBeMoved -> id];
blockToBeMoved -> where = destinationVector;
destinationVector -> push_back(blockToBeMoved);
}
vectorA -> erase(vectorA -> begin() + positionOfBlockAInVectorA + 1, vectorA -> end());
}
if ( command2 == "onto" )
{
//move anything on top of B to its original position
int positionOfBlockBInVectorB = positionInVector(blockB);
for ( int i = positionOfBlockBInVectorB + 1 ; i < vectorB -> size() ; ++ i )
{
Block* blockToBeMoved = *(vectorB -> begin() + i);
std::vector<Block*>* destinationVector = collection[blockToBeMoved -> id];
blockToBeMoved -> where = destinationVector;
destinationVector -> push_back(blockToBeMoved);
}
if (positionOfBlockBInVectorB + 1 > vectorB -> size()) vectorA -> erase(vectorB -> begin() + positionOfBlockBInVectorB + 1, vectorB -> end());
}
if ( command == "move" )
{
//move block a to the pile containing block b
vectorA -> pop_back();
blockA -> where = vectorB;
vectorB -> push_back(blockA);
}
else
{
//move block a and those on top of it to the pile containing block b
std::vector<Block*> temperaryVector;
int positionOfBlockAInVectorA = positionInVector(blockA);
for ( int i = (int)vectorA -> size() - 1 ; i >= positionOfBlockAInVectorA ; -- i )
{
temperaryVector.push_back(vectorA -> at(i));
vectorA -> erase(vectorA -> begin() + i);
}
for ( int i = (int)temperaryVector.size() - 1 ; i >= 0 ; -- i )
{
temperaryVector[i] -> where = vectorB;
vectorB -> push_back(temperaryVector[i]);
}
}
}
for ( k = 0 ; k < blockCount ; ++ k )
{
std::vector<Block*>* vector = collection[k];
std::cout << k << ":";
if ( !vector -> empty() )
{
for ( int i = 0 ; i < vector -> size() ; ++ i )
{
std::cout << " " << vector -> at(i) -> id;
}
}
std::cout << std::endl;
}
delete [] blocks;
delete [] vectors;
}
return 0;
}
int positionInVector(Block* block)
{
std::vector<Block*> vector = *block -> where;
for ( int i = 0 ; i < vector.size() ; ++ i )
{
if ( vector[i] == block ) return i;
}
return -1;
}
Thanks!
For this to work:
A = (int)command[5] - 48;
B = (int)command[12] - 48;
we are need to ensure that string is 5/12 characters long, and that there is a digit in those positions. The code should add checks for the length of input and validity of the digits in those places.
Every time you add or delete a Block to your blockCollection, every pointer you hold to any Block in the collection may be invalidated.
I think that's all I need to say initially...

C++ generate next key

const int SIZE = 3;
const char val[SIZE] = {'3', 'z', '7'};
const string& next(){
static string ret = "0";
static unsigned i = 0;
static unsigned j = 0;
s[j] = val[i];
i++;
return ret;
//...
}
Everytime next is called, I want it to return the next string key, such as:
3
z
7
33
3z
37
z3
zz
z7
73
7z
77
333
33z
...
val[] could be any size with any values. My implementation is wrong and incomplete, and I can't wrap my head around it. Can anyone help?
const string& next(){
static int pos = 1;
static string s;
s.clear();
int n = pos++;
while (n){
s += val[(n-1) % SIZE];
// use s = val[(n-1] % SIZE] + s; for inverse order.
n = (n-1) / SIZE;
};
return s;
};
In terms of wrapping your head around it, you can think of it like you would incrementing a number. Increment the right-most value, but if that goes past the end then set it back to the first value and increment the next column, etc., then adding an extra value at the front if necessary.
#include <iostream>
#include <string>
const int n = 3;
const char val[n] = {'3', 'z', '7'};
const std::string& next()
{
static std::string ret;
if (ret.empty()) return ret = val[0];
for (int i = ret.length() - 1; i >= 0; --i)
if (ret[i] == val[n - 1])
{
// carry situation, reset this column & will increment next...
ret[i] = val[0];
}
else
{
// found existing column with room to increment...
ret[i] = strchr(val, ret[i])[1];
return ret;
}
return ret = val[0] + ret; // add an extra column at left...
}
int main()
{
for (int i = 0; i < 20; ++i)
std::cout << next() << ' ';
std::cout << '\n';
}
You want to format a number in base 3, with unusual symbols for your digits. You can use itoa to convert to base 3 and then modify the string by changing 0 to 3, 1 to z, and 2 to 7.

C++: how to access a multidimensional array with pointers?

Given: (In C++)
int main () {
int* ptr;
int ary [10][2];
ptr = ary;
return 0;
}
How would I access ary[0][1] with ptr?
You can't, because the type of ptr is wrong. The variable should be declared as int(*)[2] (pointer to an array of size 2 of integers). Then you could just use ptr[0][1].
#include <cstdio>
int main () {
int (* ptr) [2]; // <--
int ary [10][2];
ptr = ary;
ary[0][1] = 5;
printf("%d\n", ptr[0][1]);
return 0;
}
If you must use an int*, you need to introduce a reinterpret_cast. The array indices are laid out like:
0 1 2 3 2*n 2*n+1
[0][0] [0][1] [1][0] [1][1] ... [n][0] [n][1]
so you could use ptr[1] to get ary[0][1].
#include <cstdio>
int main () {
int* ptr;
int ary [10][2];
ptr = reinterpret_cast<int*>(ary); // <--
ary[0][1] = 5;
printf("%d\n", ptr[1]);
return 0;
}
typedef int tenints[10]; // tenints is an array of 10 ints
int main () {
tenints ary[2]; // array of 2 tenints, same as your int ary[10][2];
tenints* ptr = ary
// ptr[0] or *ptr is the first row
// ptr[1] or *(ptr+1)is the second row
int* ptr2 = ptr[0];
// ptr2[1] or *(ptr2+1) is ary[0][1]
// if you don't want do use as intermediate variable,
// just substitute "*ptr" for "ptr2" in "*(ptr2+1)"
int val = *((*ptr)+1);
return 0;
}
What you want only works when the data is on block which it might not be in all cases. In the context of image processing, you mostly do something like this:
int width = 1024;
int height = 768;
char* img = new char[width*height];
char** img2d = new char*[height];
for (int y = 0; y < height; ++y){
img2d[y] = img + y*width;
}
//set pixel at x=50, y=100
img2d[100][50] = 1;
//does the same
img2d[100*width+50] = 1;
delete[] img;
it is possible, just look at this example ( these are dynamic arrays, but works with static too ):
void bla ( void )
{
const int32_t sx = 50, sy = 30, sz = 50;
uint64_t *** n = NULL;
n = ( uint64_t*** )malloc( sizeof( uint64_t** ) * sx );
for ( int32_t x = 0; x < sx; x++ )
{
*( n + x ) = ( uint64_t** )malloc( sizeof( uint64_t* ) * sy );
for ( int32_t y = 0; y < sy; y++ )
*( *( n + x ) + y ) = ( uint64_t* )malloc( sizeof( uint64_t ) * sz );
}
for ( int32_t x = 0; x < sx; x++ )
for( int32_t y = 0; y < sy; y++ )
for( int32_t z = 0; z < sz; z++ )
*( *( *( n + x ) + y ) + z ) = 1024 * 1024;
}

C++ overloading * for polynomial multiplication

So I have been developing a polynomial class where a user inputs: 1x^0 + 2x^1 + 3x^2... and 1,2,3 (the coefficients) are stored in an int array
My overloaded + and - functions work, however, * doesnt work. No matter the input, it always shows -842150450
when is should be (5x^0 + x^1) * (-3x^0 + x^1) = -15x^0 + 2x^1 + 1x^2
or (x+5)(x-3) = x^2 +2x - 15
I'm using the overloaded * function like : Polynomial multiply = one * two;
Im guessing the problem is strtol(p, &endptr, 10) since it uses a long int, however, adding and subtracting works perfectly
My constructor
Polynomial::Polynomial(char *s)
{
char *string;
string = new char [strlen(s) + 1];
int length = strlen(string);
strcpy(string, s);
char *copy;
copy = new char [length];
strcpy(copy, string);
char *p = strtok(string, " +-");
counter = 0;
while (p)
{
p = strtok(NULL, " +-");
counter++;
}
coefficient = new int[counter];
p = strtok(copy, " +");
int a = 0;
while (p)
{
long int coeff;
char *endptr;
coeff = strtol(p, &endptr, 10); //stops at first non number
if (*p == 'x')
coeff = 1;
coefficient[a] = coeff;
p = strtok(NULL, " +");
a++;
}
}
and the overloaded * function
Polynomial Polynomial::operator * (const Polynomial &right)
{
Polynomial temp;
//make coefficient array
int count = (counter + right.counter) - 1;
temp.counter = count;
temp.coefficient = new int [count];
for (int i = 0; i < counter; i++)
{
for (int j = 0; j < right.counter; j++)
temp.coefficient[i+j] += coefficient[i] * right.coefficient[j];
}
return temp;
}
And heres my entire code: http://pastie.org/721143
You don't appear to initialise the temp.coefficient[i+j] to zero in your operator * ().
temp.coefficient = new int [count];
std::memset (temp.coefficient, 0, count * sizeof(int));
Convert -842150450 to hex to find back one of the magic values used in the CRT in the debug build. That helps finding the bug in your code:
temp.coefficient = new int [count];
// Must initialize the memory
for (int ix = 0; ix < count; ++ix) temp.coefficient[ix] = 0;
There are plenty other bugz btw, good luck fixing them.
Does
temp.coefficient = new int [count];
give you an array of zeroes?
Otherwise in your for loop you're adding stuff to garbage.
Replace
temp.coefficient = new int [count];
by
temp.coefficient = new int [count]();
in order to zero-initialize the array values.