Padding specified number of zeros to a char array - c++

I want to pad a given char array to make it a 15 character array.
For eg. if the array contains two characters 1, 2 then 13 0 characters should be padded to make in 000000000000012 and if contains five characters then 10 0s should be padded. The resultant array should contain 15 characters always.
Found one solution here but that’s for stl string I need similar solution for char arrays. Please help.
What I have tried is below:
char moneyArray[256];
memset(moneyArray, 0, 256);
for(int i=0;i<(15-strlen(moneyArray))-1;i++)
sprintf(moneyArray,"0%s",moneyArray);
But I am looking for a standard solution if possible using a std function may be?

You can use the pad function below:
#include <iostream>
#include <cstring>
void pad(char *s, int n, int c) {
char *p = s + n - strlen(s);
strcpy(p, s);
p--;
while (p >= s) { p[0] = c; p--; }
}
int main () {
char b[16] = "123";
pad(b, 15, '0');
std::cout << b << std::endl;
return 0;
}

If you're fine with std::string (and I think you should be), you can make use of its fill constructor:
char s[] = "12";
std::string padded = std::string( (15 - strlen(s) ), '0').append(s);
Of course you might want to check whether strlen(s) > 15 first.

You have various options; one of them would be (again under the assumption we already know that moneyArray contains a string and is a 16-byte buffer at least):
size_t len = strlen(moneyArray);
memmove(moneyArray + 15 - len, moneyArray, len + 1);
memset(moneyArray, '0', 15 - len);

you could just write code to move the chars up
char str[10] = "123456";
padStart(str, 7, '0');
str would become "0123456". be sure the char array is large enough to fit the longer string
void padStart(char *str, int len, char padChar)
{
// find the null terminator
int strLen = 0;
while (str[strLen] != '\0')
{
strLen++;
};
// is there anything to actually do
if (strLen < len)
{
// move the string up to the given length
for (int i = 0; i <= strLen; i++) // notice the '<=' to include the \0 terminator
{
str[len - i] = str[strLen - i];
}
// add padChar to the start
for (int i = 0; i < len - strLen; i++)
{
str[i] = padChar;
}
}
}

Related

