So i would like to know how to save characters in a char array. something like this.
int const l=100;
char a[l];
char b[l]
cin.getline(a,l);
int d;
d=strlen (a);
int i=0;
for(i=0;i<d;i++)
{
if(a[i]=='a')
{do something so i can save only the items that match the
criteria in the new char array}
I don't know if there is a function to do this or even how i should approach it .
First of all, if you really write in C++, avoid arrays. They are tougher to handle than objects really created for array or string handling, such as std::string.
Try this one:
#include <string>
#include <iostream>
int main(int argc, char * argv[])
{
std::string s, s1;
std::getline(std::cin, s);
for (int i = 0; i < s.length(); i++)
{
if (s[i] == 'a')
s1.push_back(s[i]);
}
std::cout << "Processed string: " << s1;
}
This may help if you don't use STL:
int j = 0; // index for b. An array will be filled from the zero element
for (int i = 0; i < d; i++)
{
if (a[i] == 'a') // or any filter criter
{
b[j] = a[i];
++j;
}
}
b[j] = '\0';
With STL (and C++11):
auto it = std::copy_if(&a[0], &a[d], &b[0], [](char c){ return c == 'a'; });
*it = '\0';
Related
I am trying to use a C Library, which requires that I pass in dynamically allocated c-strings for the functions to modify. However, I want to avoid using new/delete operators because I feel it is better practice to have memory management done under the hood by STL libraries, rather than by me.
Below, I'm trying to use std::string (and vectors) to solve this problem, and preallocating them before passing them to the C function. The examples with one string (CChar, CVoid) work, but I'm still unsure if this is the correct way, or even if it is a safe way (bug-free) to do it. Using vectors does not seem to work at all.
I have included the "C"-way of doing what I want to achieve for both strings and vectors.
#include <string>
#include <iostream>
#include <vector>
// ----------------------------------------------------
// Example C library Code
void CChar(char* data, int len)
{
int i;
for (i = 0; i < len; ++i)
data[i] = 'A' + (i % 26);
}
void CVoid(void* data, int len)
{
char* d = (char*)data;
int i;
for (i = 0; i < len; ++i)
d[i] = 'Z' - (i % 26);
}
void CStrings(char** strings, int count, int lengths)
{
int i, j;
for (i = 0; i < count; ++i)
for (j = 0; j < lengths; ++j)
strings[i][j] = 'A' + ((i * j + i) % 26);
}
// ----------------------------------------------------
// C++ code
int main()
{
// Traditional way, using new/delete.
char* c = new char[11];
CChar(c, 10);
c[10] = '\0';
std::cout << c << std::endl; // ABCDEFGHIJ
delete [] c;
std::string s(10, '\0');
CChar(&s[0], 10);
std::cout << s << std::endl; // ABCDEFGHIJ
CVoid(&s[0], 10);
std::cout << s << std::endl; // ZYXWVUTSRQ
std::vector<std::string> v(5, std::string(10, '\0'));
// Traditional way with arrays of arrays.
char** cc = new char*[5];
for (int i = 0; i < 5; ++i)
{
cc[i] = new char[11];
cc[i][10] = '\0';
}
CStrings(cc, 5, 10);
for (int i = 0; i < 5; ++i)
{
std::cout << cc[i] << std::endl; // AAAAAAAAAA, BCDEFGHIJK, CEGIKMOQSU, DGJMPSVYBE, EIMQUYCGKO
delete [] cc[i];
}
delete [] cc;
// Doesn't compile
// CStrings(&v[0], 5, 10);
// for (int i = 0; i < 5; ++i)
// std::cout << v[i] << std::endl;
return 0;
}
Summary: Is there a good way to use C++'s STL libraries so that I don't need to do my own resource management when trying to use C libraries.
edit: Error cleaning up array of arrays
Sure, you can just use std::vector<char> is you don't want to think about allocation. Here's how you do it:
#include <vector>
int main()
{
std::vector<char> str(100, 0); //Allocate an array of 100 chars and initialize them to 0
SomeFunction(&str[0], str.size()); //Pass the address to the array and its size
return 0;
}
For arrays of arrays, can store a vector<char*> which refers to the starts of the already dynamically allocated std::vector<std::string>.
int main()
{
std::vector<std::string> v(5, std::string(10, '\0'));
std::vector<char*> vc(5);
for (int i = 0; i < 5; ++i)
vc[i] = &(v[i])[0];
CStrings(&vc[0], 5, 10);
for (int i = 0; i < 5; ++i)
std::cout << v[i] << std::endl;
return 0;
}
I have modified the code from my previous question, and now it looks like this:
//#include "stdafx.h"
#include <iostream>
#include <cstring>
#include <chrono>
#include <cassert>
using namespace std;
const int MAX_SIZE=10000;
const int MAX_STRINGS = 10;
char** strings=new char*[10];
int len;
char* GetLongestCommonSubstring( char* str1, char* str2 );
inline void readNumberSubstrings();
inline const char* getMaxSubstring();
void readNumberSubstrings()
{
cin >> len;
assert(len >= 1 && len <=MAX_STRINGS);
for(int i=0; i<len;i++)
strings[i]=new char[MAX_SIZE];
for(int i=0; i<len; i++)
cin >> strings[i];
}
const char* getMaxSubstring()
{
char *maxSubstring=strings[0];
auto begin = chrono::high_resolution_clock::now();
for(int i=1; i < len; i++)
maxSubstring=GetLongestCommonSubstring(maxSubstring, strings[i]);
cout << chrono::duration_cast <chrono::milliseconds> (chrono::high_resolution_clock::now()-begin).count() << endl;
return maxSubstring;
}
char* GetLongestCommonSubstring( char* string1, char* string2 )
{
if (strlen(string1)==0 || strlen(string2)==0) cerr << "error!";
int *x=new int[strlen(string2)+ 1]();
int *y= new int[strlen(string2)+ 1]();
int **previous = &x;
int **current = &y;
int max_length = 0;
int result_index = 0;
int length;
int M=strlen(string2) - 1;
for(int i = strlen(string1) - 1; i >= 0; i--)
{
for(int j = M; j >= 0; j--)
{
if(string1[i] != string2[j])
(*current)[j] = 0;
else
{
length = 1 + (*previous)[j + 1];
if (length > max_length)
{
max_length = length;
result_index = i;
}
(*current)[j] = length;
}
}
swap(previous, current);
}
delete[] x;
delete[] y;
string1[max_length+result_index]='\0';
return &(string1[result_index]);
}
int main()
{
readNumberSubstrings();
cout << getMaxSubstring() << endl;
return 0;
}
It's still solving the generalised longest common substring problem, and now it's rather fast.
But there's a catch: if a user specifies, say, 3 as a number of strings he's about to enter, and then only actually enters one string, this code waits forever.
How do I change that?
If you read from a file and the number of arguments isn't equal to the number of arguments provided, just print a nice, clean error message to the user.
"Expected 7 arguments, received 3:"
Print out the arguments you found so the user has an idea of what the program is looking at when it spits out the error.
As for human input, I agree with the comments. The program should wait until the user close it or enters all the needed arguments.
I have the following c++ program that multiple 2 large numbers :
#include <iostream>
#include <string>
#define OVERFLOW 2
#define ROW b_len
#define COL a_len+b_len+OVERFLOW
using namespace std;
int getCarry(int num) {
int carry = 0;
if(num>=10) {
while(num!=0) {
carry = num %10;
num = num/10;
}
}
else carry = 0;
return carry;
}
int num(char a) {
return int(a)-48;
}
string mult(string a, string b) {
string ret;
int a_len = a.length();
int b_len = b.length();
int mat[ROW][COL];
for(int i =0; i<ROW; ++i) {
for(int j=0; j<COL; ++j) {
mat[i][j] = 0;
}
}
int carry=0, n,x=a_len-1,y=b_len-1;
for(int i=0; i<ROW; ++i) {
x=a_len-1;
carry = 0;
for(int j=(COL-1)-i; j>=0; --j) {
if((x>=0)&&(y>=0)) {
n = (num(a[x])*num(b[y]))+carry;
mat[i][j] = n%10;
carry = getCarry(n);
}
else if((x>=-1)&&(y>=-1)) mat[i][j] = carry;
x=x-1;
}
y=y-1;
}
carry = 0;
int sum_arr[COL];
for(int i =0; i<COL; ++i) sum_arr[i] = 0;
for(int i=0; i<ROW; ++i) {
for(int j=COL-1; j>=0; --j) {
sum_arr[j] += (mat[i][j]);
}
}
int temp;
for(int i=COL-1; i>=0; --i) {
sum_arr[i] += carry;
temp = sum_arr[i];
sum_arr[i] = sum_arr[i]%10;
carry = getCarry(temp);
}
for(int i=0; i<COL; ++i) {
ret.push_back(char(sum_arr[i]+48));
}
while(ret[0]=='0'){
ret = ret.substr(1,ret.length()-1);
}
return ret;
}
void printhuge(string a) {
cout<<"\n";
for(string::iterator i = a.begin(); i!=a.end(); ++i) {
cout<<*i;
}
}
int main() {
string a,b;
cin>>a>>b;
printhuge(mult(a,b));
return 0;
}
All is working fine, but I need to use char[] instead of "string" . I know it's silly but I have to use that format necessary. So - how can I convert the code to work with char[] definition ?
Any ideas is greatly appreciated, Thanks :)
Provided you don't need to modify the C string (the char array), i. e. it can be const char[] or const char *, use the c_str() method of std::string:
const char *c_string = str.c_str();
Edit: so your problem is that you should not use std::string at all. Well, in this case, this is how you can replace C++ strings with C strings:
C strings are 0-terminated arrays of char (or const char). As usually, in certain conditions, they decay into pointers.
You can get the length of a C string using the strlen() function in <string.h>.
To append strings to each other, use the strcat() or strncat() functions. Beware of buffer sizes and the extra space for the terminating NUL character!
etc.
Call std::string::c_str() on your string objects.
Just make sure the buffer isn't modifed by the functions.
Edit
Or, if you need to accept a char[], just create a string out of it.
I'm pretty new to C++ and I have some problems with getting into all that pointer stuff. Basically I am passing a pointer to a Function, creating an Array at that pointer. Back in the main function I can't access this array.
Here's my code:
#include <iostream>
using namespace std;
void createArray(char** dict, int* arraysize)
{
*arraysize = 26*26*26*26;
delete dict;
dict = 0;
//Initialisiere character array of character
//char **wortliste = 0;
dict = new char*[*arraysize];
for(int i = 0; i < *arraysize; i++)
dict[i] = new char[5];
int ctr = 0;
//Erstelle Einträge (sortiert)
for (char i = 'A'; i <= 'Z'; i++)
{
for (char j = 'A'; j <= 'Z'; j++)
{
for (char k = 'A'; k <= 'Z'; k++)
{
for (char l = 'A'; l <= 'Z'; l++)
{
dict[ctr][0] = i;
dict[ctr][1] = j;
dict[ctr][2] = k;
dict[ctr][3] = l;
dict[ctr][4] = '\0';
ctr++;
}
}
}
}
}
int main(void)
{
char** dict = 0;
int arraysize;
createArray(dict, &arraysize);
cout << dict[0] << endl << dict[arraysize-1] << endl;
return 0;
}
I can't figure out my error thank you very much in advance.
In C++ parameters are pass by value (unless explicitly marked as being reference parameters), so when you pass dict, a pointer (to a pointer to char) to createArray, the dict inside your function is a different object, albeit with the same initial value, as the dict in main. If you want to see changes to dict in main you would have to pass it by reference, or pass the address of it into a function taking a char ***.
E.g.
void createArray(char**& dict, int* arraysize)
or
void createArray(char*** pdict, int* arraysize)
{ // use (*pdict) instead of dict ...
and
// ...
createArray(&dict, &arraysize);
A more "C++" way to achieve what you want would be to have:
void createArray( std::vector<std::string>& dict );
and to simply have createArray resize the vector to the required size. Using standard containers like vector and string also frees you of the obligation to explicity deallocate that memory that you allocate which is currently missing from your code.
There are a couple of mistakes.
To delete an array:
char **array = /* new with whatever */;
/* do your work */
for (i = 0; i < array_size; ++i)
delete[] array[i];
delete[] array;
To new an array:
char **array = new char *[array_size];
for (i = 0; i < array_size; ++i)
array[i] = new char[array_size_2];
When deleteing, to make sure you don't iterate over a not-newed array, check it against NULL:
for (i = 0; i < array_size; ++i)
{
if (array[i] != NULL) /* Or simply if (array[i]) */
delete[] array[i];
array[i] = NULL;
}
if (array != NULL)
delete[] array;
array = NULL;
alternatively, since delete makes a check for NULL anyway, you can simplify this to:
if (array != NULL)
for (i = 0; i < array_size; ++i)
delete[] array[i]; /* no need to set to NULL after if going to delete the array */
delete[] array;
array = NULL;
Note: delete deletes a single object while delete[] deletes an array.
I can't imagine what you would do with such data, but you can at least use modern techniques.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<string> create() {
vector<string> result;
for (char i = 'A'; i <= 'Z'; ++i) {
for (char j = 'A'; j <= 'Z'; ++j) {
for (char k = 'A'; k <= 'Z'; ++k) {
for (char l = 'A'; l <= 'Z'; ++l) {
result.push_back(string() + i + j + k + l);
}
}
}
}
return result;
}
int main() {
vector<string> data = create();
cout << data.front() << endl << data.back() << endl;
}
Lets say that I'm trying to solve a parsing problem of string to char **
For some reason the below code generates a lot of trash, can anyone have a look at it please?
Here's what it's supposed to do :
Dump all argv into a string_array
container
Dump everything in the string_array
container into a std::string and
separate with spaces
Break the string down into string
tokens using boost/algorithm/string
create a new char ** and dump all
tokens into it, print out the new char **, clean up
What have I done wrong ?
#include <string>
#include <vector>
#include <iostream>
#include <boost/algorithm/string.hpp>
using namespace std;
using namespace boost;
typedef vector<string> string_array;
int main(int argc, char ** argv)
{
string_array args;
string_array tokens;
cout << "Real arguments :" << endl;
for(int i = 0; i < argc; i++)
{ cout << argv[i] << endl;}
string arg = "";
for(int i = 1; i < argc; i++)
{
args.push_back(argv[i]);
}
for(int i = 0; i < (int)args.size(); i++)
{
arg += args[i];
if(i != (int)args.size() - 1)
arg += " ";
}
split(tokens, arg, is_any_of(" "));
char ** new_args = NULL;
new_args = new char*[(int)tokens.size()];
for(int i = 0; i < (int)tokens.size(); i++)
{
new_args[i] = new char[(int)tokens[i].size()];
for(int j = 0; j < (int)tokens[i].size(); j++)
{
new_args[i][j] = tokens[i][j];
}
}
for(int i = 0; i < (int)tokens.size(); i++)
{ std::cout << new_args[i] << std::endl; }
delete [] new_args;
}
C-style strings (char*) are meant to be zero-terminated. So instead of new char[tokens[i].size()], you need to add 1 to the allocation: new char[token[i].size() + 1]. Also, you need to set new_args[i][tokens[i].size()] = 0 to zero-terminate the string.
Without the zero-terminator, programs would not know when to stop printing, as char* does not hold a string length, unlike std::string.