Error "stack smashing detected" while prepending line numbers in a string - c++

I'm taking a string as input for the function, and I'm trying to prepend line numbers to every new line in the string. I'm also returning a string but it keeps giving me this error: stack smashing detected.
Here's the code:
string prepend(string code) {
string arr;
int i = 0;
int j = 0;
int count = 100;
while (code[i] != '\0') {
if (j == 0) {
arr[j] = count;
arr[j + 3] = ' ';
j = j + 4;
}
if (code[i] == '\n') {
arr[j + 1] = count;
arr[j + 3] = ' ';
j = j + 4;
}
arr[j] = code[i];
i++;
j++;
count++;
}
return arr;
}

There are several errors in your code,
you should convert int to string using to_string()
you should iterate string using its size()
...
#include <iostream>
#include <string>
using namespace std;
string prepend(string code) {
string arr;
int count = 1;
arr += to_string(count++) + " ";
for (size_t i = 0; i < code.size(); ++i) {
arr += code[i];
if (code[i] == '\n') {
arr += to_string(count++) + " ";
}
}
return arr;
}
int main(int argc, char **argv) {
string code = "a\nbc\nd ef g\n\n";
cout << prepend(code);
return 0;
}

Related

Why the simple multiplication would result in some garbled characters?

I try to design a program that implements the multiplication between two big integers(Using C++). But after I complete it, I found that if I input the two integers by the command arguments, the results would be sometimes very weird and sometimes right. Please help me figure out the reason and tell me how to fix it. Thanks (The main function that implements the function of multiplication between two big integers is mul() ).
#include <iostream>
#include <cstring>
#include <stdlib.h>
using namespace std;
void mul(char *c1, char *c2, int len1, int len2);
void printArr(char *c1, char *c2, int len1, int len2);
int main(int argc, char **argv)
{
if (argv[1] != NULL)
{
char cArr1[500], cArr2[500];
for (int i = 0; i < strlen(argv[1]); i++)
{
cArr1[i] = argv[1][i];
}
for (int i = 0; i < strlen(argv[2]); i++)
{
cArr2[i] = argv[2][i];
}
int len1 = strlen(cArr1);
int len2 = strlen(cArr2);
printArr(cArr1, cArr2, len1, len2);
(len1 > len2) ? mul(cArr1, cArr2, len1, len2) : mul(cArr2, cArr1, len2, len1);
exit(100);
}
while (true)
{
cout << "Please input two integers" << endl;
char cArr1[500], cArr2[500];
cin >> cArr1;
if (cArr1[0] == 'q' && cArr1[1] == 'u' && cArr1[2] == 'i' && cArr1[3] == 't')
{
exit(1000);
}
cin >> cArr2;
int parity = 0;
int len1 = strlen(cArr1);
int len2 = strlen(cArr2);
printArr(cArr1, cArr2, len1, len2);
if (cArr1[0] == '-')
{
for (int i = 1; i < len1; i++)
{
cArr1[i - 1] = cArr1[i];
}
parity++;
len1--;
}
if (cArr2[0] == '-')
{
for (int i = 1; i < len2; i++)
{
cArr2[i - 1] = cArr2[i];
}
parity++;
len2--;
}
bool isDigit = true;
for (int i = 0; i < len1; i++)
{
if (!isdigit(cArr1[i]))
{
isDigit = false;
}
}
for (int i = 0; i < len2; i++)
{
if (!isdigit(cArr2[i]))
{
isDigit = false;
}
}
if (!isDigit)
{
cout << "\rInvalid input. Try again" << endl;
continue;
}
if (parity % 2 != 0)
{
cout << "-";
}
(len1 > len2) ? mul(cArr1, cArr2, len1, len2) : mul(cArr2, cArr1, len2, len1);
}
}
void mul(char *bigger, char *smaller, int bigLen, int smallLen)
{
int *bigNum = new int[bigLen];
int *smallNum = new int[smallLen];
for (int i = 0; i < bigLen; i++)
{
bigNum[i] = bigger[bigLen - i - 1] - '0';
}
for (int i = 0; i < smallLen; i++)
{
smallNum[i] = smaller[smallLen - i - 1] - '0';
}
int res[30];
for (int i = 0; i < 30; i++)
{
res[i] = 0;
}
for (int i = 0; i < smallLen; i++)
{
for (int j = 0; j < bigLen; j++)
{
res[i + j] += bigNum[j] * smallNum[i];
}
}
for (int i = 0; i < bigLen + smallLen; i++)
{
int digit = res[i] % 10;
int carry = res[i] / 10;
res[i] = digit;
res[i + 1] += carry;
}
bool null = false;
for (int i = bigLen + smallLen - 1; i >= 0; i--)
{
if (res[i] != 0 && res[i + 1] == 0)
{
null = true;
}
if (null)
{
cout << res[i];
}
}
cout << endl;
}
void printArr(char *c1, char *c2, int len1, int len2)
{
for (int i = 0; i < len1; i++)
{
cout << c1[i];
}
cout << " * ";
for (int i = 0; i < len2; i++)
{
cout << c2[i];
}
cout << " = ";
}
Just initialize your char arrays to empty ones:
char cArr1[500] = {};
char cArr2[500] = {};
then, for the sake of clarity, assign the lengths from your arguments to two integers, casting them since the compiler might warn you about incompatibility between size_t and int.
int lenArg1 = 0;
int lenArg2 = 0;
lenArg1 = (int)strlen ( argv[1] );
lenArg2 = (int)strlen ( argv[2] );
Then, printing the lengths len1 and len2 for debugging purposes only:
int len1 = strlen ( cArr1 );
int len2 = strlen ( cArr2 );
cout << "len1 >> " + to_string(len1) <<endl;
cout << "len2 >> " + to_string(len2) <<endl;
In fact, as #Kevin SUN mentioned, it was possible that your argument reading steps were missing the null characters, however, after running some tests it seems to work fine just by initializing the char arrays.
Also, as mentioned in the comments you need to increase the size reserved for res array, I did it to 500
Compiled with g++ -Wall main.cpp -o calc.exe and running: calc 10 100
Without initialization you get problems like:
after initializing, the output works just fine:

