How to Return Two Arrays - c++

I have this function which purpouse is to "separate" numeric characters and letters in 2 arrays and then printing them.
char separa(char arr[MAX_CAR-1]){
char alpha[MAX_CAR];
char num[MAX_CAR];
int schiavo,schiavo2,schiavo3;
int j=0;
int k=0;
int f=0;
int lunghezza =strlen(arr);
for (int i =0;i<lunghezza;i++) {
schiavo = 0;
schiavo2 = -2;
schiavo3 = -2;
schiavo = isalpha(arr[i]);
schiavo2 = isspace(arr[i]);
schiavo3 = isdigit(arr[i]);
if (schiavo != 0 && schiavo2 == 0) {
alpha[j] = arr[i];
j++;
} else if (schiavo3 != 0 && schiavo2 == 0) {
num[k] = arr[i];
k++;
} else if (schiavo2 != 0) {
f++;
}
}
}
So the thing is that i am supposed to print those arrays in the main but i have no idea how to return them, i've tried reading forums about using pointers but i can't understand how it works for arrays
I even tried to return 1 array per time instead of 2 but even that didn't work

An approach you can use is to initialize the 2 arrays: alpha[MAX_CAR] and num[MAX_CAR] as a global variable outside of the function sepera. To use this approach, what you can do is have void separa(char arr[MAX_CAR-1], char alpha[MAX_CAR], char num[MAX_CAR]). This way, you can store these global variables as arguments to the function sepera, and it should work. An approach would work like this (I haven't tested this code):
Somewhere in main:
char alpha[MAX_CAR]
char num[MAX_CAR]
Then write your function looking something like this:
void separa(char arr[MAX_CAR-1],char alpha[MAX_CAR], char num[MAX_CAR]){
int schiavo,schiavo2,schiavo3;
int j=0;
int k=0;
int f=0;
int lunghezza =strlen(arr);
for (int i =0;i<lunghezza;i++) {
schiavo = 0;
schiavo2 = -2;
schiavo3 = -2;
schiavo = isalpha(arr[i]);
schiavo2 = isspace(arr[i]);
schiavo3 = isdigit(arr[i]);
if (schiavo != 0 && schiavo2 == 0) {
alpha[j] = arr[i];
j++;
} else if (schiavo3 != 0 && schiavo2 == 0) {
num[k] = arr[i];
k++;
} else if (schiavo2 != 0) {
f++;
}
}
}
Hope this helps.

Related

is there any faster way to do this exercise?

int function2 (const char * string1) returning the number of unique digits appearing in the string, e.g. function2 ("ab512af6kc1") -> 3.
int function2(const char* string1) {
int zero = 0, one = 0, two = 0, three = 0, four = 0, five = 0, six = 0,
seven = 0, eight = 0, nine = 0, counter = 0;
for (int i = 0; i < strlen(string1); i++) {
if (string1[i] == '0') {
zero++;
}
if (string1[i] == '1') {
one++;
}
if (string1[i] == '2') {
two++;
}
if (string1[i] == '3') {
three++;
}
if (string1[i] == '4') {
four++;
}
if (string1[i] == '5') {
five++;
}
if (string1[i] == '6') {
six++;
}
if (string1[i] == '7') {
seven++;
}
if (string1[i] == '8') {
eight++;
}
if (string1[i] == '9') {
nine++;
}
}
if (zero == 1) {
counter++;
}
if (one == 1) {
counter++;
}
if (two == 1) {
counter++;
}
if (three == 1) {
counter++;
}
if (four == 1) {
counter++;
}
if (five == 1) {
counter++;
}
if (six == 1) {
counter++;
}
if (seven == 1) {
counter++;
}
if (eight == 1) {
counter++;
}
if (nine == 1) {
counter++;
}
return counter;
}
It's every correct in this code, but it's long a bit. Could someone help me and write SHORTER code? It's the only way that I can measure up to this exercise.
You can use an array instead of 10 variables. Calculate the index in the array by converting the character to an integer.
int function2(const char *in) {
// Array to hold digits occurence counts.
unsigned digits[10]{};
// Iterate over the characters in input.
// Better (auto i : std::string_view(in)) in C++17.
for (auto i = in; *i; ++i) {
if (isdigit(*i)) {
// Increment the proper digit index.
digits[*i - '0']++;
}
}
int count = 0;
// Go through digit occurences.
for (auto i : digits) {
// If the digit occurred only once.
if (i == 1) {
// Increment the count.
count++;
}
}
return count;
}
To shorten your code, use an array instead of 10 individual variables:
int digits[10] = {0}; // instead of int zero = 0, one = 0, ...
To check whether a char is a representation of a digit, use isdigit:
if (isdigit(string1[i])) // instead of if (string1[i] == '0'), if (string1[i] == '1'), ...
The only non-trivial part is to convert a char to the corresponding int:
string1[i] - '0'
This code subtracts the character code of 0 (usually 48) from the character code of a digit (usually 49 for 1, 50 for 2, ..., 57 for 9). The result is an index to your array of counters.
So, to increase the proper array element, use the following code:
digit = string1[i] - '0';
digits[digit]++; // instead of zero++, one++, ...
After the code goes over the input string, count the number of digits which appeared once:
int counter = 0;
for (digit = 0; digit < 10; ++digit)
{
if (digits[digit] == 1)
++counter;
}
Use a hash table collection class to keep track of unique digits. In this case, unordered_set will do just fine. Don't even bother converting the char to integer. You're just looking for unique chars between '0' and '9'.
#include <string>
#include <unordered_set>
size_t getUniqueDigits(const std::string& string1)
{
std::unordered_set<char> table;
for (char c : string1)
{
if ((c >= '0') && (c <= '9'))
{
table.insert(c);
}
}
return table.size();
}
A more traditional "C" based solution that doesn't use any std:: collections or objects is to use an array to be that "set"
int getUniqueDigits(const char* string1)
{
int table[10] = {0};
int count = 0;
const size_t len = (string1 != nullptr) ? strlen(string1) : 0;
for(size_t i = 0; i < len; i++)
{
char c = string1[i];
if ((c >= '0') && (c <= '9'))
{
table[c - '0'] = 1;
}
}
for (char j = '0'; j <= '9'; j++)
{
count += table[j];
}
return count;
}
Just use an ordinary array as for example in this demonstrative program
#include <iostream>
size_t unique_digits( const char *s )
{
unsigned char digits[10] = { 0 };
for ( ; *s; ++s )
{
if ( '0' <= *s && *s <= '9' )
{
if ( digits[*s - '0'] != 2 ) ++digits[*s - '0'];
}
}
size_t count = 0;
for ( unsigned char c : digits ) count += c == 1;
return count;
}
int main()
{
std::cout << unique_digits( "ab512af6kc1" ) << '\n';
return 0;
}
The program output is
3
Or you can declare the array of the element type size_t. In this case the function will look the following way
#include <iostream>
size_t unique_digits( const char *s )
{
size_t digits[10] = { 0 };
for ( ; *s; ++s )
{
if ( '0' <= *s && *s <= '9' )
{
++digits[*s - '0'];
}
}
size_t count = 0;
for ( unsigned char c : digits ) count += c == 1;
return count;
}
int main()
{
std::cout << unique_digits( "ab512af6kc1" ) << '\n';
return 0;
}
I think you already have many good solutions.
Here is mine version anyway
int function2(const char* string1) {
int count[10] = {0};
int counter = 0;
int i;
for(i = 0; i < strlen(string1); i++)
int a = (++count[string1[i]-'0']);
if(a == 1)counter++;
if(a == 2)counter--;
return counter;
}
I haven't tried it. Hope there is no error
Edit:
I tried it. It seems to work fine now.

Huffman coding c++

So I am working on Huffman coding for a project. However, my code just doesn't work. When i ran it on visual studio, it didn't give me an error. What I was trying to do is to read a file and put all of them into a string. And get the frequency for each character in that string. But I think when the file got a little bit large, it seems like my code is running in a infinite loop. Can anyone explain anything to me? By the way, I had a sorted function that I used to sort a vector of node* by their frequency.
ifstream infile;
infile.open(filename);
string q;
string line;
while (getline(infile, line))
{
q += line;
}
char y;
int count = 0;
int check = 0;
for (int i = 0; i < q.size(); i++) //if the string gets big, it seems to become an infinite loop in here
{
y = q[i];
for (int x = i - 1; x > 0; x--) //make sure not counting the same char
{
if (y == q[x])
{
check++;
}
}
if (check == 0)
{
for (int i = 0; i < q.size(); i++)
{
if (q[i] == y)
{
count++;
}
}
node*x = new node;
x->char1 = y; //my node have char
x->freq = count; //my node has frequency
list1.push_back(x);
}
count = 0;
check = 0;
}
sort(list1.begin(), list1.end(), sorter); //sort them from small to big
while (list1.size() > 1)
{
node*left = list1[0];
node*right = list1[1];
list1.erase(list1.begin(), list1.begin() + 2);
double sum = left->freq + right->freq;
node* x = new node;
x->freq = sum;
x->left = left;
x->right = right;
list1.push_back(x);
sort(list1.begin(), list1.end(), sorter);
}
list1.clear();
return true;
The following is my sort function
static struct {
bool operator()(NodeInterface* a, NodeInterface* b) {
if (a->getFrequency() == b->getFrequency()) {//if the frequencies are even,
if (b->getCharacter() == '\0') return false;
if (a->getCharacter() != '\0') {
return (int)a->getCharacter() < (int)b->getCharacter();
}
return false;
}
return a->getFrequency() < b->getFrequency();
}
} sorter;
I see two major problems.
You have a for loop inside a for loop both initializing and using int i
Change the variable name of the inner loop.
for (int i = 0; i < q.size(); i++) //if the string gets big, it seems to become an infinite loop in here
.
.
if (check == 0)
{
for (int i = 0; i < q.size(); i++) //Change this to int j for example
{
.
.
And the Sorter struct. I would rewrite it as this.
static struct {
bool operator()(NodeInterface* a, NodeInterface* b) {
if (a->getFrequency() == b->getFrequency()) {//if the frequencies are even,
if (b->getCharacter() == '\0') return false;
if (a->getCharacter() == '\0') return true;
return (int)a->getCharacter() < (int)b->getCharacter();
}
return a->getFrequency() < b->getFrequency();
}
} sorter;
A few suggestions for your for loop:
for (int i = 0; i < q.size(); i++) //if the string gets big, it seems to become an infinite loop in here
{
y = q[i];
//You can avoid this entire loop by using a structure like map
for (int x = i - 1; x > 0; x--) //make sure not counting the same char
{
if (y == q[x])
{
check++;
//break; //if you use a loop, break it once you find the character.
}
}
if (check == 0)
{
for (int j = 0; j < q.size(); j++)//Renamed variable + you can start this loop from j = i as you know there is no occurrence of y before that.
{
if (q[i] == y)
{
count++;
}
}
node*x = new node;
x->char1 = y; //my node have char
x->freq = count; //my node has frequency
list1.push_back(x);
}
count = 0;
check = 0;
}

Printing an integer value from an ASCII character

I am trying to implement the function stoi() in c++. I have made an int array arr to store the integer ASCII of all elements of char_arr. This works fine if I print the values from my char_arr array because its a character array. But, how do I transfer my integer values from the char array to an int array and print only the numbers and not their ASCII?
Code:
int stoi(){
int *arr = new int [strlen(char_arr)];
for (int i=0; char_arr[i]!='\0'; ++i){
arr[i] = char_arr[i];
}
for (int i=0; char_arr[i] != '\0'; ++i){
if (arr[i] >= 48 && arr[i] <= 57){
cout << char_arr[i];
}
}
}
First of all, remove the first loop and use char_arr directly. You don't need to hold ints to make it work.
As for printing int values, you can use this:
for (int i = 0; char_arr[i] != '\0'; ++i) {
if (char_arr[i] >= '0' && char_arr[i] <= '9') { //I would suggest you to use this syntax instead of raw ASCII codes.
cout << (char_arr[i] - '0');
}
}
int stoi(){
/* if you do not use arr.
int *arr = new int[strlen(char_arr)];
for (int i = 0; char_arr[i] != '\0'; ++i){
arr[i] = char_arr[i];
}
*/
int sign = 1, value = 0;
if (*char_arr == '+') {
++char_arr;
}
else if (*char_arr == '-') {
++char_arr;
sign = -1;
}
while (*char_arr) {
if (*char_arr >= '0' && *char_arr <= '9') {
value = value * 10 + *char_arr - '0';
++char_arr;
} else {
break;
}
}
return sign * value;
}
Here's the one I came up with:
#include <cstdio>
#include <cstring>
#define _BASE_ 10
int main(int argc, char **argv)
{
char ascii[] = "474927";
signed int value = 0;
signed int ascii_len = strlen(ascii);
int pos = 0;
for(signed int i = ascii_len-1; i >= 0; i--)
{
if(i == 0 && ascii[i] == '-')
{
value *= -1;
continue;
}
int base = 1;
if(pos > 0)
{
base = _BASE_;
for(int j = 1; j < pos; j++)
base *= _BASE_;
}
value += base * (ascii[i] - 48);
pos++;
}
printf("Value: %d\n", value);
return 0;
}

cellular automaton in c++ with class and object

I did my cellular automaton in c but now I want to convert it to c++ with using class and object. I am new in c++ that is why I need your help. My program crashes after typing decimal number. I think data is not transfered properly between the functions, but I send few hours on it and I cannot get it. I would be pleased if I could get any advice with finding when my error is. I've got 3 files. One is my main, one is file with functions, and the last one is a header.
Main:
#include <iostream>
#include "cellular.h"
using namespace std;
int main()
{
CA myCA;
myCA.run();
return 0;
}
File with functions:
#include "cellular.h"
#include <cstdio>
CA::CA()
{
int WIDTH = 59;
int numOfRules = 8;
currentState = new int [WIDTH];
nextState = new int[WIDTH];
storeTheRules = new int[numOfRules];
}
CA::~CA()
{
delete [] currentState;
delete [] nextState;
delete [] storeTheRules;
}
void CA::run()
{
int x;
int t;
//enter which cellular you want to print out
printf("Enter the number of cellular you want to print out 0-255 (-1 to end):\n");
scanf("%d", &number);
while(number != -1) {
if(number >= 0 && number <= 255) {
for(x = 0; x < WIDTH; x++) {
currentState[x] = 0;
}
for(x = 0; x < WIDTH; x++) {
t = (int)WIDTH/2;
currentState[t] = 1;
}
// convert decimal number to binary
decimalToBinary(number);
// print binary number
printf("In binary:");
for(x = 0; x < numOfRules; x++)
{
printf("%d", storeTheRules[x]);
}
printf("\n");
//print current state
printCellular();
printf("\n");
// calculate for next generation
calcNextGeneration();
// update array
updateArray();
}
else {
printf("\nWrong number entered! Try again\n");
}
//enter which cellular you want to print out
printf("\nEnter the number of cellular you want to print out 0-255 (-1 to end):\n");
scanf("%d", &number);
}
}
void CA::calcNextGeneration()
{
int i;
int j;
int LENGHT = 27;
for(j = 0; j < LENGHT; j++) {
for (i = 0; i < WIDTH; i++) {
left = currentState[i-1];
middle = currentState[i];
right = currentState[i+1];
nextState[i] = rules(left, middle, right);
}
updateArray();
printCellular();
printf("\n");
}
}
int CA::rules(int left,int middle, int right)
{
if(left == 1 && middle == 1 && right == 1)
return storeTheRules[0];
else if(left == 1 && middle == 1 && right == 0)
return storeTheRules[1];
else if(left == 1 && middle == 0 && right == 1)
return storeTheRules[2];
else if(left == 1 && middle == 0 && right == 0)
return storeTheRules[3];
else if(left == 0 && middle == 1 && right == 1)
return storeTheRules[4];
else if(left == 0 && middle == 1 && right == 0)
return storeTheRules[5];
else if(left == 0 && middle == 0 && right == 1)
return storeTheRules[6];
else if(left == 0 && middle == 0 && right == 0)
return storeTheRules[7];
return 0;
}
void CA::printCellular()
{
int i;
for(i = 0; i < WIDTH; i++) {
if(nextState[i] == 1 || currentState[i] == 1)
printf("#");
else
printf(" ");
}
}
void CA::updateArray()
{
int i;
for(i = 0; i < WIDTH; i++) {
currentState[i] = nextState[i];
}
}
// function to convert decimal number to binary
void CA::decimalToBinary(int n)
{
int k;
int i = 0;
for (numOfRules = 7; numOfRules >= 0; numOfRules--) {
k = n >> numOfRules;
if (k & 1)
storeTheRules[i] = 1;
else
storeTheRules[i] = 0;
i++;
}
printf("\n");
}
Header:
#ifndef CELLULAR_H_INCLUDED
#define CELLULAR_H_INCLUDED
// A cellular automaton class
class CA {
private:
int WIDTH;
int numOfRules;
int *currentState;
int *nextState;
int *storeTheRules;
int number;
int left, middle, right;
public:
// Constructor
CA();
// Destructor
~CA();
// Functions
void run();
int rules(int left, int middle, int right);
void calcNextGeneration();
void printCellular();
void updateArray();
void decimalToBinary(int n);
};
#endif // CELLULAR_H_INCLUDED
I am making my code in CodeBlocks. And.. include cstdio is because I didn't changed my printf's from C code yet.
Thank you for any help.
Regards,
Nel
I didn't read through everything, but a few issues upon first glance:
In your constructor you are creating local variables instead of accessing the class variables you intend to modify.
int WIDTH = 59;
int numOfRules = 8;
Also, just as a personal preference, I wouldn't organize this in such a way that a data entry loop getting input from the user is a part of a class. That could just be personal preference though.

count the ocurrences of substrings

I've a task to count the occurrences of sub string in a char String. I write this code but on certain inputs output is wrong. like string is "hassana" and sub is "as" then it outputs 2 ...some one plz help me
int CharString :: countOccurenceOf(const char* substr)
{
int count = 0;
bool find = false;
for(int i = 0; i < size1; i++)
{
if(cstr[i] == substr[0])
{
int x = i;
int c = 1;
find = true;
while ( substr[c] != '\0' && find == true && (x+1) < size1)
{
if(cstr [x+1] != substr[c])
{
find = false;
}
c++;
x++;
}
if (find == true)
{
count++;
i = i + c-1;
}
}
}
return count;
}
Got some Solution.....is that okay?
int CharString :: countOccurenceOf(const char* substr)
{
int len = 0;
if ( substr != '\0')
{
while( substr[len] != '\0')
len++;
}
int count = 0;
bool find = false;
for(int i = 0; i < size1; i++)
{
if(cstr[i] == substr[0])
{
int x = i;
int c = 1;
find = true;
while ( substr[c] != '\0' && find == true && (x+1) < size1)
{
if(cstr [x+1] != substr[c])
{
find = false;
}
c++;
x++;
}
if (find == true && c == len)
{
count++;
i = i + c-1;
}
}
}
return count;
}
The problem is that you're breaking automatically if x+1 < size1. If the first character of the substring matches the last character of the main string, then this will automatically break and "find" will still be set to true so you'll increment matches by 1. There are numerous ways to change your code to fix this problem; hopefully you can find one now that you know what the problem is.
Assuming cstr is your class internal string:
int CharString :: countOccurenceOf(const char* substr)
{
int occurrencies = 0;
unsigned char* s = cstr;
while (s) {
if (strstr(s,substr)) { occurrencies++; s+= strlen(substr); }
else s++;
}
return occurrencies;
}