Truncating an array of char via function C++ - c++

trying to format this function as it will truncate an array of char (anything that the user enters it will split that up to a number the user also enters)
void truncate(char array[], int maxLength)
{
// Variable definition
int x = 0;
// While loop start.
while (array[x] <= maxLength)
{
cout << array[x];
x++;
}
}
The array parameter in the function header is just a string that was entered by the user, its an array of char. And the maxLength parameter is an int variable entered by the user as well, it could be 3, 4 or 5. The maxLength is supposed to act as the null termination whatever the user enters the string will truncate after that number.
But this code doesn't work, it doesn't display an output for the function. Anyone know what I'm doing wrong? Thanks.

The problem here is this:
while (array[x] <= maxLength)
This is comparing the character returned from the array at x to the value of maxLength, so you're comparing a char to an int. I would recommend the more standard for loop for this:
for (int x = 0; x < maxLength; x++) {
cout << array[x];
}

int truncate(const char *str, int maxchunk, char ***chunks)
{
int len = strlen(str);
int nchunks = len / maxchunk + !!(len % maxchunk);
char **table = malloc(sizeof(char *) * (nchunks));
if (table != NULL)
{
for (int i = 0; i < nchunks; i++)
{
if ((table[i] = malloc(sizeof(char) * maxchunk + 1)) == NULL)
{
for (int j = i - 1; j >= 0; j--)
{
free(table[j]);
}
free(table);
table = NULL;
break;
}
strncpy(table[i], str + i * maxchunk, maxchunk);
*(table[i] + maxchunk) = '\0';
}
}
*chunks = table;
return table == NULL ? -1 : nchunks;
}

Related

what is the issue with this char reverse function?