compiling in linux using g++

I have following code which is simply tokenizing an array and then deviding on the basis of '<' and '>' characters. It is running fine in VS community 2019 but when I run it in Linux using g++ command it gives
Free(): invalid pointer
and
Aborted (core dumped)
errors. What am I doing wrong.
PS: error seems to be in the instructions where I am deallocating b in rangbrk and langbrk because when I put it in comments it runs fine in Linux too. But it runs fine in VS 2019 anyways.
//#include <sys/types.h>
//#include <sys/wait.h>
//#include <sys/stat.h>
#include <fcntl.h>
//#include <unistd.h>
#include<string.h>
#include<stdio.h>
#include<fstream>
#include<iostream>
#include<stdlib.h>
using namespace std;
//_________________________________________________________
int reads(char str[])
{//a simple function to get input
int s = 1;
char buffer[100];
cout << "enter command" << endl;
cin.getline(buffer, 100);
if (strlen(buffer) == 0)
{
cout << "Couldnt get input\n";
return 0;
}
for (int i = 0; i <= strlen(buffer); i++)
{
str[i] = buffer[i];
if (buffer[i] == 32)
s++;
}
return s;
}
//____________________________________________________________
int tokenizing(char** a, char str[], char buff[50], int x)
{//a function to devide a complete string into smaller parts
//also stores '/bin/command' into buff to pass as first parameter of execvp
int k = 0, m = 0;
bool check = false;
for (int i = 0; i < x; i++)
{
a[i] = new char[50];
for (int j = 0; str[k] != 32; j++)
{
if (str[k] == 0)
{
check = true;
break;
}
a[i][j] = str[k];
if (i == 0)
buff[j + 5] = str[k];
k++;
a[i][j + 1] = 0;
if (i == 0)
buff[j + 6] = 0;
}
m++;
k++;
if (check)
break;
}
return m;
}
//__________________________________________________________
void rangbrk(char**& a, char**& b, int& x, char filename[])
{//saperates the array before and after '>'
for (int i = 0; i < (x - 2); i++)
{
b[i] = new char[50];
for (int j = 0; j < 50; j++)
{
b[i][j] = a[i][j];
}
}
b[x - 2] = NULL;
for (int i = 0; i < 50; i++)
{
filename[i] = a[x - 1][i];
}
char** c;//temprory pointer to swap a and b
c = a;
a = b;
b = c;
x = x - 2;
for(int i=0;i<x-1;i++)
{
delete [] b[i];
}
b=NULL;
}
//__________________________________________________________
void langbrk(char** &a, char** &b, int& x, int index, char filename[])
{//saperates the array before and after '<'
int k = 0;
for (int i = 0; i < x; i++)
{
if ((i != index) && (i != index - 1))
{
b[k] = new char[50];
for (int j = 0; j < 50; j++)
{
b[k][j] = a[i][j];
}
k++;
}
}
b[x - 2] = NULL;
for (int i = 0; i < 50; i++)
{
filename[i] = a[index - 1][i];
}
char** c;//temprory pointer to swap a and b
c = a;
a = b;
b = c;
x = x - 2;
for(int i=0;i<x-1;i++)
{
if(b[i]!=NULL)
delete [] b[i];
}
b=NULL;
}
//__________________________________________________________
int main()
{
char buff[50] = { "/bin/" };
char str[100];
char exit[5] = { 'e','x','i','t',0 };
char outfile[50];
char infile[50];
int x = reads(str);
char** a;
a = new char* [x];
int s = tokenizing(a, str, buff, x);
a[s] = NULL;
bool flag = false;
for (int i = 0; a[i] != NULL; i++)
cout << a[i] << endl;
cout << s << endl;;
for (int i = 0; i < s; i++)
{
if (a[i][0] == '>')//checks if it need to print in a file
{
cout << i;
char** b;
b = new char* [s - 2];
rangbrk(a, b, s, outfile);
flag = true;
cout << "New" << endl;
for (int j = 0; j < s; j++)
cout << a[j] << endl;
i = 0;
}
else if (a[i][0] == '<')
{
cout << i;
char** c;
c = new char * [s - 2];
langbrk(a, c, s, i, infile);
cout << "New" << endl;
for (int j = 0; j < s; j++)
cout << a[j] << endl;
i = 0;
}
}
}
The reads function gets input, tokenizing tokenized the string in form of words. langbrk copies the string having index 1 less than index of '<' in infile and removes them both from main char** a. rangbrk removes '>' and string succeeding it from a and stores it in outfile

