Why my string has diffrent length than i choosed? - c++

I want to create a string with numbers. So i define length of my string array to 10, but when i start the program in console is 11 chars.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define N 10
using namespace std;
int main()
{
srand(time(0));
int numArr[N];
for(int i = 0; i < N; i++)
numArr[i] = rand() % 26 + 97;
for(int i = 0; i < N; i++)
std::cout << numArr[i] << " ";
std::cout << std::endl;
char str[N] = "";
for(int i = 0; i < N; i++)
str[i] = numArr[i];
std::cout << str << endl;
std::cout << strlen(str);
return 0;
}

A string needs to be terminated with \0 to get its length with strlen, in the codestr isn't terminated with \0, when you add it as last character strlen gives correct answer
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define N 10
using namespace std;
int main()
{
srand(time(0));
int numArr[N];
for(int i = 0; i < N; i++)
numArr[i] = rand() % 26 + 97;
for(int i = 0; i < N; i++)
std::cout << numArr[i] << " ";
std::cout << std::endl;
char str[N + 1] = "";
for(int i = 0; i < N; i++)
str[i] = numArr[i];
str[N] = '\0'; // terminate with \0
std::cout << str << endl;
std::cout << strlen(str);
return 0;
}

It is rather risky to use char[N] when you can use std::string.
Here is safer way to write your code (and you will now get the 10 characters lenght you expect).
int main()
{
srand(time(0));
char numArr[N]; // I changed your type from int to char because you can only pack chars in a string
for(char i = 0; i < N; i++)
numArr[i] = (char)(rand() % 26 + 97);
for(int i = 0; i < N; i++)
std::cout << numArr[i] << " ";
std::cout << std::endl;
std::string str;
str.reserve(N); // not strictly required: this is an optimization
for(int i = 0; i < N; i++)
str.push_back(numArr[i]);
std::cout << str << endl;
std::cout << str.length();
return 0;
}

Related

Make dynamically allocated object type string

