Create an array of char from string array - c++

(language : C++)
I have this array:
string myArray[] = {"Apple", "Ball", "Cat"};
Is it possible to store each element in the above array to a new array? Something like this.
char word1[] = myArray[0];
char word2[] = myArray[1];
char word3[] = myArray[2];
I checked the above code, it would throw an error. How would I get this functionality? I cannot use two-dimensional array because I don't know the length of my word in my actual program. A file has the list of words, I would have to read it into the array and get the above string array.

As per the example that you have posted, this is what you are looking for:
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main() {
string myArray[] = {"Apple", "Ball", "Cat"};
char test0[myArray[0].length()];
strcpy(test0, myArray[0].c_str());
char test1[myArray[1].length()];
strcpy(test1, myArray[1].c_str());
char test2[myArray[2].length()];
strcpy(test2, myArray[2].c_str());
int i=0;
for(i=0; i<(sizeof(test0)/sizeof(*test0)); i++)
cout<<test0[i]<<" ";
cout<<"\n";
for(i=0; i<(sizeof(test1)/sizeof(*test1)); i++)
cout<<test1[i]<<" ";
cout<<"\n";
for(i=0; i<(sizeof(test2)/sizeof(*test2)); i++)
cout<<test2[i]<<" ";
cout<<"\n";
return 0;
}
In the above code, I have created character arrays test0[], test1[] and test2[] of length equal to the corresponding string in myArray[]. Then I used strcpy() to copy the corresponding string from myArray[] to the character array (test0[], etc). Finally, I just printed these new character arrays.
Working code here.
Note: I am assuming that you are using GCC, since it supports VLAs. If not, then you can use an array of particular length (or better yet, a vector).
Hope this is helpful.

Old style (c++98/c++03):
#include <string>
#include <iostream>
int main()
{
std::string myArray[] = { "Apple", "Ball", "Cat" };
char *firstString = new char[myArray[0].length() + 1];
char *secondString = new char[myArray[1].length() + 1];
char *thirdString = new char[myArray[2].length() + 1];
strcpy(firstString, myArray[0].c_str());
strcpy(secondString, myArray[1].c_str());
strcpy(thirdString, myArray[2].c_str());
std::cout << "firstString = " << firstString << std::endl;
std::cout << "secondString = " << secondString << std::endl;
std::cout << "thirdString = " << thirdString << std::endl;
delete firstString;
delete secondString;
delete thirdString;
return 0;
}
New style (c++11/14):
#include <string>
#include <iostream>
#include <memory>
int main()
{
std::string myArray[] = { "Apple", "Ball", "Cat" };
std::unique_ptr<char> firstString{ new char[myArray[0].length() + 1] };
std::unique_ptr<char> secondString{ new char[myArray[1].length() + 1]};
std::unique_ptr<char> thirdString{ new char[myArray[2].length() + 1]};
strcpy(firstString.get(), myArray[0].c_str());
strcpy(secondString.get(), myArray[1].c_str());
strcpy(thirdString.get(), myArray[2].c_str());
std::cout << "firstString = " << firstString.get() << std::endl;
std::cout << "secondString = " << secondString.get() << std::endl;
std::cout << "thirdString = " << thirdString.get() << std::endl;
return 0;
}

Related

How do I remove repeated words from a string and only show it once with their wordcount