C++ - Output always pushes to the most left?

The fiboEncoding() function below is to read an integer then return the Fibonacci encoding.
When I test it in the main function, it always pushes itself into the most left part of the output. How can I solve this problem? What did I do wrong to cause this problem?
#include <iostream>
#include <vector>
using namespace std;
string fiboEncoding(int n) {
string word;
int fib[1000];
fib[0] = 1;
fib[1] = 2;
int i = 0;
for(i = 2; fib[i-1] <= n; i++) {
fib[i] = fib[i-1] + fib[i-2];
}
int r = i - 2;
int index = r;
vector<char> v(r+3);
while(n > 0) {
v[index] = '1';
n = n - fib[index];
index = index - 1;
while (index >= 0 && fib[index] > n) {
v[index] = '0';
index = index - 1;
}
}
v[r + 1] = '1';
for (int j = 0; j < v.size() - 1; j++) {
cout << v[j];
}
return word;
}
int main() {
int n;
string fibo;
cin >> n;
fibo = fiboEncoding(n);
cout << "code: " << fibo << endl;
}
Your function returns an empty string word. You forgot to copy the result into word string.
What you see in the console is the result of executing the following part not cout.
for (int j = 0; j < v.size() - 1; j++) {
cout << v[j];
}
To fix replace the above for loop by
for (int j = 0; j < v.size() - 1; j++) {
//cout << v[j];
word += v[j];
}

Trying to use a bubble sort to sort a string array alphabetically but sort is returning the reverse of the array

