C++ creating a string from char array elements? - c++

I have a char array which is VERY large and I iterate through the array. I look for patterns with logic such as:
if (array[n] == 'x' and array[n+1] == 'y' and array[n+2] == 'z')
{
mystring = array[n+4] + array[n+5];
}
if array[n+4] is '4' and array[n+5] is '5' then mystring = "45"
However, mystring is always "", what am I doing wrong? I don't want to use substring as the array is too large. I just want to cast the chars to strings and then append to mystring.

I suggest so use assign(const char*, len);
no copy constructor is involved
if (array[n] == 'x' and array[n+1] == 'y' and array[n+2] == 'z')
{
mystring.assign(array + n + 4, 2);
}

You're checking for a consecutive "xyz" occurrence , why not simply use std::string ?
std::string s(array);
size_t i =s.find("xyz");
if(i!=std::string::npos && i+5 <= s.size())
{
std::string mystring = std::string(1,array[i + 4]) + array[i + 5];
std::cout<<mystring;
}

You can cast chars to ints and vice versa because they are basic language types. Strings are implemented as a class so you need to invoke the string constructor for both chars then concatenation the two resulting strings into mystring

If you can't use std::string in the first place, as suggested by #P0W (which is a good suggestion), then there is another alternative to do this conversion that does not involve string constructor (I think the solution using string constructor is a great one, but knowing different approaches can give you more flexibility), but relies on std::string::append.
int main ()
{
// create char
char *str1 = new char[6];
strcpy( str1,"hello ");
char *str2 = new char[5];
strcpy(str2, "world" );
// use of append to convert to a string
std::string mystring;
mystring.append(str1);
mystring.append(str2);
std::cout << mystring << std::endl;
}
Check the std::string::append documentation, and you will also see that one of the overloading of this functions is string& append (const char* s, size_t n), which means you can convert just subset of char arrays, as you request it.

Adding characters strings doesn't work like that in C++. The easier way to do this is to create a stringstream and add the characters to the string with the << operator, then recover a string from it using the str() method.
Example:
#include <iostream>
#include <sstream>
using namespace std;
int main(void)
{
char a[] = {'a', 'd', 'c', 'b', 'a' };
stringstream linestream;
linestream << a[0] << a[1];
cout << linestream.str() << endl; // Prints ad
return 0;
}

Related

Struggling with the fundamentals. Especially char[], char* and reading from arrays. Perhaps I should use type string

