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;
}
Related
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.
So for this program the user gives a text and it must print the text back modifying in these ways by adding and removing space between words:
Each line should contain 60 characters and be aligned left and right
In each line the biggest space between two words must be bigger than the smallest by only one character and a bigger space must be righter than a smaller one. This is what I have managed to do yet, but without any success.
I tried C++ strings instead of a char array but my knowledge about them is limited yet.
#include <iostream>
using namespace std;
bool isletter(char c) {
return c >= 'a' and c <= 'z' or c >= 'A' and c <= 'Z';
}
int main() {
int c, i = 0, constant = 0, counter = 0;
char text[1500], original[1500];
do {
c = getchar();
original[i] = c;
i++;
} while (c != EOF);
for (int j = 0; j <= i; j++) {
if (original[j] == ' ') {
int n = 0;
j = constant;
while (not isletter(original[j])) {
n++;
text[constant] = original[j];
j = j + n;
}
counter++;
} else if (text[j] == '\n') {
text[j] = ' ';
counter++;
} else {
text[j] = original[j];
counter++;
}
}
for (int i = 0; i < counter; i++) {
cout << text[i];
}
}
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.
The function should simply read a matrix.
Why does it freeze after I enter the first character?
#include "stdafx.h"
#include <iostream>
using namespace std;
void as(char **p,int n,int m)
{
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j < m; j++)
{
cout << "p[" << i << "][" << j << "]=";
cin >> p[i][j];
}
}
int main()
{
char *a[100];
as(a, 3, 3);
return 0;
}
This is undefined behavior: your array is an array of 100 pointers to char. But you've never initialized them. So when you address p[i] it gets an uninitialized pointer that could point anywhere, and when you dereference it with p[i][j] you might then freeze or suffer of anyother symptom of undefined behavior.
If you want to learn to use pointers and arrays:
Solution 1: define your array as char a[100][100];
Solution 2: in the outer loop of as(), start to allocate the chars with p[i] = new char[m];
If you want to learn modern C++:
Solution 3: Forget about memory allocation and deallocation and use vectors instead. The vectors are totally dynamic, so no maximum of 100 rows anymore:
void as(vector<vector<char>> &p, int n, int m)
{
p.resize(n);
int i, j;
for (i = 0; i < n; i++) {
p[i].resize(m);
for (j = 0; j < m; j++)
{
cout << "p[" << i << "][" << j << "]=";
cin >> p[i][j];
}
}
}
int main()
{
vector<vector<char>>a;
as(a, 3, 3);
return 0;
}
If you want to try online...
Solution 4: you want modern C++, but you'd like to use your the elements in a[] as they were a string, for easy output and manipulation, just use the same code as above but replace vector<vector<char>> with vector<string>
And here you can look online the slightly simplified code.
I have for you simple pseudo array on mallocs reallocs and pointers. Maybe it will be interesting for you:
typedef struct arr_str_t{
size_t rows, columns;
char **table;
}dynamicStringTable_t;
int CreateStringTable(dynamicStringTable_t **ptr, int rows, int columns)
{
int result = 0;
*ptr = (dynamicStringTable_t *)malloc(sizeof(dynamicStringTable_t));
if (ptr == NULL) return - 1;
(*ptr)->rows = rows;
(*ptr)->columns = columns;
(*ptr) -> table = (char *)malloc(rows * columns * sizeof(char *));
if (*ptr == NULL)
{
free(*ptr);
return -1;
}
for (int i = 0; i < rows * columns; i++) (*ptr)->table[i] = NULL;
return 0;
}
char *getString(dynamicStringTable_t *ptr, int x, int y)
{
char *result = (ptr == NULL || x >= ptr->columns || y >= ptr->rows || !x || !y) ? NULL : "";
if (result != NULL)
{
result = ptr->table[x + y * ptr->rows];
}
return result;
}
int putString(dynamicStringTable_t *ptr, int x, int y, const char *str)
{
int result = (ptr == NULL || x >= ptr->columns || y >= ptr->rows || str == NULL || !x || !y) * -1;
if (!result)
{
char *tmp = (char *)realloc(ptr->table[x + y * ptr->rows], (strlen(str) + 1) * sizeof(char));
if (tmp == NULL) result = -2;
else
{
ptr->table[x + y * ptr->rows] = tmp;
strcpy(tmp, str);
}
}
return result;
}
int removeString(dynamicStringTable_t *ptr, int x, int y)
{
int result = (ptr == NULL || x >= ptr->columns || y >= ptr->rows || !x || !y) * -1;
if (!result)
{
free(ptr->table[x + y * ptr->rows]);
ptr->table[x + y * ptr->rows] = NULL;
}
return result;
}
int destroyStringTable(dynamicStringTable_t *ptr, int x, int y)
{
int result = (ptr == NULL || x >= ptr->columns || y >= ptr->rows || !x || !y) * -1;
if (!result)
{
if (ptr->table != NULL)
{
for (int i = ptr->rows * ptr->columns - 1; i >= 0; i--)
free(ptr->table[i]);
free(ptr->table);
}
free(ptr);
}
return result;
}
You have a great problem in your code. You are facing a UB in:
char *a[100]; // an array of 100 pointer to a character
// it is not initialized yet
Above no element is initialized (even not allocated).
To correct your code:
char *a[100];
// Allocating the array of 100 elements on the heap:
for(int i(0); i < 100; i++){
a[i] = new char[100]; // let's say your array is n = m
}
as(a, 3, 3);
for(int i = 0; i < 3; i++){
for(int j(0); j < 3; j++)
cout << a[i][j] << ", ";
cout << endl;
}
Last but not least Don't forget to free up memory when you are done with the dynamic array:
for(int i = 0; i < 100; i++)
delete[] a[i];
I have written a small program for run length encoding.
void runLengthEncoding (string& str)
{
int k=0;
int count =1;
for (unsigned i=1, count=1; i<str.size(); ++i)
{
if ( str[i] == str[k])
{
count +=1;
}
else
{
str[++k] = count+'0';
str[++k] = str[i];
count = 1;
}
}
str[++k] = count + '0';
str.resize(k);
}
When I call this function using
string s = "wwwwaaadexxxxxx";
runLengthEncoding (s);
cout << endl << s;
It is printing - "w4a3d1e1x"
It should print - "w4a3d1e1x6"
My doubt is why it is not printing the last count?
Instead of using
str.resize(k)
i need to use
str.resize(k+1);
If you delete for count initialization, and resize correctly, you got it:
void runLengthEncoding (string& str)
{
int k=0;
int count =1;
for (unsigned i=1; i<str.size(); ++i)
{
if ( str[i] == str[k])
{
count +=1;
}
else
{
str[++k] = count+'0';
str[++k] = str[i];
count = 1;
}
}
str[++k] = count + '0';
str.resize(++k);
}