I'm currently trying to read from a .txt file into a string array and then use a bubble sort to sort them alphabetically though when I actually run my code it gives the reverse of my array as seen below:
bool swapped = true;
int j = 0;
string tmp;
while (swapped)
{
swapped = false;
j++;
for (int i = 0; i < n - j; i++)
{
if (arr[i].compare(arr[i + 1]));
{
tmp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = tmp;
swapped = true;
}
}
}
for (int i = 0; i < n; i++)
{
cout <<arr[i + 1];
}
This is the code for the bubble sort.
ifstream file("titles.txt");
string myArray[6];
for (int i = 0; i < 6; i++)
{
file >> myArray[i];
//cout << myArray[i];
}
sortStrings(myArray, 6);
and this is the code for the reading of the .txt file.
the file contains the letters b c a d e f in this order
though the output i receive is edabc.
Any help would be appreciated.
I fixed a few problems and this should work:
bool swapped = true;
string tmp;
int j = 0;
while (swapped)
{
swapped = false;
++j;
for (int i = 0; i < n - j; i++)
{
// 1. Your original code has a comma in the following line which terminates the if statement
// 2. compare function returns signed integer indicating the relationship
// between two strings, and > 0 value indicates previous string is greater:
// http://www.cplusplus.com/reference/string/string/compare/
if (arr[i].compare(arr[i + 1]) > 0)
{
tmp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = tmp;
swapped = true;
}
}
}
for (int i = 0; i < n; i++)
{
cout <<arr[i] << endl;
}
Semicolon at the end of an if statement works as if the condition is always true.
The following snippets are identical
if (cond);
{
// ...
}
if (cond) { }
// ...
Take a look std::string's compare method:
Return value
negative value if *this appears before the character sequence specified by the arguments, in lexicographical order
zero if both character sequences compare equivalent
positive value if *this appears after the character sequence specified by the arguments, in lexicographical order
Thus, you should rather check if the value greater than zero in order to sort in ascending order. There is also operator > for std::string, that wouldn't result in the error you encountered.
Summary (formatting applied):
#include <fstream>
#include <iostream>
using namespace std;
void sortStrings(string* arr, int n) {
bool swapped = true;
int j = 0;
string tmp;
while (swapped) {
swapped = false;
j++;
for (int i = 0; i < n - j; i++) {
if (arr[i].compare(arr[i + 1]) > 0) {
tmp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = tmp;
swapped = true;
}
}
}
}
int main() {
ifstream file("titles.txt");
string myArray[6];
for (int i = 0; i < 6; i++) {
file >> myArray[i];
}
sortStrings(myArray, 6);
for (int i = 0; i < 6; i++) {
cout << myArray[i] << ' ';
}
}

Converting "12345678" into "1-234-5678", my code produces nothing

It's not showing any errors but for some reason my cout's wont show up. Am I missing something? I'm trying to convert a series of numbers to a typical phone number format.
int numberCount = 0;
string phoneNumberUnform = "12345678";
for (size_t i = 0; i < phoneNumberUnform.length(); i++)
{
numberCount++;
}
if (numberCount = 8)
{
string phoneNumber[10];
phoneNumber[0] = phoneNumberUnform[0];
phoneNumber[1] = "-";
for (int i = 2; i = 5; i++)
{
phoneNumber[i] = phoneNumberUnform[i-1];
}
phoneNumber[6] = "-";
for (int i = 7; i = 10; i++)
{
phoneNumber[i] = phoneNumberUnform[i-1];
}
cout << phoneNumberUnform;
cout << phoneNumber;
return 0;
}
Use the std::string's insert member function:
#include <iostream>
#include <string>
int main() {
std::string s = "123456789";
s.insert(1, "-");
s.insert(5, "-");
std::cout << s;
return 0;
}
For the manual approach, resize the original string to accommodate the additional two characters:
std::string s = "123456789";
std::string temp = s;
int strlen = temp.length();
s.resize(s.length() + 2);
s[1] = '-';
for (int i = 2; i < 5; i++)
{
s[i] = temp[i - 1];
}
s[5] = '-';
for (int i = 6; i < strlen + 2; i++)
{
s[i] = temp[i - 2];
}
In the second loop use the temp[i - 2] index instead of the temp[i - 1] one because by then we have already inserted the two - characters into our original string.