strstr not working in C++ 4.7 on codeforces - c++

On online compiler this program is giving perfect output on giving input "ABACABA", but on Codeforces tests it is just posting the last line. On debugging I found out that the pointer u is indicating to address 0 when strstr() is used. I am unable to understand why the function is working on other online compiler ,but not on Codeforces.
EDIT: Okay so thanks to #Jeremy Friesner, I found out that it is actually strncpy that is not working properly because now the custom test cases compiler is giving wrong output for 'str'. Still don't know why it should behave differently on two different compilers and what changes should I make.
#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<stdlib.h>
using namespace std;
int main()
{
char *s;
int length=20;
s = (char *) malloc(length*(sizeof(char)));
char c;
int count=0;
while((c=getchar())>='A')
{
if(c<='Z')
{
//cout<<count;
if(length>=count)
{
s = (char *) realloc(s,(length+=10)*sizeof(char));
}
s[count++]=c;
//printf("%p\n",s);
}
else
{
break;
}
}
char *u=s;
int o=1;
//printf("%p\n",s);
while(u)
{
char *str = (char *) malloc(o*sizeof(char));
str = strncpy(str,s,o);
//cout<<str<<endl;
char *t;
u = strstr(s+1,str);
//printf("u %p\n",u);
t=u;
int ct=0;
char *p;
while(t)
{
ct++;
p=t;
t = strstr(t+o,str);
}
ct=ct+1;
//cout<<"here"<<endl;
if(p==(s+count-o))
{
cout<<o<<" "<<ct<<endl;
}
//cout<<ct<<endl;
o++;
}
cout<<count<<" "<<1;
}

As noted in the comments, a principal problem was that you were not null-terminating the string after you read it in, which leads to odd results. Specifically, it leads to you invoking undefined behaviour, which is always a bad thing. The memory allocated by malloc() and the extra memory allocated by realloc() is not guaranteed to be zeroed.
You can fix the problem by adding:
s[count] = '\0';
just before:
char *u = s;
Strictly, you should also check the return values of both malloc() and realloc(). Also, you should not use the idiom:
x = realloc(x, newsize);
If the realloc() fails, you've lost your pointer to the original data, so you've leaked memory. The safe way to work is:
void *space = realloc(x, newsize);
if (space == 0)
…report error etc…
x = space;
x_size = newsize;
There may be other problems; I've not scrutinized the code for every possible issue.