Basically, I have to show each word with their count but repeated words show up again in my program.
How do I remove them by using loops or should I use 2d arrays to store both the word and count?
#include <iostream>
#include <stdio.h>
#include <iomanip>
#include <cstring>
#include <conio.h>
#include <time.h>
using namespace std;
char* getstring();
void xyz(char*);
void tokenizing(char*);
int main()
{
char* pa = getstring();
xyz(pa);
tokenizing(pa);
_getch();
}
char* getstring()
{
static char pa[100];
cout << "Enter a paragraph: " << endl;
cin.getline(pa, 1000, '#');
return pa;
}
void xyz(char* pa)
{
cout << pa << endl;
}
void tokenizing(char* pa)
{
char sepa[] = " ,.\n\t";
char* token;
char* nexttoken;
int size = strlen(pa);
token = strtok_s(pa, sepa, &nexttoken);
while (token != NULL) {
int wordcount = 0;
if (token != NULL) {
int sizex = strlen(token);
//char** fin;
int j;
for (int i = 0; i <= size; i++) {
for (j = 0; j < sizex; j++) {
if (pa[i + j] != token[j]) {
break;
}
}
if (j == sizex) {
wordcount++;
}
}
//for (int w = 0; w < size; w++)
//fin[w] = token;
//cout << fin[w];
cout << token;
cout << " " << wordcount << "\n";
}
token = strtok_s(NULL, sepa, &nexttoken);
}
}
This is the output I get:
I want to show, for example, the word "i" once with its count of 5, and then not show it again.
First of all, since you are using c++, I would recommend you to split text in c++ way(some examples are here), and store every word in map or unordered_map. Example of my realization you can find here
But if you don't want to rewrite your code, you can simply add a variable that will indicate whether a copy of the word was found before or after the word position. If a copy was not found in front, then print your word
This post gives an example to save each word from your 'strtok' function into a vector of string. Then, use string.compare to have each word compared with word[0]. Those indexes match with word[0] are marked in an int array 'used'. The count of match equals to the number marks in the array used ('nused'). Those words of marked are then removed from the vector, and the remaining carries on to the next comparing process. The program ends when no word remained.
You may write a word comparing function to replace 'str.compare(str2)', if you prefer not to use std::vector and std::string.
#include <iostream>
#include <string>
#include <vector>
#include<iomanip>
#include<cstring>
using namespace std;
char* getstring();
void xyz(char*);
void tokenizing(char*);
int main()
{
char* pa = getstring();
xyz(pa);
tokenizing(pa);
}
char* getstring()
{
static char pa[100] = "this is a test and is a test and is test.";
return pa;
}
void xyz(char* pa)
{
cout << pa << endl;
}
void tokenizing(char* pa)
{
char sepa[] = " ,.\n\t";
char* token;
char* nexttoken;
std::vector<std::string> word;
int used[64];
std::string tok;
int nword = 0, nsize, nused;
int size = strlen(pa);
token = strtok_s(pa, sepa, &nexttoken);
while (token)
{
word.push_back(token);
++nword;
token = strtok_s(NULL, sepa, &nexttoken);
}
for (int i = 0; i<nword; i++) std::cout << word[i] << std::endl;
std::cout << "total " << nword << " words.\n" << std::endl;
nsize = nword;
while (nsize > 0)
{
nused = 0;
tok = word[0] ;
used[nused++] = 0;
for (int i=1; i<nsize; i++)
{
if ( tok.compare(word[i]) == 0 )
{
used[nused++] = i; }
}
std::cout << tok << " : " << nused << std::endl;
for (int i=nused-1; i>=0; --i)
{
for (int j=used[i]; j<(nsize+i-nused); j++) word[j] = word[j+1];
}
nsize -= nused;
}
}
Notice that the removal of used words has to do in backward order. If you do it in sequential order, the marked indexes in the 'used' array will need to be changed. A running test:
$ ./a.out
this is a test and is a test and is test.
this
is
a
test
and
is
a
test
and
is
test
total 11 words.
this : 1
is : 3
a : 2
test : 3
and : 2
I read your last comment.
But I am very sorry, I do not know C. So, I will answer in C++.
But anyway, I will answer with the C++ standard approach. That is usually only 10 lines of code . . .
#include <iostream>
#include <algorithm>
#include <map>
#include <string>
#include <regex>
// Regex Helpers
// Regex to find a word
static const std::regex reWord{ R"(\w+)" };
// Result of search for one word in the string
static std::smatch smWord;
int main() {
std::cout << "\nPlease enter text: \n";
if (std::string line; std::getline(std::cin, line)) {
// Words and its appearance count
std::map<std::string, int> words{};
// Count the words
for (std::string s{ line }; std::regex_search(s, smWord, reWord); s = smWord.suffix())
words[smWord[0]]++;
// Show result
for (const auto& [word, count] : words) std::cout << word << "\t\t--> " << count << '\n';
}
return 0;
}

