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

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.

Related

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

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;
}

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

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] << ' ';
}
}

First element of a pointer is polluted C++

I have this piece of code that puts a random string in an char pointer array:
char * str[100] = {0};
const int elems = sizeof(str)/sizeof(str[0]),size=5;
srand(time(0));
for(int i=0;i<elems;i++){
char rString[size] = {0};
for(int j = 0;j<size;j++){
rString[j] = 97+rand()%26;
}
rString[size] = '\0';
str[i] = new char[size];
strcpy(str[i],rString);
}
for(int i=0;i<elems;i++){
cout<<str[i]<<endl;
}
But str[0] is polluted or empty.
Your rString[size] = '\0'; writes to an element out of bounds! The last element is rString[size-1]. Anything after this will be undefined behaviour.
To fix this (but keeping 5-character strings), you need to increase size to 6 and change your loop limits and null-terminator index, as follows:
int main()
{
char* str[100] = { 0 };
const int elems = sizeof(str) / sizeof(str[0]), size = 6; // Add space for nul-terminator
srand(time(0));
for (int i = 0; i < elems; i++) {
char rString[size] = { 0 };
for (int j = 0; j < size-1; j++) { // End BEFORE last character
rString[j] = 97 + rand() % 26;
}
rString[size-1] = '\0'; // Last element is at [size-1] NOT [size]
str[i] = new char[size];
strcpy(str[i], rString);
}
for (int i = 0; i < elems; i++) {
std::cout << str[i] << std::endl;
}
// And, for good measure, don't forget to free the allocated strings:
for (int i = 0; i < elems; i++) {
delete[] str[i];
}
return 0;
}
Alternatively (if you insist on using raw pointers and C-style strings), you can just change your rString declaration and str[i] allocation lines to use size+1 (less typing):
//...
char rString[size+1] = { 0 };
//...
str[i] = new char[size+1];
But you really should consider using more modern C++ techniques, like std::string and std::vector, in place of your dynamic arrays. Here's a version using those STL containers:
int main()
{
std::vector<std::string> str(100);
const int elems = str.size(), size = 5;
srand(time(0));
for (int i = 0; i < elems; i++) {
std::string rString {""};
for (int j = 0; j < size; j++) {
rString += static_cast<char>(97 + rand() % 26);
}
str[i] = rString;
}
for (int i = 0; i < elems; i++) {
std::cout << str[i] << std::endl;
}
return 0;
}
Feel free to ask for further clarification and/or explanation.