so I wrote this code to reverse one of the names based on the user option the idea is to use another function to reverse and to use pointers but after trying all I could think of my code return the same name not changed the best I could do was changing the first letter of the name to a weird sign.
#include <iostream>
using namespace std;
void reverse(char* A) {
int count = 0;
char temp[10];
for (int i = 0; A[i] != NULL; i++)
count++;
for (int i = 0; A[i] != NULL; i++) {
temp[count]=A[i];
count--;
}
for (int i = 0; A[i] != NULL; i++) {
A[i] = temp[i];
}
}
int main(){
int x= 0;
int index;
char Name_list[5][10];
cout << "please enter the names of the student " << endl;
for (int i = 0; i < 5; i++) {
cin >> Name_list[i];
for (int j = 0; Name_list[i][j] != NULL; j++) {
x++;
}
while (x > 10)
{
x = 0;
cout << "you have entered more then the allowed number of characters per name enter another name " << endl;
cin >> Name_list[i];
for (int j = 0; Name_list[i][j] != NULL; j++) {
x++;
}
}
x = 0;
}
for (int i = 0; i < 5; i++) {
cout << Name_list[i] << endl;
}
cout << "please enter the index of the name you want to reverse" << endl;
cin >> index;
while (index>4||index <0)
{
cout << "you entered incorrect index please enter a number from 0 to 4 " << endl;
}
reverse(Name_list[index]);
for (int i = 0; i < 5; i++) {
cout << Name_list[i] << endl;
}
system("pause");
}
For starters such a function should return a pointer to the result string. That is it should be declared like
char * reverse( char *s );
Note: do not use variable names consisting from upper case letters.
The type int can be not large enough to store length of a string. Instead use the type size_t.
char * reverse( char *s )
{
size_t count = 0;
//...
It is totally unclear why there is present an array with the number of elements equal to the magic number 10
char temp[10];
To reverse a string there is no need to declare an auxiliary array. Such an approach is principally wrong.
In this for loop
for (int i = 0; A[i] != NULL; i++)
there is compared an object of the type char with the pointer NULL. The compiler should issue a message for such a wrong comparison. It seems you mean
for (int i = 0; A[i] != '\0'; i++)
In any case the introduced variable i in this first for loop is redundant because you already has the variable count.
As you have the array temp with the fixed size equal to 10 then the both loops after the first loop can invoke undefined behavior even if the length of the source string is equal exactly to 10.
And the result string is not zero terminated.
The function can look the following way.
char * reverse( char *s )
{
size_t count = 0;
while ( s[count] ) ++count;
for ( size_t i = 0; i < count / 2; i++ )
{
char c = s[i];
s[i] = s[count - i - 1];
s[count - i - 1] = c;
}
return s;
}
Or using standard functions you could write the function reverse the following way
#include <utility>
#include <cstring>
//...
char * reverse( char *s )
{
for ( size_t i = 0, n = std::strlen( s ); i < n / 2; i++ )
{
std::swap( s[i], s[n-i-1] );
}
return s;
}
Pay attention to that there is the standard algorithm std::reverse. Using it you could reverse a string the following way
std::reverse( s, s + std::strlen( s ) );
for (int i = 0; A[i] != NULL; i++) {
temp[count]=A[i];
count--;
}
If i goes up from 0 to 5, count goes down from 6 to 1.
Ok, a few things.
If you want do some string manipulation, look into the stdlib. Unless you are doing this for class.
Your writing everything to the end of the temp. buffer
You need to add an extra character at the end of the strings for the null byte (I think this implementation may allow for a seg. fault)

Printing an integer value from an ASCII character

I am trying to implement the function stoi() in c++. I have made an int array arr to store the integer ASCII of all elements of char_arr. This works fine if I print the values from my char_arr array because its a character array. But, how do I transfer my integer values from the char array to an int array and print only the numbers and not their ASCII?
Code:
int stoi(){
int *arr = new int [strlen(char_arr)];
for (int i=0; char_arr[i]!='\0'; ++i){
arr[i] = char_arr[i];
}
for (int i=0; char_arr[i] != '\0'; ++i){
if (arr[i] >= 48 && arr[i] <= 57){
cout << char_arr[i];
}
}
}
First of all, remove the first loop and use char_arr directly. You don't need to hold ints to make it work.
As for printing int values, you can use this:
for (int i = 0; char_arr[i] != '\0'; ++i) {
if (char_arr[i] >= '0' && char_arr[i] <= '9') { //I would suggest you to use this syntax instead of raw ASCII codes.
cout << (char_arr[i] - '0');
}
}
int stoi(){
/* if you do not use arr.
int *arr = new int[strlen(char_arr)];
for (int i = 0; char_arr[i] != '\0'; ++i){
arr[i] = char_arr[i];
}
*/
int sign = 1, value = 0;
if (*char_arr == '+') {
++char_arr;
}
else if (*char_arr == '-') {
++char_arr;
sign = -1;
}
while (*char_arr) {
if (*char_arr >= '0' && *char_arr <= '9') {
value = value * 10 + *char_arr - '0';
++char_arr;
} else {
break;
}
}
return sign * value;
}
Here's the one I came up with:
#include <cstdio>
#include <cstring>
#define _BASE_ 10
int main(int argc, char **argv)
{
char ascii[] = "474927";
signed int value = 0;
signed int ascii_len = strlen(ascii);
int pos = 0;
for(signed int i = ascii_len-1; i >= 0; i--)
{
if(i == 0 && ascii[i] == '-')
{
value *= -1;
continue;
}
int base = 1;
if(pos > 0)
{
base = _BASE_;
for(int j = 1; j < pos; j++)
base *= _BASE_;
}
value += base * (ascii[i] - 48);
pos++;
}
printf("Value: %d\n", value);
return 0;
}

Trouble with finding a c-string substring in C++

long time lurker, first time poster. I have been working on this problem for the last six hours hours.
Problem:
Implement the following functions. Each function deals with null terminated C-Style strings. You can assume that any char array passed into the functions will contain null terminated data. Place all of the functions in a single file and then create a main() function that tests the functions thoroughly.
Note: You may not use any c-string functions other than strlen().
I am having trouble with the fourth function.
The desired behavior is: This function returns the index in string s where the substring can first be found. For example if s is "Skyscraper" and substring is "ysc" the function would return 2. It should return -1 if the substring does not appear in the string.
prototype:
int findSubstring(char *str, char substring[])
Here's my two starts for function definitions, I'm not really sure if either is going in the right direction, I'm having a lot of trouble keeping the loop iterations in my head, any help would be TREMENDOUSLY appreciated.
int findSubstring(char *str, char substring[]){
int subS = -1, index1 = 0, index2 = 0;
int length1 = (strlen(str) - 1);
int length2 = (strlen(substring) - 1);
if(length1 > length2){
for(int i = 0; i <= length2; i++){
for(int j = 0; j <= length1; j++){
if(*(substring + i) == *(str + j) && *(substring +i) != '\0' ){
i++;
if(index1 == 0){
index1 = i;
}
}
if( *(substring + i) == '\0'){
subS = i + 2;
}
}
}
}
if (length1 < length2){
cout << "Invalid, substring exceeds size of string!" << endl;
}
return subS;
}
int findSubstring(char *str, char substring[]){
int index = -1;
int lengthStr = (strlen(str) - 1);
int lengthSub = (strlen(substring) - 1);
if (lengthStr < lengthSub){
cout << "Invalid input, substring exceeds size of string!" << endl;
}
if( lengthSub == 0){
cout << "";
}
if (lengthStr > lengthSub){
for(int i = 0; i <= lengthSub; i++){
for(int j = 0; j <= lengthStr; j++){
}
return index;
}
//You can replace my str.size() and subString.size() by the size of each c-string.
int stringPointerOperation( string str, string subString )
{
int pos=0;
bool notFound;
for(int i = 0; i < str.size() ; i++)
{
notFound= false;
if(str[i] == subString[0])
{
pos=i;
for(int k = 0 ; k < subString.size() && k < str.size() ; k++,i++)
{
if(subString[k] != str[i] )
{
notFound=true;
break;
}
}
}
}
if(notFound)
return -1;
else
return pos;
}
You are using the wrong strategy for finding a sub-string in a string. The outer for loop needs to iterate over the main string and the inner for loop needs to iterate over the sub-string.
Say you are looking for "de" in "abcdef". The strategy that I find easier to understand and implement is:
Can I find "de" starting from 0 of "abcdef". No, I can't.
Can I find "de" starting from 1 of "abcdef". No, I can't.
Can I find "de" starting from 2 of "abcdef". No, I can't.
Can I find "de" starting from 3 of "abcdef". Yes, I can. Return 3.
Here's a version that works for me.
int findSubstring(char *str, char substring[]){
int i;
int j;
int length1 = strlen(str);
int length2 = strlen(substring);
if(length1 < length2){
std::cout << "Invalid, substring exceeds size of string!" << std::endl;
return -1;
}
for(i = 0; i < length1; i++){
for(j = 0; j < length2; j++){
// The index to use access the element of str
// needs to be offset by i.
if( str[i+j] != substring[j] )
{
break;
}
}
if ( j == length2 )
{
return i;
}
}
return -1;
}

Recursive function to generate string does not contain two adjacent identical substring c++

I have a task that is difficult for me to handle. The task is: Create recursive function that can be generate a string of length N (N <= 100), formed by the letters 'A', 'B' and 'C' and does not containing two identical adjacent substring. For example: enter for N = 6 and the program should generate such a string in which no one else to repeated substrings: ABACAB. Wrong strings are: AABACA - because 'A' is to 'A'; ABCBCA - as 'BC' is to 'BC' and ABCABC is also wrong because 'ABC' is to 'ABC'.
I made a version of the program but an iterative way, here is the code:
#include <iostream>
#include <ctime>
using namespace std;
const char letters[] = "ABC";
char generate_rand()
{
return letters[rand() % 3];
}
int check(char *s, int pos)
{
for (int i = 1; i <= (pos + 1)/2; i++)
{
int flag = 1;
for (int j = 0; j < i; j++)
if (s[pos-j] != s[pos-i-j])
{
flag = 0;
break;
}
if (flag)
return 1;
}
return 0;
}
int main()
{
char s[100];
int n;
cout << "enter n: ";
cin >> n;
srand(time(NULL));
for (int i = 0; i < n; i++)
{
do
{
s[i] = generate_rand();
} while (check(s, i));
cout << s[i] << " ";
}
cout << " ok" << endl;
system("pause");
return 0;
}
I think the entrance of the recursive function may need to be the number of characters in the string, which will seek to repeat with an adjacent string and each time increased by 1, but not more than half the length of the original string, but do not know how to do it.
So lets start with a simple recursive function which prints 10 letters but doesn't check anything:
void addLetter(char* buf, int max_length)
{
int len = strlen(buf);
buf[len] = generate_rand();
if (strlen(buf) < max_length)
addLetter(buf);
}
int main()
{
srand(time(NULL)); //I forgot srand!
int max_length = 10; //ask user to input max_length, like you had earlier
char buf[100];
memset(buf,0,sizeof(buf));
addLetter(buf, max_length);
printf("\n%s\n", buf);
return 0;
}
Now lets change the recursive function, get it to check just 1 letter:
void addLetter(char* buf, int max_length)
{
int len = strlen(buf);
buf[len] = generate_rand();
if (len > 0)
{
if (buf[len] == buf[len-1])
buf[len] = 0;
}
if (strlen(buf) < max_length)
addLetter(buf);
}
Next step, check 2 letters with previous ones etc. You should be able to take it from here.

C++ Binary to Decimal and Back Converter

I've almost solved this exercise:
Binary to Decimal and Back Converter - "Develop a converter to convert a decimal number to binary or a binary number to its decimal equivalent."
So, the binary to decimal converter works perfectly, but the other one doesn't. convertToBinary() function returns crap and I don't know why. Here is the code:
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
char* convertToBinary(int dec);
int convertToDec(const char* bin);
int main()
{
std::cout << convertToBinary(100) << std::endl; // wtf!
return 0;
}
char* convertToBinary(int dec)
{
char binary[15] = "";
int result;
for(int i = 0; dec >= 1; dec /= 2, ++i)
{
result = !((dec % 2) == 0);
binary[i] = result + 48;
}
for(int i = strlen(binary); strlen(binary) % 4 != 0; ++i) // add some zeros to make it look cool
binary[i] = '0';
for(int i = 0, j = strlen(binary)-1; i < j; ++i, --j) // reverse the array
{
char temp = binary[i];
binary[i] = binary[j];
binary[j] = temp;
}
std::cout << binary << std::endl; // looking good!
return binary;
}
int convertToDec(const char* bin)
{
int dec = 0;
int size = strlen(bin);
for(int i = 0; *bin; ++i, ++bin)
{
int ch = *bin - 48;
dec += ch * pow(2, size - i - 1);
}
return dec;
}
Using c language
char *convertToBinary(int value)
{
char *binary;
size_t length;
size_t i;
length = 8 * sizeof(value);
binary = malloc(1 + length);
if (binary == NULL)
return NULL;
for (i = 0 ; i < length ; ++i)
binary[length - i - 1] = (value & (1 << i)) ? '1' : '0';
binary[length] = '\0';
return binary;
}
int binaryToDecimal(const char *binary)
{
int value;
size_t length;
size_t i;
value = 0;
length = strlen(binary);
for (i = 0 ; i < length ; i++)
value |= (binary[i] == '1') ? (1 << (length - i - 1)) : 0;
return value;
}
Using c++ language
std::string convertToBinary(int value)
{
std::string binary;
size_t length;
length = 8 * sizeof(value);
binary.resize(length);
for (size_t i = 0 ; i < length ; ++i)
binary[length - i - 1] = (value & (1 << i)) ? '1' : '0';
return binary;
}
int binaryToDecimal(const std::string &binary)
{
int value;
size_t length;
value = 0;
length = binary.length();
for (size_t i = 0 ; i < length ; i++)
value |= (binary[i] == '1') ? (1 << (length - i - 1)) : 0;
return value;
}
to convert from binary to decimal, you can use strtol of course.
Your mistake is returning a local variable, a local variable is automatically deallocated when the function returns, and hence the garbage you got.
When you do something like this:
char *toString(...)
{
char res[MAX_RES];
// fill res
return res;
}
you create the array res as a local array on the stack. This array goes out of scope when you return from the function; a pointer to this array is no longer valid and most likely will point to garbage.
If you want to use C-style char buffers, there are two ways to get around this:
Allocate the result on the heap.
char *toString(...)
{
char *res = malloc(MAX_RES);
// fill res
return res;
}
Data allocated on the heap with malloc will be valid until explicitly released with free. The advantage of this approach is that you can make the string as long as you wish. Thedrawback is that the allocation might fail. It is also worth noting that the caller now owns the string and is responsible for freeing it:
char *x = toString(...);
// do stuff with x
free(x);
**Pass the buffer and maximum length **
int toString(char *res, size_t max, ...)
{
// fill res
}
That is the approach many library functions use, notably snprintf. The caller has to provide their own buffer and information on the maximum allowable length in order to avoid buffer overflows. This approach must keep track of the buffer size and truncate the result if necessary, possibly maintaining the string null-terminated. Such functions could be void, but it is customary to return the actual string length or -1 as error indicator.
It is called like this:
char x[200];
toString(x, sizeof(x), ...);
// do stuff with x