How to concatenate strings in an output function?

Some languages have easy ways of doing this, but my question revolves in C and C++.
I wanna do something like this in Java:
public class sandbox {
public static void main(String[] args) {
System.out.println("Thank" + " you!");
}
}
And transfer it in C:
#include <stdio.h>
int main() {
/* The easiest way is like this:
char *text1 = "Thank";
char *text2 = " you";
printf("%s%s\n", text1, text2);
*/
printf("Thank" + " you."); // What I really want to do
}
How do I concatenate strings in a language like this?
You use just nothing:
puts ("Thank" " you.");
Concatenating strings is not that easy in C unfortunately, here's how to do it most succinctly:
char *text1 = "Thank";
char *text2 = " you";
char *text_concat = malloc(strlen(text1) + strlen(text2) + 1);
assert(text_concat);
text_concat = strcpy(text_concat, text1);
text_concat = strcat(text_concat, text2);
printf("%s\n", text_concat);
free(text_concat);
What I have understood from your question, hope the below solution will answer your question.
#include <stdio.h>
int main() {
char s1[100] = "Thank ", s2[] = "You";
int length, j;
// store length of s1 in the length variable
length = 0;
while (s1[length] != '\0') {
++length;
}
// concatenate s2 to s1
for (j = 0; s2[j] != '\0'; ++j, ++length) {
s1[length] = s2[j];
}
// terminating the s1 string
s1[length] = '\0';
printf("After concatenation: %s",s1);
return 0;
}
In C++, you can easily concatenate two string it by adding two string with a + operator.
#include <iostream>
using namespace std;
int main()
{
string s1, s2, result;
cout << "Enter string s1: ";
cin>>s1;
cout << "Enter string s2: ";
cin>>s2;
result = s1 + s2;
cout << "After concatenation: = "<< result;
return 0;
}
This is a concatenation, but is a constant or compile time concatenation, you can't concatenate strings like that, but in case you need to split a string constant in multiple parts is ok:
...
printf("Thank" " you."); // What I really want to do
...
For dynamic, runtime concatenation you need strcat like
strcat(text1, text2);
First you must assure that you have enough memory in target string, see this link http://www.cplusplus.com/reference/cstring/strcat/
Ok, that was the C way, but C++ has STL with std::string
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1 = "hello ", str2 = "world";
cout<< str1 + str2<< endl;
return 0;
}
It is not possible in C to do something like printf("Thank" + " you."); because C doesn't support Operator Overloading Unlike C++. You can refer Is it possible to overload operators in C?

Assigning an integer into index in char * pointer array

Redoing my previous question since I didn't provide enough detail.
I have a char pointer array, char* token[100]. Let's say I have a double-digit number, like 33.
How do I assign this int into an index in the token array, so that when I print out that token it will give me 33 and not some sort of ASCII value?
char* token[100];
int num = 33;
//How do I assign num into a specific token index, like for example:
token[1] = num;
//When I print out that token index, I want 33 to be printed out
cout << token[1] << endl; // I want to have 33 be the result. Right now I have '!' as an output
It seems you mean something like the following
#include <iostream>
#include <string>
#include <cstring>
int main()
{
char * token[100] = {};
int num = 33;
std::string s= std::to_string( num );
token[1] = new char[s.size() + 1];
std::strcpy( token[1], s.c_str() );
std::cout << "token[1] = " << token[1] << '\n';
delete [] token[1];
return 0;
}
The program output is
token[1] = 33
If you are not allowed to use C++ containers and functions then the program can look the following way
#include <iostream>
#include <cstdio>
#include <cstring>
int main()
{
char * token[100] = {};
int num = 33;
char buffer[12];
std::sprintf( buffer, "%d", num );
token[1] = new char[std::strlen( buffer ) + 1];
std::strcpy( token[1], buffer );
std::cout << "token[1] = " << token[1] << '\n';
delete [] token[1];
return 0;
}
I'm convinced, from comments, that you want an array of integer types. If we get further clarification about why this needs to be a char array, I'll update my answer, but from all available information it seems like you really want an integer-type array.
#include <iostream>
int main(int argc, char** argv)
{
int token[100] = {};
int num = 33;
token[1] = num;
std::cout << token[1] << std::endl;
return 0;
}