I need to make dynamically allocated object type of string to store sentences and after that sentences should be sorted in alphabetical order using std::sort.
This would be correct solution using char array:
#include <cstring>
#include <iostream>
#include <new>
#include <string>
#include <algorithm>
int main() {
std::cout << "How many senteces: ";
int n;
std::cin >> n;
std::cin.ignore(1000, '\n');
char ** sentence = nullptr;
std::cout << "Enter senteces:" << std::endl;
try {
sentence = new char * [n];
for (int i = 0; i < n; i++)
sentence[i] = nullptr;
for (int i = 0; i < n; i++) {
char temp[1000];
std::cin.getline(temp, 1000);
sentence[i] = new char[strlen(temp) + 1];
strcpy(sentence[i], temp);
}
std::sort(sentence, sentence + n, [](const char * a,
const char * b) {
return std::strcmp(a, b) < 0;
});
std::cout << "Sorted sentences:" << std::endl;
for (int i = 0; i < n; i++)
std::cout << sentence[i] << std::endl;
for (int i = 0; i < n; i++)
delete[] sentence[i];
delete[] sentence;
} catch (...) {
std::cout << "Problems with memory!";
return 0;
}
return 0;
}
When I try to convert this to dynamically allocated array type of string, like this:
#include <cstring>
#include <iostream>
#include <new>
#include <string>
#include <algorithm>
#include <cctype>
int main() {
std::cout << "How many senteces: ";
int n;
std::cin >> n;
std::cin.ignore(1000, '\n');
std::string ** sentence = nullptr;
std::cout << "Enter senteces:" << std::endl;
try {
sentence = new std::string * [n];
for (int i = 0; i < n; i++)
sentence[i] = nullptr;
for (int i = 0; i < n; i++) {
std::string temp;
std::getline(std::cin, temp);
sentence[i] = new std::string[temp.length() + 1];
temp = sentence[i];
}
std::sort(sentence, sentence + n, [](std::string a,
std::string b) {
for (char & c: a) c = std::toupper(c);
for (char & c: b) c = std::toupper(c);
return a < b;
});
std::cout << "Sorted sentences:" << std::endl;
for (int i = 0; i < n; i++)
std::cout << sentence[i] << std::endl;
for (int i = 0; i < n; i++)
delete[] sentence[i];
delete[] sentence;
} catch (...) {
std::cout << "Problems with memory!";
return 0;
}
return 0;
}
I get a bunch of errors. Could you explain me how to convert this program of dynamically allocation of char array to dynamically allocated string array on a correct way?
It looks like you think std::string "corresponds to" char, but it corresponds to char*.
You want std::string* sentence = nullptr;.
(A lot of the point of this exercise is to notice how much easier it gets when you don't need to allocate the strings yourself.)
int main() {
try {
std::cout << "How many sentences: ";
int n;
std::cin >> n;
std::cin.ignore(1000, '\n');
std::cout << "Enter sentences:" << std::endl;
std::string* sentence = new std::string [n];
for (int i = 0; i < n; i++) {
std::getline(std::cin, sentence[i]);
}
std::sort(sentence, sentence + n, [](std::string a,
std::string b) {
for (char & c: a) c = std::toupper(c);
for (char & c: b) c = std::toupper(c);
return a < b;
});
std::cout << "Sorted sentences:" << std::endl;
for (int i = 0; i < n; i++)
std::cout << sentence[i] << std::endl;
delete[] sentence;
} catch (...) {
std::cout << "Problems with memory!";
}
}

getting a OUTOFRANGE error with vector in c++ when using insert method

I am getting a OUTOFRANGE error with vector in c++ when using insert method. I don't know why this is happening but I was able to narrow down the problem to one line through debugging. Here is the full code.
//
#include <cstdio>
#include <iostream>
#include <vector>
#include <fstream>
#include <cassert>
#include <string>
using namespace std;
class suffixArray{
public: suffixArray(std:: string concatenated ){
vector<int> attempt1;
const int size = (int)concatenated.length();
int rank[7] = {};
char *suffixPointers[concatenated.length()];
int value[concatenated.length()];
for(int i =0; i <= size-1; i++){
suffixPointers[i] = &concatenated[i];
value[i] = (int)concatenated[i];
}
std::cout << "[";
for(int i = 0; i<= size-1; i++){
std::cout <<value[i] << " ";
}
std::cout << "]"<< std:: endl;
for(int i = 0; i<=size -1; i++){
if(i == 0){
rank[i] = i;
attempt1.push_back(i);
}
else if(value[i] > value[i-1]){
rank[i] = i;
attempt1.push_back(i);
}else{
int current =i;
int savedValue = value[i];
int prevSavedRank;
int indexcounter = i;
while(savedValue <= value[attempt1.at(indexcounter-1)] && indexcounter - 1 >= 0 ){
indexcounter--;
}
cout << indexcounter << endl;
attempt1.insert(attempt1.begin() + indexcounter ,i);
// while(savedValue <= value[rank[current-1]] && current-1 >= 0){
// prevSavedRank= rank[current-1];
// rank[current-1] = i;
// rank[current] = prevSavedRank;
// current--;
// }
}
}
int now;
for(int i = 0; i<= 3; i++){
now = attempt1[i];
std::cout << now << " ";
}
}
};
void read_file(string filename, string& contents, int& num_lines){
ifstream f;
f.open(filename.c_str());
string line;
contents = "";
num_lines = 0;
while(getline(f, line)){
contents.append(line.substr(0, line.length()));
num_lines++;
}
f.close();
}
int main(int argc, const char* argv[]) {
std:: string test = "BANANA$";
suffixArray testString (test);
string fn;
string contents;
int num_lines;
cout << "File 1:" << endl;
cin>> fn;
read_file(fn, contents, num_lines);
cout << "Read: " << fn << "\n";
cout << " * " << num_lines << " lines\n";
cout << " * " << contents.length() << " characters (excluding newlines)\n";
//cout <<" * " << contents << endl;
// char * contents_cstring = (char*)contents.c_str();
//for(int i =0; i< contents.length(); i++){
// assert(contents_cstring[i] == *(contents_cstring + 1));
// assert(contents_cstring[i] == contents.at(i));
//}
//assert(contents_cstring[contents.length()] == '\0');
return 0;
}
I have narrowed down the problem to be the problem to be from this line, but can not figure out why it is occurring, or how to fix it.
attempt1.insert(attempt1.begin() + indexcounter ,i);
Consider the first time the program reaches
int indexcounter = i;
while(savedValue <= value[attempt1.at(indexcounter-1)] && indexcounter - 1 >= 0){
indexcounter--;
}
i will be 1. indexcounter-1 will be 0. If the loop is entered,
int indexcounter = 1;
while(savedValue <= value[attempt1.at(0)] && 0 >= 0 ){
1--;
}
OK, so what happens the next time?
while(savedValue <= value[attempt1.at(-1)] && -1 >= 0 ){
0--;
}
value[attempt1.at(-1)] happens before -1 >= 0, s the trap to prevent -1 fails. Reverse the order of the tests.
while(indexcounter - 1 >= 0 && savedValue <= value[attempt1.at(indexcounter-1)])
Could be more bugs, but after that the program hangs and asks for a file that I don't have.

cpp strange behaviour in this function

I am trying to write a function that calculates the gap heursitic. Below is my code:
#include <iostream>
using namespace std;
#include <vector>
#include <map>
#include <string>
using namespace std;
int main(int argc, char const *argv[])
{
string direction = "backward";
string state_string = "012345";
string goal_state_string = "125430";
int n = 3;
string ignored_pancakes;
int gap = 0;
state_string += to_string(state_string.length());
unsigned int goal_state_index;
goal_state_string += to_string(goal_state_string.length());
if (direction == "forward")
{
for (unsigned int i = 0; i < n; i++)
{
ignored_pancakes += goal_state_string[i];
}
}
else
{
for (unsigned int i = 0; i < n; i++)
{
ignored_pancakes += state_string[i];
}
}
for (int i = 0; i < state_string.length(); i++)
{
if ((ignored_pancakes.find(state_string[i + 1]) != string::npos) or (ignored_pancakes.find(state_string.at(i)) != string::npos))
{
continue;
}
if (abs(goal_state_string.find(state_string[i])-goal_state_string.find(state_string[i+1])!=1)){
gap++;
}
cout << state_string.at(i) << "\t" << state_string.at(i + 1) << endl;
}
// cout << state_string << endl;
cout << ignored_pancakes << endl;
cout << gap << endl;
}
The output that I expect is as follows:
3 4
4 5
5 6
012
2
But what is being printed out is:
3 4
4 5
5 6
Strangely when I comment out the line that says :
cout << state_string.at(i) << "\t" << state_string.at(i + 1) << endl;
The output is:
012
2
Why is it printing out something completely different depending on that line which seems irrelevant.
for (int i = 0; i < state_string.length(); i++)
{
// ...
cout << state_string.at(i) << "\t" << state_string.at(i + 1) << endl;
}
With i + 1 you are accessing the string out of bounds. Change your loop to
for (int i = 0; i < state_string.length() - 1; i++)

How to move word in a circular motion in a string?

I have a string that contains X words (between each word there is a space) I have to move the words in a circular motion to the left according to the number that the user inserts. For example:
"hi my name is aviv and",
the user entered 2. "name is aviv and hi my" I'm looking for legality that repeats itself but I can not find.
Thanks for the guidance. Most importantly, I can not use built-in libraries
Update:
I see there are examples with libraries, I can not use any library.
So what I've done so far.
I wrote a function that gets a string and a number from the user, to move left.
Before sending the string to the function I try to calculate the number of characters I need to move.
My output is - "name is avivhi my"
Regarding the function:
When it gets a string without spaces it works great.
This is my code:
int main()
{
char str[] = "hi my name is aviv";
char str2[] = "hi my name is aviv";
int CountSpace = 0, CountWord = 0;
int Size = 18, flag = 0;
int MoveLeft, Index = 0;
for (int i = 0; str[i] != '\0'; i++)
{
if (str[i] == ' ')
{
CountSpace++;
}
}
CountWord = CountSpace + 1;//Understand how many words there are in a string.
cin >> MoveLeft;
if (MoveLeft >= CountWord)//
{
MoveLeft = (MoveLeft - ((MoveLeft / CountWord) * CountWord));//the size of movment;//To reduce the amount of moves if there is such a possibility
}
for (int i = Size - 1; i >= 0; i--)
{
if (str[i] == ' ')
{
flag++;
}
if (flag == MoveLeft)
{
Index = Size - 1 - (i + 1);//That's the amount of characters I have to move
break;
}
}
MoveLeft = Index;
//This code belongs to the function that accepts a string and the amount to move the characters
for (int i = 0; i < Size; i++)
{
if (i + MoveLeft < Size)
{
str[i] = str2[i + MoveLeft];
}
else
{
str[i] = str2[(i + MoveLeft) - Size];
}
}
cout << "Move Left: " << MoveLeft << endl << str << endl << str2 << endl;
return 0;
}
Here's a hint:
vector<string> words = Your_Code_To_Split_Input_Into_Words();
int count = words.size();
int shift = Your_Code_To_Read_Users_Input();
// print the sentence with the rotation specified by shift
for (int i = 0; i < count; i++)
{
int shifted_index = (i + shift) % count; // modulo math implements circular rotation
string spacing = (i == 0) ? "" : " "; // add a space before each word, except first word
cout << spacing << words[shifted_index];
}
cout << endl;
One possible answer, i highly recommend using vectors instead of regular arrays, it's easy and more dynamic, but i didn't use it because you said you can't use built-in libraries.
#include <iostream>
#include<string>
using namespace std;
int main() {
string a[10000];
int counter = 0;
string b = "hi my name is aviv and";
string temp = "";
int userNum = 2;
for(int i=0;i<b.length() ; i++){
if(b[i]!=' '){
temp+=b[i];
}
else if(b[i]==' ' && temp.length()){
a[counter]= temp;
temp = "";
counter++;
}
}
if(temp.length()){
a[counter] = temp;
}
for(int i=userNum;i<=counter+userNum;i++){
cout<<a[i%(counter+1)]<<endl;
}
}
If you can make use of std::rotate() from <algorithm>, this is much easy to do with that. Parse the words using std::stringstream and store to std::vector. Then apply the shif directly to the vector.
Sample Output: https://www.ideone.com/rSPhPR
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
int main()
{
std::vector<std::string> vec;
std::string str = "hi my name is aviv and";
std::string word;
std::stringstream sstr(str);
while(std::getline(sstr, word,' '))
vec.emplace_back(word);
int shift;
std::cout << "Enter the Shift: ";
std::cin >> shift;
std::rotate(vec.begin(), vec.begin() + shift, vec.end());
for(const auto& it: vec)
std::cout << it << " ";
return 0;
}
Here's a snippet :
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
#define MaxWords 10
int main()
{
stringstream ss;
ss.str("hi my name is aviv and");
string str[MaxWords];
int i;
for (i =0; std::getline(ss, str[i],' ');i++ )
{
cout << str[i] << " ";
}
int n;
cout << "\nEnter pos to split : ";
cin >> n;
for (int j = n; j <= i; j++)
{
cout << str[j] << " ";
}
for (int j = 0; j < n; j++)
{
cout << str[j] << " ";
}
cout << endl;
return 0;
}
Output:

cpp Get numbers from string

What is the simple way to get numbers from given string pattern using regular expressions?
the string pattern is like,
${type:1234} ${type:2345}
I want the numbers, in that case, 1234, 2345.
the string patten can also contain spaces,
${(WS)*type(WS)*:(WS)*1234(WS)*} , ... (more like this)
I need also to check that the string is valid pattern and if it is, to extract the numbers.
I know it can be easily done using tokenizer but I think it will be better to use regular expressions.
you use some magic to achieve what you want using loops:
#include <iostream>
#include <string>
int main()
{
std::string str("${type:1234} ${type:2345}");
int n = 0;
for(int i(0); i < str.length(); i++)
{
if(isdigit(str[i]))
{
n++;
while(isdigit(str[i]))
i++;
}
}
std::cout << "There are: " << n << std::endl;
std::string* strTmp = new std::string[n];
int j = 0;
for(int i = 0; i < str.length(); i++)
{
if(isdigit(str[i]))
{
while(isdigit(str[i]))
{
strTmp[j] += str[i];
i++;
}
j++;
}
}
for(int i = 0; i < n; i++)
std::cout << strTmp[i] << std::endl;
// now you have strTmo holding numbers as strings you can convert them to integer:
int *pInt = new int[n];
for(int i = 0; i < n; i++)
pInt[i] = atoi(strTmp[i].c_str());
for(int i = 0; i < n; i++)
std::cout << "value " << i+1 << ": " << pInt[i] << std::endl;
delete[] strTmp;
strTmp = NULL;
delete[] pInt;
pInt = NULL;
std::cout << std::endl;
return 0;
}