During string reversal extra character is added for array size less than 5 in c using jni - java-native-interface

I'm writing a basic string reversal program in c by getting the input from java through jni. I'm initialising the output array dynamically by getting the output of the input string. But the output always has an extra letter if the length of the string is less than 5. For example the output for "hello" is "ollehp". So how can I fix this?
This is my code.
JNIEXPORT jstring JNICALL Java_JavaTest_reversal(JNIEnv * env, jobject obj, jstring input)
{
const char *str = (*env)->GetStringUTFChars(env, input, 0);
const int length = (int)strlen(str);
int l = length;
char output[l];
int j = length-1;
for(int i = 0 ; i < length ; i++)
{
output[j] = str[i];
j--;
}
(*env)->ReleaseStringUTFChars(env, input, str);
printf("output %s \n",output);
return (*env)->NewStringUTF(env, output);
}

Related

strcat Function in c++

I'm new to C and C++ programming, can anyone give me a hint on what I'm doing wrong here. I'm trying to write to concat function that takes to pointers to chars and concatenates the second to the first. The code does do that, but the problem is that it adds a bunch of junk at the end. For instance, when passing the arguments - "green" and "blue", the output will be "greenblue" plus a bunch of random characters. I also wrote the strlen function that strcat uses, which I will provide below it for reference. I'm using the online compiler at https://www.onlinegdb.com/online_c++_compiler
The exact instructions and specification is this:
The strcat(char *__s1, const char *__s2) functions concatenates the contents of __s2 onto __s1 beginning with the NULL character of __s1. Note: The concatenation includes the NULL character of __s2. The function returns __s1.
int main(int argc, char** argv)
{
const int MAX = 100;
char s1[MAX];
char s2[MAX];
cout << "Enter your first string up to 99 characters. ";
cin.getline(s1, sizeof(s1));
int size_s1 = strlen(s1);
cout << "Length of first string is " << size_s1 << "\n";
cout << "Enter your second string up to 99 characters. ";
cin.getline(s2, sizeof(s2));
int size_s2 = strlen(s2);
cout << "Length of second string is " << size_s2 << "\n";
cout << " Now the first string will be concatenated with the second
string ";
char* a = strcat(s1,s2);
for(int i = 0; i<MAX; i++)
cout <<a[i];
// system("pause");
return 0;
}
//strcat function to contatenate two strings
char* strcat(char *__s1, const char *__s2)
{
int indexOfs1 = strlen(__s1);
int s2L = strlen(__s2);
cout <<s2L << "\n";
int indexOfs2 = 0;
do{
__s1[indexOfs1] = __s2[indexOfs2];
indexOfs1++;
indexOfs2++;
}while(indexOfs2 < s2L);
return __s1;
}
//Returns length of char array
size_t strlen(const char *__s)
{
int count = 0;
int i;
for (i = 0; __s[i] != '\0'; i++)
count++;
return (count) / sizeof(__s[0]);
}
The behavior you are seeing is a result of the null terminator of __s1 being overwritten by data from __s2 and no new null terminator being appended. The extra characters you are seeing are just random values in RAM that happen to be after the end of your string. To prevent this a NULL character MUST be added at the end of your string.
A working version is as follows:
char* strcar(char *__s1, const char *__s2)
{
//check inputs for NULL
if(__s1 == NULL || __s2 == NULL)
return NULL;
int s1Length = strlen(__s1);
int s2Length = strlen(__s2);
//ensure strings do not overlap in memory
if(!(__s1 + s1Length < __s2 || __s2 + s2Length < __s1))
return NULL;
//append __s2 to __s1
//the "+ 1" here is necessary to copy the NULL from the end of __s2
for(int i = 0; i < s2Length + 1; i++)
result[s1Length + i] = __s2[i];
}
You Need to add a trailing "\0"-char at the end of __s1.
e.g. insert
__s1[indexOfs1] = 0;
before your return-line.

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.

Padding specified number of zeros to a char array

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

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.

"The Debugger has exited due to signal 10" when writing a char* iteration

So I have a program that makes char* stuff lowercase. It does it by iterating through and manipulating the ascii. Now I know there's probably some library for this in c++, but that's not the point - I'm a student trying to get a grasp on char*s and stuff :).
Here's my code:
#include <iostream>
using namespace std;
char* tolower(char* src);
int main (int argc, char * const argv[])
{
char* hello = "Hello, World!\n";
cout << tolower(hello);
return 0;
}
char* tolower(char* src)
{
int ascii;
for (int n = 0; n <= strlen(src); n++)
{
ascii = int(src[n]);
if (ascii >= 65 && ascii <= 90)
{
src[n] = char(ascii+32);
}
}
return src;
}
( this is not for an assignment ;) )
It builds fine, but when I run it it I get a "The Debugger has exited due to signal 10" and Xcode points me to the line: "src[n] = char(ascii+32);"
Thanks!
Mark
Yowsers!
Your "Hello World!" string is what is called a string literal, this means its memory is part of the program and cannot be written to.
You are performing what is called an "in-place" transform, e.g. instead of writing out the lowercase version to a new buffer you are writing to the original destination. Because the destination is a literal and cannot be written to you are getting a crash.
Try this;
char hello[32];
strcpy(hello, "Hello, World!\n");
Also in your for loop, you should use <, not <=. strlen returns the length of a string minus its null terminator, and array indices are zero-based.
As Andrew noted "Hello World\n" in code is a read-only literal. You can either use strcpy to make a modifiable copy, or else try this:
char hello[] = "Hello, World!\n";
This automatically allocates an array on the stack big enough to hold a copy of the literal string and a trailing '\0', and copies the literal into the array.
Also, you can just leave ascii as a char, and use character literals instead of having to know what the numeric value of 'A' is:
char ascii;
for (int n = 0; n < strlen(src); n++)
{
ascii = src[n];
if (ascii >= 'A' && ascii <= 'Z')
{
src[n] = ascii - 'A' + 'a';
}
}
While you're at it, why bother with ascii at all, just use src[n]:
for (int n = 0; n < strlen(src); n++)
{
if (src[n] >= 'A' && src[n] <= 'Z')
{
src[n] -= 'A' - 'a';
}
}
And then, you can take advantage of the fact that in order to determine the length of a c-string, you have to iterate though it anyway, and just combine both together:
for (char *n = src; *n != 0; n++)
if (*n >= 'A' && *n <= 'Z')
*n -= 'A' - 'a';