You never put null-termination after the characters you put into s, therefore s does not contain a string. So it causes undefined behaviour to pass it to a function that expects a string, such as strncpy.
Another big problem is your usage of strncpy.
int o=1;
while(u)
{
char *str = (char *) malloc(o*sizeof(char));
str = strncpy(str,s,o);
u = strstr(s+1,str);
The strncpy function does not create a string, if strlen(s) >= o. In this case, the strstr function will just read off the end of the buffer, causing undefined behaviour. (Exactly what happens will depend on your compiler and on what junk was in this piece of memory).
You need to put a null-terminated string into str. Either manually add a null-terminator:
assert(o > 0);
strncpy(str, s, o-1);
str[o-1] = 0;
or use a different function:
snprintf(str, o, "%s", s);
You have to keep in mind that a string is a series of characters followed by a null terminator. Whenever you work with functions that expect strings, it's up to you to make sure that the null terminator is present.
Also be careful with lines like strstr(t+o,str);. If o > strlen(t) this causes undefined behaviour. You've got to do the checking yourself that you do not go outside the bounds of the string.

Related

How to check an empty array returned from a function in C++

I was asked to write a function that accepts a character array, a zero-based start position, and a length.
It should return a character array containing length characters (len) starting with the start character of the input array
#include<iostream>
#include<vector>
#include<iterator>
using namespace std;
char* lengthChar(char c[],int array_len, int start, int len)
{
char* v = new char[len];
if(start < 0 || len > array_len || (start + len - 1) >= array_len){
return NULL;
}
if((start + len) == start)
{
return v;
}
copy(&c[start], &c[len+start], &v[0]);
return v;
}
My question is when I call my function as
char* r = lengthChar(t,3, 1, 0);
Normally based on my implementation, it should return a pointer pointing to an empty array. However, I can't seem to verify this. When I do if(!r[0]), it doesn't detect it. I even did
char s[] = {};
char* tt = &s[0];
if(r[0] == *tt)
Still nothing. The strange thing is when I cout the value of r[0], nothing is printed. So I don't know what actually is return. How do I verify that it is empty?
Don't use if(!r[0]) to check if NULL was returned. You want to compare directly to NULL using if(!r) or if(r == NULL). This will tell you if the string is empty. Doing if(!r[0]) when you return NULL is undefined behavior so you definitely want to make sure the address is valid before you try and access what it points to.
Another thing to note is that in the case that you return NULL, you function has a memory leak. You need to move char* v = new char[len]; to after you decide if you are going to return NULL. You could call delete [] v; in the if statement, but that makes the code more brittle.
There are a few things going on here. Firstly, I would replace that
if((start+len) == start)
with just
if(len == 0) // if(!len) works too
And also note that you don't need to take the address of an index, so
&c[start] is the same thing as c + start
I would read http://www.cplusplus.com/reference/algorithm/copy/ to make sure you understand that the value being passed is an iterator.
But secondly, your char* v = new char[len] statement is invoking undefined behavior. When you call
new char[len];
You're merely telling the compiler that you want to give space to a new character array. Remember that std::cout is a function. It is going to detect a char array as a c string. This means that the char array needs to be null terminated. If it's not, you are truly just invoking undefined behavior because you're reading memory on places that have been allocated but not initialized.
When you call
if(!r[0])
This doesn't really mean anything at all. r[0] is technically initialized, so it is not a nullptr, but it doesn't have any data in it so it is going to evaluate to true with undefined behavior.
Now, if you want to make this more concrete, I would fill the array with zeros
char* v = new char[len];
memset(v, 0, len);
Now your char is a truly "empty" array.
I think it's just a misunderstanding of what an "empty" array actually means.
Finally, don't listen to the guys who say just use std::vector. They're absolutely right, it's better practice, but it's better to understand how those classes work before you pull out the real power of the standard library. Just saying.

C++: How to use new to find store for function return value?

I'm reading the 3rd edition of The C++ Programming Language by Bjarne Stroustrup and attempting to complete all the exercises. I'm not sure how to approach exercise 13 from section 6.6, so I thought I'd turn to Stack Overflow for some insight. Here's the description of the problem:
Write a function cat() that takes two C-style string arguments and
returns a single string that is the concatenation of the arguments.
Use new to find store for the result.
Here's my code thus far, with question marks where I'm not sure what to do:
? cat(char first[], char second[])
{
char current = '';
int i = 0;
while (current != '\0')
{
current = first[i];
// somehow append current to whatever will eventually be returned
i++;
}
current = '';
i = 0;
while (current != '\0')
{
current = second[i];
// somehow append current to whatever will eventually be returned
i++;
}
return ?
}
int main(int argc, char* argv[])
{
char first[] = "Hello, ";
char second[] = "World!";
? = cat(first, second);
return 0;
}
And here are my questions:
How do I use new to find store? Am I expected to do something like std::string* result = new std::string; or should I be using new to create another C-style string somehow?
Related to the previous question, what should I return from cat()? I assume it will need to be a pointer if I must use new. But a pointer to what?
Although the problem doesn't mention using delete to free memory, I know I should because I will have used new to allocate. Should I just delete at the end of main, right before returning?
How do I use new to find store? Am I expected to do something like std::string* result = new std::string; or should I be using new to create another C-style string somehow?
The latter; the method takes C-style strings and nothing in the text suggests that it should return anything else. The prototype of the function should thus be char* cat(char const*, char const*). Of course this is not how you’d normally write functions; manual memory management is completely taboo in modern C++ because it’s so error-prone.
Although the problem doesn't mention using delete to free memory, I know I should because I will have used new to allocate. Should I just delete at the end of main, right before returning?
In this exercise, yes. In the real world, no: like I said above, this is completely taboo. In reality you would return a std::string and not allocate memory using new. If you find yourself manually allocating memory (and assuming it’s for good reason), you’d put that memory not in a raw pointer but a smart pointer – std::unique_ptr or std::shared_ptr.
In a "real" program, yes, you would use std::string. It sounds like this example wants you to use a C string instead.
So maybe something like this:
char * cat(char first[], char second[])
{
char *result = new char[strlen(first) + strlen(second) + 1];
...
Q: How do you "append"?
A: Just write everything in "first" to "result".
As soon as you're done, then continue by writing everything in "second" to result (starting where you left off). When you're done, make sure to append '\0' at the end.
You are supposed to return a C style string, so you can't use std::string (or at least, that's not "in the spirit of the question"). Yes, you should use new to make a C-style string.
You should return the C-style string you generated... So, the pointer to the first character of your newly created string.
Correct, you should delete the result at the end. I expect it may be ignored, as in this particular case, it probably doesn't matter that much - but for completeness/correctness, you should.
Here's some old code I dug up from a project of mine a while back:
char* mergeChar(char* text1, char* text2){
//Find the length of the first text
int alen = 0;
while(text1[alen] != '\0')
alen++;
//Find the length of the second text
int blen = 0;
while(text2[blen] != '\0')
blen++;
//Copy the first text
char* newchar = new char[alen + blen + 1];
for(int a = 0; a < alen; a++){
newchar[a] = text1[a];
}
//Copy the second text
for(int b = 0; b < blen; b++)
newchar[alen + b] = text2[b];
//Null terminate!
newchar[alen + blen] = '\0';
return newchar;
}
Generally, in a 'real' program, you'll be expected to use std::string, though. Make sure you delete[] newchar later!
What the exercise means is to use new in order to allocate memory. "Find store" is phrased weirdly, but in fact that's what it does. You tell it how much store you need, it finds an available block of memory that you can use, and returns its address.
It doesn't look like the exercise wants you to use std::string. It sounds like you need to return a char*. So the function prototype should be:
char* cat(const char first[], const char second[]);
Note the const specifier. It's important so that you'll be able to pass string literals as arguments.
So without giving the code out straight away, what you need to do is determine how big the resulting char* string should be, allocate the required amount using new, copy the two source strings into the newly allocated space, and return it.
Note that you normally don't do this kind of memory management manually in C++ (you use std::string instead), but it's still important to know about it, which is why the reason for this exercise.
It seems like you need to use new to allocate memory for a string, and then return the pointer. Therefore the return type of cat would be `char*.
You could do do something like this:
int n = 0;
int k = 0;
//also can use strlen
while( first[n] != '\0' )
n ++ ;
while( second[k] != '\0' )
k ++ ;
//now, the allocation
char* joint = new char[n+k+1]; //+1 for a '\0'
//and for example memcpy for joining
memcpy(joint, first, n );
memcpy(joint+n, second, k+1); //also copying the null
return joint;
It is telling you to do this the C way pretty much:
#include <cstring>
char *cat (const char *s1, const char *s2)
{
// Learn to explore your library a bit, and
// you'll see that there is no need for a loop
// to determine the lengths. Anything C string
// related is in <cstring>.
//
size_t len_s1 = std::strlen(s1);
size_t len_s2 = std::strlen(s2);
char *dst;
// You have the lengths.
// Now use `new` to allocate storage for dst.
/*
* There's a faster way to copy C strings
* than looping, especially when you
* know the lengths...
*
* Use a reference to determine what functions
* in <cstring> COPY values.
* Add code before the return statement to
* do this, and you will have your answer.
*
* Note: remember that C strings are zero
* terminated!
*/
return dst;
}
Don't forget to use the correct operator when you go to free the memory allocated. Otherwise you'll have a memory leak.
Happy coding! :-)

atof and non-null terminated character array

using namespace std;
int main(int argc, char *argv[]) {
char c[] = {'0','.','5'};
//char c[] = "0.5";
float f = atof(c);
cout << f*10;
if(c[3] != '\0')
{
cout << "YES";
}
}
OUTPUT: 5YES
Does atof work with non-null terminated character arrays too? If so, how does it know where to stop?
Does atof work with non-null terminated character arrays too?
No, it doesn't. std::atof requires a null-terminated string in input. Failing to satisfy this precondition is Undefined Behavior.
Undefined Behavior means that anything could happen, including the program seeming to work fine. What is happening here is that by chance you have a byte in memory right after the last element of your array which cannot be interpreted as part of the representation of a floating-point number, which is why your implementation of std::atof stops. But that's something that cannot be relied upon.
You should fix your program this way:
char c[] = {'0', '.', '5', '\0'};
// ^^^^
No, atof does not work with non-null terminated arrays: it stops whenever it discovers zero after the end of the array that you pass in. Passing an array without termination is undefined behavior, because it leads the function to read past the end of the array. In your example, the function has likely accessed bytes that you have allocated to f (although there is no certainty there, because f does not need to follow c[] in memory).
char c[] = {'0','.','5'};
char d[] = {'6','7','8'};
float f = atof(c); // << Undefined behavior!!!
float g = atof(d); // << Undefined behavior!!!
cout << f*10;
The above prints 5.678, pointing out the fact that a read past the end of the array has been made.
No... atof() requires a null terminated string.
If you have a string you need to convert that is not null terminated, you could try copying it into a target buffer based on the value of each char being a valid digit. Something to the effect of...
char buff[64] = { 0 };
for( int i = 0; i < sizeof( buff )-1; i++ )
{
char input = input_string[i];
if( isdigit( input ) || input == '-' || input == '.' )
buff[i] = input;
else
break;
}
double result = atof( buff );
From the description of the atof() function on MSDN (probably applies to other compilers) :
The function stops reading the input string at the first character that it cannot recognize as part of a number. This character may be the null character ('\0' or L'\0') terminating the string.
It must either be 0 terminated or the text must contain characters that do not belong to the number.
std::string already terminate a string with NULL!
So why not
std::string number = "7.6";
double temp = ::atof(number.c_str());
You can also do it with the stringstream or boost::lexical_cast
http://www.boost.org/doc/libs/1_53_0/doc/html/boost_lexical_cast.html
http://www.cplusplus.com/reference/sstream/stringstream/
Since C++11, we have std::stof. By replacing atof with std::stof, it would be easier to handle.
I made a handy wrapper if you always pass a known size of char array.
Live Demo
#include <fmt/core.h>
#include <type_traits>
#include <iostream>
// SFINAE fallback
template<typename T, typename =
std::enable_if< std::is_pointer<T>::value >
>
float charArrayToFloat(const T arr){ // Fall back for user friendly compiler errors
static_assert(false == std::is_pointer<T>::value, "`charArrayToFloat()` dosen't allow conversion from pointer!");
return -1;
}
// Valid for both null or non-null-terminated char array
template<size_t sz>
float charArrayToFloat(const char(&arr)[sz]){
// It doesn't matter whether it's null terminated or not
std::string str(arr, sz);
return std::stof(str);
}
int main() {
char number[4] = {'0','.','4','2'};
float ret = charArrayToFloat(number);
fmt::print("The answer is {}. ", ret);
return 0;
}
Output: The answer is 0.42.
Does atof work with non-null terminated character arrays too?
No, this function expects a pointer to a null terminated string. Failing to do so, say for example by passing a pointer to a non-null terminated string(or a non-null terminated character array) is undefined behavior.
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior.
So the output that you're seeing(maybe seeing) is a result of undefined behavior. And as i said don't rely on the output of a program that has UB. The program may just crash.
So the first step to make the program correct would be to remove UB. Then and only then you can start reasoning about the output of the program.
1For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program.

C++ error - returning a char array

Consider the following code:
char CeaserCrypt(char str[256],int key)
{
char encrypted[256],encryptedChar;
int currentAsci;
encrypted[0] = '\0';
for(int i = 0; i < strlen(str); i++)
{
currentAsci = (int)str[i];
encryptedChar = (char)(currentAsci+key);
encrypted[i] = encryptedChar;
}
return encrypted;
}
Visual Studio 2010 gives an error because the function returns an array. What should I do?
My friend told me to change the signature to void CeaserCrypt(char str[256], char encrypted[256], int key). But I don't think that is correct. How can I get rid of the compile error?
The return type should be char * but this'll only add another problem.
encrypted is "allocated" on the stack of CeaserCrypt and might not be valid when the function returns. Since encrypted would have the same length as the input, do:
int len = strlen(str);
char *encrypted = (char *) malloc(len+1);
encrypted[len] = '\0';
for (int i = 0; i < len; i++) {
// ...
}
Don't forget to deallocate the buffer later, though (with free()).
EDIT: #Yosy: don't feel obliged to just copy/paste. Use this as a pointer to improve your coding practice. Also, to satisfy criticizers: pass an already allocated pointer to your encryption routine using the above example.
It wants you to return a char* rather than a char. Regardless, you shouldn't be returning a reference or a pointer to something you've created on the stack. Things allocated on the stack have a lifetime that corresponds with their scope. After the scope ends, those stack variables are allowed to go away.
Return a std::vector instead of an array.
std::vector<char> CeaserCrypt(char str[256],int key)
{
std::vector<char> encrypted(256);
char encryptedChar;
int currentAsci;
encrypted[0] = '\0';
for(int i = 0; i < strlen(str); ++i)
{
currentAsci = (int)str[i];
encryptedChar = (char)(currentAsci+key);
encrypted[i] = encryptedChar;
}
return encrypted;
}
There's another subtle problem there though: you're casting an integer to a character value. The max size of an int is much larger than a char, so your cast may truncate the value.
Since you're using C++ you could just use an std::string instead. But otherwise, what your friend suggested is probably best.
There are a few problems here. First up:
char CeaserCrypt(char str[256],int key)
As others have pointed out, your return type is incorrect. You cannot return in a single character an entire array. You could return char* but this returns a pointer to an array which will be allocated locally on the stack, and so be invalid once the stack frame is removed (after the function, basically). In English, you'll be accessing that memory address but who knows what's going to be there...
As your friend suggested, a better signature would be:
void CeaserCrypt(char* encrypted, const char str*, const size_t length ,int key)
I've added a few things - a size_t length so you can process any length string. This way, the size of str can be defined as needed. Just make sure char* encrypted is of the same size.
Then you can do:
for(int i = 0; i < length; i++)
{
// ...
For this to work your caller is going to need to have allocated appropriately-sized buffers of the same length, whose length you must pass in in the length parameter. Look up malloc for C. If C++, use a std::string.
If you need C compatibility make encrypted string function argument.
If not, than use C++ std::string instead C style string.
And also In your code encrypted string isn't ending with '\0'
The problem with the original code is that you are trying to return a char* pointer (to which your local array decayed) from a function that is prototyped as one returning a char. A function cannot return arrays in C, nor in C++.
Your friend probably suggested that you change the function in such a way, that the caller is responsible for allocation the required buffer.
Do note, that the following prototypes are completely equal. You can't pass an array as a parameter to normal function.
int func(char array[256]);
int func(char* array);
OTOH, you should (if you can!) decide the language which you use. Better version of the original (in C++).
std::vector<unsigned char> CeaserCrypt(const std::string& str, const int key)
{
std::vector<unsigned char> encrypted(str.begin(), str.end());
for (std::vector<unsigned char>::iterator iter = vec.begin();
iter != vec.end(); ++iter) {
*iter += key;
}
return vec;
}
Do note that overflowing a signed integer causes undefined behavior.
VS2010 is "yelling" at you because you are trying to return a value that is allocated on the stack, and is no longer valid once your function call returns.
You have two choices: 1) Allocate memory on the heap inside your function, or 2) use memory provided to you by the caller. Number 2 is what your friend in suggesting and is a very good way to do things.
For 1, you need to call malloc() or new depending on whether you are working in C or C++. In C, I'd have the following:
char* encrypted = malloc(256 * sizeof(char));
For C++, if you don't want to use a string, try
char* encrypted = new char[256];
Edit: facepalm Sorry about the C noise, I should have looked at the question more closely and realized you are working in C++.
You can just do your Ceaser cipher in place, no need to pass arrays in and out.
char * CeaserCrypt(char str[256], int key)
{
for(unsigned i = 0; i < strlen(str); i++)
{
str[i] += key;
}
return str;
}
As a further simplification, skip the return value.
void CeaserCrypt(char str[256], int key)
{
for(unsigned i = 0; i < strlen(str); i++)
{
str[i] += key;
}
}
well what you're returning isn't a char, but a char array. Try changing the return type to char*(char* and a char array are ostensibly the same thing for the compiler)
char* CeaserCrypt(char str[256],int key)
EDIT: as said in other posts, the encrypted array will probably not be valid after the function call. you could always do a new[] declaration for encrypted, remembering to delete[] it later on.

C++ Allocated Memory Problem

It has been a long time since I have programmed in C++, but I recently wrote a little C++ function and am having a little bit of trouble. The function returns a struct, Result, that have some strings in it. I thought I allocated memory for the strings, but jsonResult is sometimes partially overwritten.
//The structs
struct Interp {
int score;
char* sentence;
char* jsonResult;
};
struct Result {
int resultCode;
char* errorMessage;
Interp interp;
};
...
//Inside the function
Result result;
//Store decode
const char* jsonResult,* sentence;
if (result.resultCode == -1)
{
LVInterpretation interp = port.GetInterpretation(voiceChannel, 0);
result.interp.score = interp.Score();
sentence = interp.InputSentence();
jsonResult = interp.ResultData().Print(SI_FORMAT_ECMA);
}
//Allocate memory for strings
result.interp.jsonResult = new char[strlen(jsonResult) + 1];
strcpy(result.interp.jsonResult, jsonResult);
result.interp.sentence = new char[strlen(sentence) + 1];
strcpy(result.interp.sentence, sentence);
result.errorMessage = new char[strlen(errorMessage) + 1];
strcpy(result.errorMessage, errorMessage);
return result;
Other info:
I am observing all of this behind the python binding that I wrote, using ctypes. Don't think that is really effecting anything though.
Use std::string. You won't regret it.
I'd put money on your problem being in here:
jsonResult = interp.ResultData().Print(SI_FORMAT_ECMA);
Who 'owns' the char* array returned by Print()? Maybe it's attempting to return a pointer to memory that's out of scope???
example:
char* badFunction(void)
{
char test[100];
strcpy(test,"This is really clever"); // oh, yeah?
return test; // returns pointer to data that's out of scope
}
One other thing. Assign null pointers to sentence, jsonResult, etc when you declare them. Otherwise you could end up strcpy()ing uninitialized data,
Couple of things:
What does "partially overwritten" mean? How do you know this? i.e. what is your expected output vs. what you see?
It's not really clear how result.resultCode is set to -1 (or if it is at all), and if it is set, how does the memory get allocated in interp.InputSentence() and interp.ResultData().Print(SI_FORMAT_ECMA)? I'd suggest that your problem lies there
The rest of the code should work as long as jsonResult and sentence contain valid null terminated strings.