strncpy and strcat not working the way I think they would c++

I have an assignment to implement a string object ourselves, and am currently stuck when trying to concatenate two such strings. I figured I would go this route:
allocate big enough space to hold
insert beginning of holding string into new space up to index using strncpy(this part works)
cat on the string I am inserting
cat on the remainder of the holding string
Implementation:
#include <iostream>
#include <cstring>
using namespace std;
int main(){
int index = 6;//insertion position
char * temp = new char[21];
char * mystr = new char[21 + 7 +1];
char * insert = new char[7];
temp = "Hello this is a test";
insert = " world ";
strncpy(mystr, temp, index);
strcat(mystr + 7, insert);
strcat(mystr, temp + index);
mystr[21 + 6] = '\0';
cout << "mystr: " << mystr << endl;
return 0;
}
that code prints out gibberish after Hello when using visual studios, but works when using g++ (with warnings), why the discrepancy?
You're mixing native c concepts with c++. Not a good idea.
This is better:
#include <iostream>
#include <string> // not cstring
using namespace std;
int main(){
int index = 6;//insertion position
string temp = "Hello this is a test";
string insert = "world ";
string mystr = temp.substr(0, index) + insert + temp.substr(index);
cout << "mystr: " << mystr << endl;
return 0;
}

Invalid Conversion Problem in C++

I have the following snippet:
string base= tag1[j];
That gives the invalid conversion error.
What's wrong with my code below? How can I overcome it.
Full code is here:
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <time.h>
using namespace std;
int main ( int arg_count, char *arg_vec[] ) {
if (arg_count < 3 ) {
cerr << "expected one argument" << endl;
return EXIT_FAILURE;
}
// Initialize Random Seed
srand (time(NULL));
string line;
string tag1 = arg_vec[1];
string tag2 = arg_vec[2];
double SubsRate = 0.003;
double nofTag = static_cast<double>(atoi(arg_vec[3]));
vector <string> DNA;
DNA.push_back("A");
DNA.push_back("C");
DNA.push_back("G");
DNA.push_back("T");
for (unsigned i=0; i < nofTag ; i++) {
int toSub = rand() % 1000 + 1;
if (toSub <= (SubsRate * 1000)) {
// Mutate
cout << toSub << " Sub" << endl;
int mutateNo = 0;
for (int j=0; j < tag1.size(); j++) {
mutateNo++;
string base = tag1[j]; // This fail
int dnaNo = rand() % 4;
if (mutateNo <= 3) {
// Mutation happen at most at 3 position
base = DNA[dnaNo];
}
cout << tag1[j] << " " << dnaNo << " " << base << endl;
//cout << base;
}
cout << endl;
}
else {
// Don't mutate
//cout << tag1 << endl;
}
}
return 0;
}
Why do I get an Invalid conversion from char to const char* when looping over a string?
The std::string operator [] returns a single char. string cannot be instantiated with a single char.
Use:
string base = string( 1, tag1[j] ) instead
Change it to
char base = tag1[j];
string tag1 = arg_vec[1];
tag1 is a string literal.
string base = tag1[j]; is initialized with a char instead of char *.
Try, char base = tag1[j];
There is no constructor for string that takes just a char (which is what tag1[j] is). You have a couple options:
string base; // construct a default string
base = tag1[j]; // set it to a char (there is an
// assignment from char to string,
// even if there's no constructor
or
string base( 1, tag1[j]); // create a string with a single char
Or as Josh mentioned, you can define base as a char since you're not performing any string operations on it anyway. If you decide to do this you'll need to change DNA to be a vector<char> (and change the initialization of DNA to using chars instead of strings).
One problem is that the error message says the program expects one argument when it actually requires two. You should probably follow the Unix conventions and show the required usage too (or instead):
if (arg_count != 3) {
cerr << "Usage: " << arg_vec[0] << " tag1 tag2";
return EXIT_FAILURE;
}
The names 'argc' and 'argv' are very conventional (and the only major alternative I've seen is 'ac' and 'av'). It might be worth sticking with that.