How to replace a char in string with another char fast(I think test didn't want common way)

I was asked this question in tech test.
They asked how to change ' ' to '_' in string.
I think they didn't want common answer. like this (I can assure this)
void replaceChar(char originalStr[], size_t strLength, char originalChar, char newChar
{
for(size_t i = 0 ; i < strLength ; i++)
{
if(originalStr[i] == originalChar)
{
originalStr[i] = newChar ;
}
}
}
So I answered like this. Use WORD. ( Actually I didn't write code, They want just explaining how to do)
I think comparing Each 8 byte(64bit OS) of string with mask 8 byte.
if They eqaul, replace 8byte in a time.
When Cpu read data with size less than WORD , Cpu should do operation clearing rest bits.
It's slow. So I tried to use WORD in comparing chars.
void replaceChar(char originalStr[], size_t strLength, char originalChar, char newChar //
{
size_t mask = 0;
size_t replaced = 0;
for(size_t i = 0 ; i < sizeof(size_t) ; i++)
{
mask |= originalChar << i;
replaced |= newChar << i;
}
for(size_t i = 0 ; i < strLength ; i++)
{
// if 8 byte data equal with 8 byte data filled with originalChar
// replace 8 byte data with 8 byte data filled with newChar
if(i % sizeof(size_t) == 0 &&
strLength - i > sizeof(size_t) &&
*(size_t*)(originalStr + i) == mask)
{
*(size_t*)(originalStr + i) = replaced;
i += sizeof(size_t);
continue;
}
if(originalStr[i] == originalChar)
{
originalStr[i] = newChar ;
}
}
}
Is There any faster way??
Do not try to optimize a code when you do not know what is the bottleneck of the code. Try to write a clear readable code.
This function declaration and definition
void replaceChar(char originalStr[], size_t strLength, char originalChar, char newChar
{
for(size_t i = 0 ; i < strLength ; i++)
{
if(originalStr[i] == originalChar)
{
originalStr[i] = newChar ;
}
}
}
does not make a sense because it duplicates the behavior of the standard algorithm std::replace.
Moreover for such a simple basic general-purpose function you are using too long identifier names.
If you need to write a similar function specially for C-strings then it can look for example the following way as it is shown in the demonstrative program below
#include <iostream>
#include <cstring>
char * replaceChar( char s[], char from, char to )
{
for ( char *p = s; ( p = strchr( p, from ) ) != nullptr; ++p )
{
*p = to;
}
return s;
}
int main()
{
char s[] = "Hello C strings!";
std::cout << replaceChar( s, ' ', '_' ) << '\n';
return 0;
}
The program output is
Hello_C_strings!
As for your second function then it is unreadable. Using the continue statement in a body of for loop makes it difficult to follow its logic.
As a character array is not necessary aligned by the value of size_t then the function is not as fast as you think.
If you need a very optimized function then you should write it directly in assembler.
The first thing in the road to being fast is being correct. The problem with the original proposal is that sizeof(s) should be a cached value of strlen(s). Then the obvious problem is that this approach scans the string twice -- first to find the terminating character and then the character to be replaced.
This should be addressed by a data structure with known length, or data structure, with enough guaranteed excess data so that multiple bytes can be processed at once without Undefined Behaviour.
Once this is solved (the OP has been edited to fix this) the problem with the proposed approach of scanning 8 bytes worth of data for ALL the bytes being the same is that a generic case does have 8 successive characters, but maybe only 7. In all those cases one would need to scan the same area twice (on top of scanning the string terminating character).
If the string length is not known, the best thing is to use a low level method:
while (*ptr != 0) {
if (*ptr == search_char) {
*ptr = replace_char;
}
++ptr;
}
If the string length is known, it's best to use a library method std::replace, or it's low level counterpart
for (auto i = 0; i < size; ++i) {
if (str[i] == search_char) {
str[i] = replace_char;
}
}
Any decent compiler is able to autovectorize this, although the compiler might generate a larger variety of kernels than intended (one kernel for small sizes, one for intermediate and one to process in chunks of 32 or 64 bytes).

Trying to reverse a string in C++, but gibberish appears at the of the reversed string?

Here is my function to reverse a string:
void reverse(char *str){
int lengthStr = strlen(str);
int j, i;
char reversedString[100];
for (j = 0, i = lengthStr-1; i >= 0; i--, j++){
reversedString[j] = str[i];
}
cout << reversedString;
}
The string does appear as reversed, but at the end there's a bunch of weird characters that appears. What could be causing this issue?
If you want to reverse the string there are many cleaner approaches already available like: std::reverse_copy etc.
But if you want to fix this function then try this:
char reversedString[100];
memset(reversedString, 0, 100*sizeof(char);
OR
for (j = 0, i = lengthStr-1; i >= 0; i--, j++){
reversedString[j] = str[i];
}
reversedString[j] = '\0'; //! Add null character at the end to indicate end of the string
cout << reversedString;
Note: Your program fails if input string has length >= 100.
Add a zero to the characters you assigned to reversedString. Otherwise, the unitialized extra portion of the new string will show up as garbage. A zero is used to mark the end of the string.
First of all the function is invalid and has no sense. You do not reverse the original string and the local string that is defined in the function can be less than the original string. Also you do not append the reversed local string with the terminating zero. The function can look like
void reverse( char *str )
{
size_t n = std::strlen( str );
for ( size_t i = 0; i < n / 2; i++ )
{
char c = str[i];
str[i] = str[n - i - 1];
str[n - i - 1] = c;
}
}
The original reversed string can be displayed in the code that calls the function.

Packed value in C++ or C

struct FILE_UPC_RECORD
{
char UPC[FILE_UPC_KEY_SIZE];// packed up to 16 digits right justified and zero filled
// possibilities are:
// 1. 12-digit UPC w/2 leading 0's
// 2. 13-digit EAN w/1 leading 0
// 3. 14-digit EAN
char SKU[FILE_ITEM_KEY_SIZE]; // packed, 0000ssssssssssss
};
Where FILE_UPC_KEY_SIZE & FILE_ITEM_KEY_SIZE = 8. Is packed value equivalent to Hex value? How do i store '0123456789012' equivaent decimal calue in the UPC & SKU array? Thanks for all your help.
You asked "How do i ...", here's some example code with comments
#include <stdio.h>
#include <stdint.h>
int main(int argc, const char * argv[])
{
int i, newSize;
// Treat the result packed data as unsigned char (i.e., not a string so not
// NULL terminated)
uint8_t upc[8];
uint8_t *destPtr;
// Assume input is a char string (which will be NULL terminated)
char newUPC[] = "0123456789012";
char *srcPtr;
// -1 to remove the string null terminator
// /2 to pack 2 decimal values into each byte
newSize = (sizeof(newUPC) - 1) / 2;
// Work from the back to the front
// -1 because we count from 0
// -1 to skip the string null terminator from the input string
destPtr = upc + (sizeof(upc) - 1);
srcPtr = newUPC + (sizeof(newUPC) - 1 - 1);
// Now pack two decimal values into each byte.
// Pointers are decremented on individual lines for clarity but could
// be combined with the lines above.
for (i = 0; i < newSize; i++)
{
*destPtr = *srcPtr - '0';
srcPtr--;
*destPtr += (*srcPtr - '0') << 4;
srcPtr--;
destPtr--;
}
// If input was an odd lenght handle last value
if ( (newSize * 2) < (sizeof(newUPC) - 1) )
{
*destPtr = *srcPtr - '0';
destPtr--;
i++;
}
// Fill in leading zeros
while (i < sizeof(upc))
{
*destPtr = 0x00;
destPtr--;
i++;
}
// Print the hex output for validation.
for (i = 0; i < sizeof(upc); i++)
{
printf("0x%02x ", upc[i]);
}
printf("\n");
return 0;
}

pointer cannot maintain in c++ function

void concat(char *str, char *ch, int num)
{
*str= *ch; ++str;
while (num>0) {
*str = '0' + num % 10;
num /= 10;
++str;
}
}
concat(runner, 'a', 10);
concat(runner, 'b', 20);
i just want to concat one character like 'a' to 10, the expected result will be a10
the first line works fine. but i just thinking after the first line(concat a10), the runner should point to the end of string, so when i run the second line, it should be a10b20, but actual result is b20 overwrite the a10.
i think it should be pointer problem , can you help me.
I'm changing my answer altogether. Put this in the beginning of your function:
void concat(char * str, const char * ch, int num) {
while (*str) {
++str;
}
Then keep the rest the same. This is really what concat should look like. Just make sure that runner[0] == 0 before calling it the first time! And add the following code to the end of your function, before the final brace:
*str = 0;
}
using & should be ok
or actually in c, you can use **, two ways.
Well, the code does what you ask of it.
For this to work you need to find the end of the first string and then add to it:
void concat(char *str, char *ch, int num)
{
str += strlen(str); /* make sure we start adding at the end of str */
*str= *ch; ++str;
while (num>0) {
*str = '0' + num % 10;
num /= 10;
++str;
}
}
But now you must make sure str[0] is 0 at the beginning
Because every time concat is called, the index of str starts from 0. That's why the content of str is overwritten. Just skip all the filled positions in str before you append any to it.
The problem is that your function is not aware of the end of the string being passed in. To fix this you will need to intialize your char * to all 0's or \0. The other issue is you are converting your number to characters incorrectly. And finally there is nothing safe about the function since the size of the string is not passed in so you just have to make sure you allocate enough space before hand.
void concat(char *str, const char *ch, int num)
{
//This is function not safe since you do not
//know how much space str has allocated
str += strlen(str);
*str = *ch; ++str;
if(num < 0)
{
*str = '-';//Add the -
++str;
num *= -1; //Make the number positive
}
//Determine the number of digits first
//because you need to add characters backwards
int digits = 0, tmpnum = num;
while (tmpnum) {
tmpnum /= 10;
++digits;
}
while(digits--)
{
str[digits] = '0' + num % 10;
num /= 10;
}
}
Usage:
char *runner = new char[20]();
//or
//char *runner = (char*)calloc(20, 1);
concat(runner, "a", 10);
concat(runner, "b", 20);
concat(runner, "c", -30);
delete [] runner;
//or if you used calloc
//free(runner);
I did this assuming this was a homework assignment, there are easier/safer ways to accomplish this especially using C++ which is what your question was tagged.

How many palindromes can be formed by selections of characters from a string?

I'm posting this on behalf of a friend since I believe this is pretty interesting:
Take the string "abb". By leaving out
any number of letters less than the
length of the string we end up with 7
strings.
a b b ab ab bb abb
Out of these 4 are palindromes.
Similarly for the string
"hihellolookhavealookatthispalindromexxqwertyuiopasdfghjklzxcvbnmmnbvcxzlkjhgfdsapoiuytrewqxxsoundsfamiliardoesit"
(a length 112 string) 2^112 - 1
strings can be formed.
Out of these how many are
palindromes??
Below there is his implementation (in C++, C is fine too though). It's pretty slow with very long words; he wants to know what's the fastest algorithm possible for this (and I'm curious too :D).
#include <iostream>
#include <cstring>
using namespace std;
void find_palindrome(const char* str, const char* max, long& count)
{
for(const char* begin = str; begin < max; begin++) {
count++;
const char* end = strchr(begin + 1, *begin);
while(end != NULL) {
count++;
find_palindrome(begin + 1, end, count);
end = strchr(end + 1, *begin);
}
}
}
int main(int argc, char *argv[])
{
const char* s = "hihellolookhavealookatthis";
long count = 0;
find_palindrome(s, strlen(s) + s, count);
cout << count << endl;
}
First of all, your friend's solution seems to have a bug since strchr can search past max. Even if you fix this, the solution is exponential in time.
For a faster solution, you can use dynamic programming to solve this in O(n^3) time. This will require O(n^2) additional memory. Note that for long strings, even 64-bit ints as I have used here will not be enough to hold the solution.
#define MAX_SIZE 1000
long long numFound[MAX_SIZE][MAX_SIZE]; //intermediate results, indexed by [startPosition][endPosition]
long long countPalindromes(const char *str) {
int len = strlen(str);
for (int startPos=0; startPos<=len; startPos++)
for (int endPos=0; endPos<=len; endPos++)
numFound[startPos][endPos] = 0;
for (int spanSize=1; spanSize<=len; spanSize++) {
for (int startPos=0; startPos<=len-spanSize; startPos++) {
int endPos = startPos + spanSize;
long long count = numFound[startPos+1][endPos]; //if str[startPos] is not in the palindrome, this will be the count
char ch = str[startPos];
//if str[startPos] is in the palindrome, choose a matching character for the palindrome end
for (int searchPos=startPos; searchPos<endPos; searchPos++) {
if (str[searchPos] == ch)
count += 1 + numFound[startPos+1][searchPos];
}
numFound[startPos][endPos] = count;
}
}
return numFound[0][len];
}
Explanation:
The array numFound[startPos][endPos] will hold the number of palindromes contained in the substring with indexes startPos to endPos.
We go over all pairs of indexes (startPos, endPos), starting from short spans and moving to longer ones. For each such pair, there are two options:
The character at str[startPos] is not in the palindrome. In that case, there are numFound[startPos+1][endPos] possible palindromes - a number that we have calculated already.
character at str[startPos] is in the palindrome (at its beginning). We scan through the string to find a matching character to put at the end of the palindrome. For each such character, we use the already-calculated results in numFound to find number of possibilities for the inner palindrome.
EDIT:
Clarification: when I say "number of palindromes contained in a string", this includes non-contiguous substrings. For example, the palindrome "aba" is contained in "abca".
It's possible to reduce memory usage to O(n) by taking advantage of the fact that calculation of numFound[startPos][x] only requires knowledge of numFound[startPos+1][y] for all y. I won't do this here since it complicates the code a bit.
Pregenerating lists of indices containing each letter can make the inner loop faster, but it will still be O(n^3) overall.
I have a way can do it in O(N^2) time and O(1) space, however I think there must be other better ways.
the basic idea was the long palindrome must contain small palindromes, so we only search for the minimal match, which means two kinds of situation: "aa", "aba". If we found either , then expand to see if it's a part of a long palindrome.
int count_palindromic_slices(const string &S) {
int count = 0;
for (int position=0; position<S.length(); position++) {
int offset = 0;
// Check the "aa" situation
while((position-offset>=0) && (position+offset+1)<S.length() && (S.at(position-offset))==(S.at(position+offset+1))) {
count ++;
offset ++;
}
offset = 1; // reset it for the odd length checking
// Check the string for "aba" situation
while((position-offset>=0) && position+offset<S.length() && (S.at(position-offset))==(S.at(position+offset))) {
count ++;
offset ++;
}
}
return count;
}
June 14th, 2012
After some investigation, I believe this is the best way to do it.
faster than the accepted answer.
Is there any mileage in making an initial traversal and building an index of all occurances of each character.
h = { 0, 2, 27}
i = { 1, 30 }
etc.
Now working from the left, h, only possible palidromes are at 3 and 17, does char[0 + 1] == char [3 -1] etc. got a palindrome. does char [0+1] == char [27 -1] no, No further analysis of char[0] needed.
Move on to char[1], only need to example char[30 -1] and inwards.
Then can probably get smart, when you've identified a palindrome running from position x->y, all inner subsets are known palindromes, hence we've dealt with some items, can eliminate those cases from later examination.
My solution using O(n) memory and O(n^2) time, where n is the string length:
palindrome.c:
#include <stdio.h>
#include <string.h>
typedef unsigned long long ull;
ull countPalindromesHelper (const char* str, const size_t len, const size_t begin, const size_t end, const ull count) {
if (begin <= 0 || end >= len) {
return count;
}
const char pred = str [begin - 1];
const char succ = str [end];
if (pred == succ) {
const ull newCount = count == 0 ? 1 : count * 2;
return countPalindromesHelper (str, len, begin - 1, end + 1, newCount);
}
return count;
}
ull countPalindromes (const char* str) {
ull count = 0;
size_t len = strlen (str);
size_t i;
for (i = 0; i < len; ++i) {
count += countPalindromesHelper (str, len, i, i, 0); // even length palindromes
count += countPalindromesHelper (str, len, i, i + 1, 1); // odd length palindromes
}
return count;
}
int main (int argc, char* argv[]) {
if (argc < 2) {
return 0;
}
const char* str = argv [1];
ull count = countPalindromes (str);
printf ("%llu\n", count);
return 0;
}
Usage:
$ gcc palindrome.c -o palindrome
$ ./palindrome myteststring
EDIT: I misread the problem as the contiguous substring version of the problem. Now given that one wants to find the palindrome count for the non-contiguous version, I strongly suspect that one could just use a math equation to solve it given the number of distinct characters and their respective character counts.
Hmmmmm, I think I would count up like this:
Each character is a palindrome on it's own (minus repeated characters).
Each pair of the same character.
Each pair of the same character, with all palindromes sandwiched in the middle that can be made from the string between repeats.
Apply recursively.
Which seems to be what you're doing, although I'm not sure you don't double-count the edge cases with repeated characters.
So, basically, I can't think of a better way.
EDIT:
Thinking some more,
It can be improved with caching, because you sometimes count the palindromes in the same sub-string more than once. So, I suppose this demonstrates that there is definitely a better way.
Here is a program for finding all the possible palindromes in a string written in both Java and C++.
int main()
{
string palindrome;
cout << "Enter a String to check if it is a Palindrome";
cin >> palindrome;
int length = palindrome.length();
cout << "the length of the string is " << length << endl;
int end = length - 1;
int start = 0;
int check=1;
while (end >= start) {
if (palindrome[start] != palindrome[end]) {
cout << "The string is not a palindrome";
check=0;
break;
}
else
{
start++;
end--;
}
}
if(check)
cout << "The string is a Palindrome" << endl;
}
public String[] findPalindromes(String source) {
Set<String> palindromes = new HashSet<String>();
int count = 0;
for(int i=0; i<source.length()-1; i++) {
for(int j= i+1; j<source.length(); j++) {
String palindromeCandidate = new String(source.substring(i, j+1));
if(isPalindrome(palindromeCandidate)) {
palindromes.add(palindromeCandidate);
}
}
}
return palindromes.toArray(new String[palindromes.size()]);
}
private boolean isPalindrome(String source) {
int i =0;
int k = source.length()-1;
for(i=0; i<source.length()/2; i++) {
if(source.charAt(i) != source.charAt(k)) {
return false;
}
k--;
}
return true;
}
I am not sure but you might try whit fourier. This problem remined me on this: O(nlogn) Algorithm - Find three evenly spaced ones within binary string
Just my 2cents