The following code is part of my project in C++98, therefore i'm not allowed to use vectors and such. Now the main use for this function is to break down a single string line, to an array of strings using the given delimeter, and the size is basically the number of words that i need to return. the problem is that when i debug and check nums towards the end, it changed it's size to 4, and only returned the first word, filled by every char of it.As if, nums is now char* i have changed the code many times, but i don't where i went wrong, any advice?
string* Split(string ss,char delimeter,int size)
{
string *nums=new string[size];
int index_c, index_sw=0;
for (int i = 0; i < size; i++)
{
for(unsigned int j=0;j<ss.length();j++)
{
if (ss.at(j) == delimeter)
{
index_c = j;
nums[i] = ss.substr(index_sw, index_c);
index_sw += index_c;
i++;
}
}
break;
}
return nums;
}
Since you do not know the number of words in the string ss beforehand, you cannot specify size when calling the Split function. Not knowing size you will not be able to allocate memory to nums.
So you are better off using a vector of strings. As pointed out, vector is available in C++98.
Then your modified Split function will look like this:
vector<string> Split(string ss, char delimiter)
{
vector<string> vs;
int index_c, index_sw=0, j;
for(j=0;j<ss.length();j++)
{
if (ss.at(j) == delimiter)
{
index_c = j;
vs.push_back(ss.substr(index_sw, index_c - index_sw));
index_sw = index_c + 1;
}
}
vs.push_back(ss.substr(index_sw, j - index_sw));
return vs;
}
which then can be called like this:
vector<string> ret = Split("This is a stackoverflow answer", ' ');
See demo here.
Related
I tried to reverse a string using char array but in the output it prints some garbage value, I am unaware of that what is the cause plus it is only happening in large strings.
my code
string reverseWord(string str){
int j = 0, n=0;
n = str.length();
char t[n]={0};
for(int i=n-1;i>=0;i--)
{
t[j]=str[i];
j+=1;
}
return t;
}
input = APFGMRZXIFPSXKOQDRRQJBBZ
output = ZBBJQRRDQOKXSPFIXZRMGFPAB#
I want to know the reason behind # these two garbage values
Using online IDE of gfg.
C-style strings must be terminated by a null-character '\0'.
Instead of using Variable-Length Array, which is not in the standard C++, you should directly allocate string because you are returning that. (assuming that string here means std::string)
string reverseWord(string str){
int j = 0, n=0;
n = str.length();
string t(n); // allocate string instead of VLA
for(int i=n-1;i>=0;i--)
{
t[j]=str[i];
j+=1;
}
return t;
}
I am writing code that finds the number of palindrome strings in a given array of strings. I think I have the right idea, but I am getting weird errors when I run it. What exactly am I doing wrong?
int countPalindromes(string s) {
int size = s.size();
int counter = 0;
string forwardSum = "";
string backwardSum = "";
for(int i = 0; i < size; i++){
for(int j = i; j < size; i++){
forwardSum.push_back(s[j]);
backwardSum.push_back(s[(n - 1)-j]);
if(forwardSum == backwardSum){
counter++;
}
}
}
return counter;
}
string forwardSum[] = {};
This is an array of zero size (which I don't believe is legal but we'll let that pass)
forwardSum[i] = forwardSum[i] + s[j];
This is an attempt to access the ith element of an array which has zero size.
That's bad.
I'm not really following your code (it's late at night), but I think you probably want forwardSum and backwardSum to be strings not arrays of strings. And you probably want to use push_back to add characters from s to those strings. I.e.
string forwardSum;
...
forwardSum.push_back(s[j]); // add s[j] to forwardSum
But if you really do want forwardSum to be an array, then the sensible thing to do would be to use a vector instead.
vector<string> forwardSum(size); // a vector of strings with the given size
Now that should at least not crash with the rest of your code.
I am trying to write a function that takes a string and a delimiter as an input and return an array of strings. For some reason, the following code runs into segmentation error. I am wondering what could be the problem?
char** split(string thing, char delimiter){
thing+='\0';//add null to signal end of string
char**split_string = new char*[100];
int i=0,j=0,l=0; //indexes- i is the ith letter in the string
// j is the jth letter in the lth string of the new array
int length = thing.length();
while (i < length){
if ((thing[i]!=delimiter && thing[i]!='\0')){
split_string[l][j]=thing[i];
j++;
}
else {
j=0; //reset j-value
l++;
}
i++;
}
return split_string;
}
After doing
char**split_string = new char*[100];
You still need to initialize each of the 100 char * pointers you created.
static const size_t str_len = 50; //assuming length will not exceed
for( size_t ix = 0 ; ix < 100 ; ++ix){
split_string[ix] = new char[str_len];
}
Also you need to make sure while writing to split_string you do not exceed the allocated memory in which case its 50 and you don't have splited strings more then 100.
Better split a std::string to std::vector<std::string>. Use the function below
#include <sstream>
#include <string>
#include <vector>
std::vector<std::string> split(std::string str, char delim) {
std::vector<std::string> result;
std::stringstream ss(str);
std::string token;
while (getline(ss, token, delim))
result.push_back(token);
return result;
}
1) Please allocate memory for each substring (something like char[l] = new char[100]) when ever you find a new substring.
As you do not know the number of substring in the beginning itself, please consider using vector. consider using vector < string > split_string. In the loop when ever you find a new sub string you just push that string in the vector. In the end, you will have all the splitted strings in the vector.
Each char * has to be individually initialized like this.
int len = 100;
char**split_string = new char*[len]; // len holds the number of pointers
for(int k = 0; k < len; k++) {
split_string[k] = new char[500]; // holds len of string (here Max word size is considered 500)
}
In C++, sticking to the usage of std::string would be more recommended to reduce complexity and increase readablity.
Your code will fail to catch hold of the last substring as you are breaking out of while-loop just before finding \0. To fix that you need to change the while (i < length) to while (i <= length).
Using vector < string >:
vector<string> split(string thing, char delimiter){
int len = 100;
vector<string> v;
char c[500];
int i=0,j=0;
int length = thing.length();
while (i <= length){
if ( thing[i] != delimiter && thing[i] != '\0') {
c[j]=thing[i];
j++;
}
else {
c[j] = '\0';
v.push_back(c);
memset(c, 0, sizeof c);
j = 0;
}
i++;
}
return v;
}
Demo.
so I'm working on a project that I have to read contents from a file and then analyze them. But I'm having a problem with getting the string out of a pointer that contains the address to what I need.
string lePapel(vector<char> vec){
string *str, s;
int i, j = 0;
vector<char> aux;
aux.resize(6);
for (i = 57; i <= 62; i++){
aux[j] = vec[i];
j++;
}
str = new string[aux.size()];
for (i = 0; i < 6; i++){ str[i] = aux[i]; }
return s;
}
So, the file contains in the array positions from 57 to 62 the word: ABCB4, but when returning the string s my output is A only as expected because of the pointer.
The thing is that I have been trying to find a solution and storing the whole content from vec[57] to vec[64] into the string s and returning it, and the closest that I got to returning anything plausible was using a pointer.
So, now to my question, how can I iterate the *str pointer and copy the whole content to s and return it?
Thanks in advance
I'd suggest you to not use pointers on string in your case. The following code is probably what you want :
#include <iostream>
#include <string>
#include <vector>
using namespace std;
string lePapel(vector<char> vec){
int j = 0;
vector<char> aux;
aux.resize(6);
for (int i = 57; i <= 62; i++){
aux[j] = vec[j];
j++;
}
string str;
str.reserve(6);
for (int i = 0; i < 6; i++){ str.push_back(aux[i]); }
return str;
}
int main() {
char x[5] = {'A', 'B', 'C', 'B', '4'};
vector<char> vec(x, x + 5);
string s = lePapel(vec);
cout << s;
return 0;
}
Tested here : Tested code
About reserving space to your vector : c++ vector::reserve
Same for strings : reserve for strings
The dynamic array of string objects and the whole aux vector seem completely needless here (unless there's some other purpose for them in your code). Additionally, str is currently causing a memory leak because you never delete it when you're finished.
A much simpler approach is just to append the characters one-at-a-time to the s string object (assuming it's a std::string):
string lePapel(vector<char> vec) {
string s;
for (int i = 57; i <= 62; i++) {
s += vec[i];
}
return s;
}
There are various ways to make the code even shorter (and more efficient) than that though, if you really want to.
EDIT: If you still need/want to iterate your dynamic array and concatenate the contents into s, here's how you could do it:
for (i = 0; i < 6; i++) s += str[i];
delete [] str; //<-- very important!
Short answer, you don't want a string * you want a char *. What you created is a string array. String objects contain a pointer to the char * data you are trying to capture. Also, the sizeof(std::string) (8 bytes in size) is a lot bigger than sizeof(char) (1 byte in size) the second character you store is 8 bytes away from the first character instead of being adjacent.
There are a lot of other C++ style and safety concerns, but I'll stick with the question. ;)
I have a program that is trying to sort some names alphabetically. I run it and it does not have any errors, but the names are not sorted. I compare 2 names and see which one is supposed to be shifted in the array.
Here is the code:
void sort_names(char array[])
{
const int arraysize = 5;
// Step through each element of the array
for (int startindex = 0; startindex < arraysize; startindex++)
{
int smallestnum = startindex;
for (int currentindex = startindex + 1; currentindex < arraysize; currentindex++)
{
// If the current element is smaller than our previously found smallest
if ((student_list[currentindex].lname) < (student_list[smallestnum].lname))
// Store the index
smallestnum = currentindex;
}
// Swap our start element with our smallest element
swap(student_list[startindex], student_list[smallestnum]);
}
}
My struct looks like this:
struct student {
char fname[30];
char lname[30];
};
Do I have to convert these to strings somewhere because they are characters arrays? I am kind of lost and trying to figure out how to make it sort properly.
The Problem is that in this line:
if ((student_list[currentindex].lname) < (student_list[smallestnum].lname))
it doesn't compare string characters, but rather compares memory adresses.
If you still want to use char arrays, you have to use the strcmp function. However, I recommed that you use string instead.
The problem is this line:
if ((student_list[currentindex].lname) < (student_list[smallestnum].lname))
The line compares the pointers, it does not compare the contents.
It should be:
if ( strcmp( student_list[currentindex].lname, student_list[smallestnum].lname ) < 0 )
Another alternative is to use std::string instead, which has built-in comparisons. For example:
struct student {
std::string fname;
std::string lname;
};