I need a bit of guidance.
I want to sharpen my skill, so I'm practicing with smaller projects.
The current challenge is to create a function that can count syllables in a user inputted word.
My thinking is to declare an array of vowels: a, e, i, o, u.
then iterate through the user inputted word, checking if any letters of the word match with the vowel array, and if yes, check if the next letter doesn't. (I'm assuming a syllable is defined by the presence of a vowel AND consonant.)
This will need nested for loops, one to iterate through the word, and then another to iterate through the vowel array with the current index of 'word'.
I haven't even figured out how I'm going to do the same for word[i+1] yet.
But I'm struggling because I can't get my program to compile due to basic errors. I should probably use a string class, but I don't know.
Here's what I've got (And it won't compile!):
#include <iostream>
char vowels[] = {'a', 'e', 'i', 'o', 'u'};
int numberOfSyllables(char *word)
{
int numberOfVowelsFound = 0;
for ( &element : word )
{
bool vowelMatch = 0;
for ( &vowel : vowels)
{
if (element == vowel)
{
vowelMatch = 1;
break;
}
}
if ((vowelMatch == 1) numberOfVowelsFound++;
}
return numberOfVowelsFound;
}
int main()
{
char *userInput[50];
std::cout << "Enter a word: ";
std::cin >> *userInput;
std::cout << numberOfSyllables(userInput) << " syllables found";
return 0;
}
This is not a code review website, but I will try my best anyway:
Your for loops don't have types:
for (TYPE &element : word )
The type you want to loop over in this case is char.
if you wanted the compiler to figure out the type for you:
for (auto &element : word)
You are looping over word with a "foreach" style loop, but a char * cannot be looped over this way. To be precise, there is no std::begin and std::end functions defined for char *, so the "foreach" style loop doesn't know where you want your string to begin/end. Either use a different style of loop, or use a type that does support "foreach" style loops (such as std::string or C++17's std::string_view).
You added an extra parenthesis ( in the if statement:
// |
// v
if ((vowelMatch == 1) numberOfVowelsFound++;
You declare your userInput variable as an "array of 40 pointers to characters", but you probably want to write "characters" to it, not "pointers to characters". Change it's type to "array of 40 characters".
Similarly, you dereference your userInput variable (probably to avoid a warning), which, because userInput is an "array of 40 (pointers to char)", will return the first, uninitialized, "pointer to char" in that array (*var is the same as var[0] in this case). Just remove the dereference operator * and change the type of the array as suggested above, and std::cin will figure out what to do. Because you (wrongfully) dereferenced userInput already to avoid a warning, std::cin thinks you want to write to the location pointed to by the uninitialized pointer. You have no control over where your program will write too at this point; it might simply crash.
Finally, you once again pass the wrong type into numberOfSyllables(userInput), as mentioned before, userInput is an "array of 40 pointers to char", while your function expects a "pointer of chars". Change the type of userInput to "array of chars", which the compiler can then convert to "pointer of chars".
Final code:
// compile with -std=c++17 for std::string_view, or use another loop style
#include <string_view>
#include <iostream>
char vowels[] = {'a', 'e', 'i', 'o', 'u'};
int numberOfSyllables(char *word)
{
int numberOfVowelsFound = 0;
// `std::string_view` can be used in "foreach" style loops
// we need to use `const char`, since `std::string_view` is a "fake string" and not writable
for (const char &element : std::string_view(word))
// Another loop style (This even works in C):
// for (int i=0; word[i] != '\0'; i++) // While the current element is not NUL
// {
// const char element = word[i]; // Remember the current element
{
bool vowelMatch = 0;
for (const char &vowel : vowels) // Use const here too just for good measure
{
if (element == vowel)
{
vowelMatch = 1;
break;
}
}
if (vowelMatch == 1) numberOfVowelsFound++; // Removed a parenthesis here
}
return numberOfVowelsFound;
}
int main()
{
char userInput[50]; // Changed type of this variable
std::cout << "Enter a word: ";
std::cin >> userInput; // Removed a dereference here
std::cout << numberOfSyllables(userInput) << " syllables found";
return 0;
}

How to see if two char variables equal to each other

#include <iostream>
using namespace std;
I want the user to input two char sequences (such as adc and abd) and the program will tell them that the characters are equal as a whole or not.(the output now would be FALSE )
I am not sure what to do with declaring my char variables.
char x[100]{};
char y[100]{};
This is my isEqual function to work out if the two char values are the same
void isEqual(char x , char y)
{
for ( int i = 0 ; x[i] != '\0';i++){
for ( int j = 0 ; y[j] != '\0'; j++){
if ( x[i]==y[j]){
cout<<"TRUE";
}else{
cout<<"FALSE";
}
}
}
}
So the user inputs two char variables here and then I call the isEqual function to see if they are True or False.
int main()
{
cout<<"Enter first characters :";
cin>>x;
cout<<"Enter second characters :";
cin>>y;
isEqual(x,y);
}
In your example, you have one mistake and one unclarity.
Mistake:
You have defined x and y like this:
char x[100]{};
char y[100]{};
After words you create a method, which has two parameters:
void isEqual(char x , char y)
If you notice, x and y are char arrays. Meanwhile the method isEqual has two parameters, which are just char and not char arrays. So whenever you want to use the first two elements in the method, it will be impossible, because of this incosistency.
In this example, I understand, that you want to compare actually two strings. Only comparing the strings to be more exact. As such there is a far easier and better way to compare groups of chars using strings:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string x, y;
cin >> x >> y;
if (x.compare(y) == 0) /*They are equal*/ {
cout << "True";
} else {
cout << "False";
}
}
This is a simple example, which uses functions from libraries, already existing in c++. You can check this page for more details on the compare function mentioned above.
Supposing you are a begginer, the most important part, you should understand at the beggining, to be able to use it later on:
0: They compare equal
smaller than 0: Either the value of the first character that does not match is lower in the compared string, or all compared characters match but the
compared string is shorter.
greater than 0: Either the value of the first character that does not match
is greater in the compared string, or all compared characters match but the
compared string is longer.
Char is a single character like 'a', "abc" is not a char variable it is string varibale.
Comparing char not differs form comparing any other type like integer numbers just use == operator:
char a = 'a';
char b = 'b';
bool isSame = a == b;
Is same will be false in this case.
In C there is no variable type for string, so you should use array of chars, and you couldn't use == operator, there is a special function for it, it's called strcmp:
const char* string1 = "I am a string";
const char* string2 = "I am a string";
int isEqual = strcmp( string1, string2 );
In this case isEqual will return 0, means that string is equal, don't get confused by this, see description for details of meaning values.
In C++ there is special class for strings it's called std::string, also there is a speciali defined == operator for this type, so you can use it as usual:
std::string string1 = "I am a string";
std::string string2 = "I am a string";
bool isEqual = string1 == string2;
Or you can use method compare wich is same as strcmp:
std::string string1 = "I am a string";
std::string string2 = "I am a different string";
int res = string1.compare( string2 );
In this case res will be equal to 1

Modifying dynamic character arrays using pointers

I'm trying to concatenate two dynamic c arrays (containing strings) using pointers. I looked up a bunch of things online that use strcat, but I need to learn how to use pointers to do this. I'm not exactly clear on what a dynamic c array is anyway, I just know I have to use "new" for it. Here's my current code that won't compile:
#include <iostream>
using namespace std;
#define MAX_CHAR 50
void append(char*, char*);
int main()
{
char *str1 = new char[MAX_CHAR];
char *add1 = new char[MAX_CHAR];
str1 = "This string";
add1 = " add this one";
append(str1, add1);
cout << str1;
delete [] add1;
delete [] str1;
return 0;
}
void append(char *str, char *add)
{
while(*str != '\0')
str++;
while(*add != '\0')
{
*str = *add;
add++;
str++;
}
*str = '\0';
}
This part doesn't do what you think it does:
str1 = "This string";
add1 = " add this one";
You're attempting to assign a string literal ("This string") to a string pointer (str1). That won't work because:
you've basically thrown away the pointers that you just allocated with new one line ago and
string literals cannot be modified during run time (literals are of type const char [], so you should expect a compiler error/warning about this).
Hence, you're going to need to manually copy the string literal into your char array. You can use the standard library function strcpy for this (this requires <cstring>):
std::strcpy(str1, "This string");
std::strcpy(add1, " add this one");

How to extract words out of a string and store them in different array in c++

How to split a string and store the words in a separate array without using strtok or istringstream and find the greatest word?? I am only a beginner so I should accomplish this using basic functions in string.h like strlen, strcpy etc. only. Is it possible to do so?? I've tried to do this and I am posting what I have done. Please correct my mistakes.
#include<iostream.h>
#include<stdio.h>
#include<string.h>
void count(char n[])
{
char a[50], b[50];
for(int i=0; n[i]!= '\0'; i++)
{
static int j=0;
for(j=0;n[j]!=' ';j++)
{
a[j]=n[j];
}
static int x=0;
if(strlen(a)>x)
{
strcpy(b,a);
x=strlen(a);
}
}
cout<<"Greatest word is:"<<b;
}
int main( int, char** )
{
char n[100];
gets(n);
count(n);
}
The code in your example looks like it's written in C. Functions like strlen and strcpy originates in C (although they are also part of the C++ standard library for compatibility via the header cstring).
You should start learning C++ using the Standard Library and things will get much easier. Things like splitting strings and finding the greatest element can be done using a few lines of code if you use the functions in the standard library, e.g:
// The text
std::string text = "foo bar foobar";
// Wrap text in stream.
std::istringstream iss{text};
// Read tokens from stream into vector (split at whitespace).
std::vector<std::string> words{std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>{}};
// Get the greatest word.
auto greatestWord = *std::max_element(std::begin(words), std::end(words), [] (const std::string& lhs, const std::string& rhs) { return lhs.size() < rhs.size(); });
Edit:
If you really want to dig down in the nitty-gritty parts using only functions from std::string, here's how you can do to split the text into words (I leave finding the greatest word to you, which shouldn't be too hard):
// Use vector to store words.
std::vector<std::string> words;
std::string text = "foo bar foobar";
std::string::size_type beg = 0, end;
do {
end = text.find(' ', beg);
if (end == std::string::npos) {
end = text.size();
}
words.emplace_back(text.substr(beg, end - beg));
beg = end + 1;
} while (beg < text.size());
I would write two functions. The first one skips blank characters for example
const char * SkipSpaces( const char *p )
{
while ( *p == ' ' || *p == '\t' ) ++p;
return ( p );
}
And the second one copies non blank characters
const char * CopyWord( char *s1, const char *s2 )
{
while ( *s2 != ' ' && *s2 != '\t' && *s2 != '\0' ) *s1++ = *s2++;
*s1 = '\0';
return ( s2 );
}
try to get a word in a small array(obviously no word is >35 characters) you can get the word by checking two successive spaces and then put that array in strlen() function and then check if the previous word was larger then drop that word else keep the new word
after all this do not forget to initialize the word array with '\0' or null character after every word catch or this would happen:-
let's say 1st word in that array was 'happen' and 2nd 'to' if you don't initialize then your array will be after 1st catch :
happen
and 2nd catch :
*to*ppen
Try this. Here ctr will be the number of elements in the array(or vector) of individual words of the sentence. You can split the sentence from whatever letter you want by changing function call in main.
#include<iostream>
#include<string>
#include<vector>
using namespace std;
void split(string s, char ch){
vector <string> vec;
string tempStr;
int ctr{};
int index{s.length()};
for(int i{}; i<=index; i++){
tempStr += s[i];
if(s[i]==ch || s[i]=='\0'){
vec.push_back(tempStr);
ctr++;
tempStr="";
continue;
}
}
for(string S: vec)
cout<<S<<endl;
}
int main(){
string s;
getline(cin, s);
split(s, ' ');
return 0;
}

How to append a char to a std::string?

The following fails with the error prog.cpp:5:13: error: invalid conversion from ‘char’ to ‘const char*’
int main()
{
char d = 'd';
std::string y("Hello worl");
y.append(d); // Line 5 - this fails
std::cout << y;
return 0;
}
I also tried, the following, which compiles but behaves randomly at runtime:
int main()
{
char d[1] = { 'd' };
std::string y("Hello worl");
y.append(d);
std::cout << y;
return 0;
}
Sorry for this dumb question, but I've searched around google, what I could see are just "char array to char ptr", "char ptr to char array", etc.
y += d;
I would use += operator instead of named functions.
Use push_back():
std::string y("Hello worl");
y.push_back('d')
std::cout << y;
To add a char to a std::string var using the append method, you need to use this overload:
std::string::append(size_type _Count, char _Ch)
Edit :
Your're right I misunderstood the size_type parameter, displayed in the context help. This is the number of chars to add. So the correct call is
s.append(1, d);
not
s.append(sizeof(char), d);
Or the simpliest way :
s += d;
In addition to the others mentioned, one of the string constructors take a char and the number of repetitions for that char.
So you can use that to append a single char.
std::string s = "hell";
s += std::string(1, 'o');
I test the several propositions by running them into a large loop.
I used microsoft visual studio 2015 as compiler and my processor is an i7, 8Hz, 2GHz.
long start = clock();
int a = 0;
//100000000
std::string ret;
for (int i = 0; i < 60000000; i++)
{
ret.append(1, ' ');
//ret += ' ';
//ret.push_back(' ');
//ret.insert(ret.end(), 1, ' ');
//ret.resize(ret.size() + 1, ' ');
}
long stop = clock();
long test = stop - start;
return 0;
According to this test, results are :
operation time(ms) note
------------------------------------------------------------------------
append 66015
+= 67328 1.02 time slower than 'append'
resize 83867 1.27 time slower than 'append'
push_back & insert 90000 more than 1.36 time slower than 'append'
Conclusion
+= seems more understandable, but if you mind about speed, use append
Try the += operator link text,
append() method link text,
or push_back() method link text
The links in this post also contain examples of how to use the respective APIs.
the problem with:
std::string y("Hello worl");
y.push_back('d')
std::cout << y;
is that you have to have the 'd' as opposed to using a name of a char, like char d = 'd'; Or am I wrong?
int main()
{
char d = 'd';
std::string y("Hello worl");
y += d;
y.push_back(d);
y.append(1, d); //appending the character 1 time
y.insert(y.end(), 1, d); //appending the character 1 time
y.resize(y.size()+1, d); //appending the character 1 time
y += std::string(1, d); //appending the character 1 time
}
Note that in all of these examples you could have used a character literal directly: y += 'd';.
Your second example almost would have worked, for unrelated reasons. char d[1] = { 'd'}; didn't work, but char d[2] = { 'd'}; (note the array is size two) would have been worked roughly the same as const char* d = "d";, and a string literal can be appended: y.append(d);.
Also adding insert option, as not mentioned yet.
std::string str("Hello World");
char ch;
str.push_back(ch); //ch is the character to be added
OR
str.append(sizeof(ch),ch);
OR
str.insert(str.length(),sizeof(ch),ch) //not mentioned above
Try using the d as pointer
y.append(*d)
I found a simple way...
I needed to tack a char on to a string that was being built on the fly. I needed a char list; because I was giving the user a choice and using that choice in a switch() statement.
I simply added another std::string Slist; and set the new string equal to the character, "list" - a, b, c or whatever the end user chooses like this:
char list;
std::string cmd, state[], Slist;
Slist = list; //set this string to the chosen char;
cmd = Slist + state[x] + "whatever";
system(cmd.c_str());
Complexity may be cool but simplicity is cooler. IMHO
there are three ways to do this:
for example, we have code like this:
std::string str_value = "origin";
char c_append = 'c';
we usually use push_back().
str_value.push_back(c)
use += .
str_value += c
use append method.
str_value.append(1,c)
And you can learn more about the methods of string from http://www.cplusplus.com/reference/string/string/
str.append(10u,'d'); //appends character d 10 times
Notice I have written 10u and not 10 for the number of times I'd like to append the character; replace 10 with whatever number.
If you are using the push_back there is no call for the string constructor. Otherwise it will create a string object via casting, then it will add the character in this string to the other string. Too much trouble for a tiny character ;)